Giter VIP home page Giter VIP logo

meteor-rest's Introduction

REST for Meteor Build Status

A set of packages that makes it easy to make your Meteor app's data accessible over HTTP. Easily integrate your Meteor backend into a native mobile app or query your data from your Rails or PHP app.

Packages

Planned

  • simple:rest-accounts-facebook, etc - OAuth login packages for HTTP
  • Static file management, authentication
  • Integration with Restivus for custom API needs

meteor-rest's People

Contributors

alanning avatar aldeed avatar atablash avatar bkuster avatar kahmali avatar kaoskeya avatar nooitaf avatar serkandurusoy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

meteor-rest's Issues

OAuth +1

Great package! Completing the login aspect / OAuth will be super!

Refactor change logs

  • Break change logs into separate CHANGELOG.md files for each package
  • Use a standard format for change logs: http://keepachangelog.com/
  • Link to each change log from corresponding README
  • Update contributing guidelines with any new info?

Collections methods insert/update/delete should not be available

I'm new to meteor and so maybe I have done something wrong/stupid ...

I have followed the tutorial on meteor.com/try, modify it a little (basically I have moved the code inside a local package to simulate to have a larger app) and then I have tried to insert meteor-rest package (simple:rest).

Below you can find the results of calling /publications/api-routes. I have removed insecure and autopublish so I expect to don't have API to insert/update/delete collections. I'm right?

Why I have for example /methods/tasks/insert or /methods/meteor_accounts_loginServiceConfiguration/insert?
How can I remove it?

{
  "api-routes": [
    {
      "_id": "get /publications/api-routes",
      "method": "get",
      "path": "/publications/api-routes"
    },
    {
      "_id": "options /methods/tasks/insert",
      "method": "options",
      "path": "/methods/tasks/insert"
    },
    {
      "_id": "post /methods/tasks/insert",
      "method": "post",
      "path": "/methods/tasks/insert"
    },
    {
      "_id": "options /methods/tasks/update",
      "method": "options",
      "path": "/methods/tasks/update"
    },
    {
      "_id": "post /methods/tasks/update",
      "method": "post",
      "path": "/methods/tasks/update"
    },
    {
      "_id": "options /methods/tasks/remove",
      "method": "options",
      "path": "/methods/tasks/remove"
    },
    {
      "_id": "post /methods/tasks/remove",
      "method": "post",
      "path": "/methods/tasks/remove"
    },
    {
      "_id": "options /methods/addTask",
      "method": "options",
      "path": "/methods/addTask"
    },
    {
      "_id": "post /methods/addTask",
      "method": "post",
      "path": "/methods/addTask"
    },
    {
      "_id": "options /methods/deleteTask",
      "method": "options",
      "path": "/methods/deleteTask"
    },
    {
      "_id": "post /methods/deleteTask",
      "method": "post",
      "path": "/methods/deleteTask"
    },
    {
      "_id": "options /methods/setChecked",
      "method": "options",
      "path": "/methods/setChecked"
    },
    {
      "_id": "post /methods/setChecked",
      "method": "post",
      "path": "/methods/setChecked"
    },
    {
      "_id": "options /methods/setPrivate",
      "method": "options",
      "path": "/methods/setPrivate"
    },
    {
      "_id": "post /methods/setPrivate",
      "method": "post",
      "path": "/methods/setPrivate"
    },
    {
      "_id": "get /publications/tasks",
      "method": "get",
      "path": "/publications/tasks"
    },
    {
      "_id": "options /methods/meteor_accounts_loginServiceConfiguration/insert",
      "method": "options",
      "path": "/methods/meteor_accounts_loginServiceConfiguration/insert"
    },
    {
      "_id": "post /methods/meteor_accounts_loginServiceConfiguration/insert",
      "method": "post",
      "path": "/methods/meteor_accounts_loginServiceConfiguration/insert"
    },
    {
      "_id": "options /methods/meteor_accounts_loginServiceConfiguration/update",
      "method": "options",
      "path": "/methods/meteor_accounts_loginServiceConfiguration/update"
    },
    {
      "_id": "post /methods/meteor_accounts_loginServiceConfiguration/update",
      "method": "post",
      "path": "/methods/meteor_accounts_loginServiceConfiguration/update"
    },
    {
      "_id": "options /methods/meteor_accounts_loginServiceConfiguration/remove",
      "method": "options",
      "path": "/methods/meteor_accounts_loginServiceConfiguration/remove"
    },
    {
      "_id": "post /methods/meteor_accounts_loginServiceConfiguration/remove",
      "method": "post",
      "path": "/methods/meteor_accounts_loginServiceConfiguration/remove"
    },
    {
      "_id": "options /methods/meteor_oauth_pendingCredentials/insert",
      "method": "options",
      "path": "/methods/meteor_oauth_pendingCredentials/insert"
    },
    {
      "_id": "post /methods/meteor_oauth_pendingCredentials/insert",
      "method": "post",
      "path": "/methods/meteor_oauth_pendingCredentials/insert"
    },
    {
      "_id": "options /methods/meteor_oauth_pendingCredentials/update",
      "method": "options",
      "path": "/methods/meteor_oauth_pendingCredentials/update"
    },
    {
      "_id": "post /methods/meteor_oauth_pendingCredentials/update",
      "method": "post",
      "path": "/methods/meteor_oauth_pendingCredentials/update"
    },
    {
      "_id": "options /methods/meteor_oauth_pendingCredentials/remove",
      "method": "options",
      "path": "/methods/meteor_oauth_pendingCredentials/remove"
    },
    {
      "_id": "post /methods/meteor_oauth_pendingCredentials/remove",
      "method": "post",
      "path": "/methods/meteor_oauth_pendingCredentials/remove"
    }
  ]
}

If I try to actually call these methods I receive this error:
Internal server error in methods/tasks/insert [TypeError: Cannot convert null to object] TypeError: Cannot convert null to object

You can find my full code here.

thanks!

Setup linter

  • Convert all strings to single-quotes for consistency

See #27

Update docs with info on pluggable auth middleware

Auth in simple:rest is now pluggable.

  • Add simple:rest-accounts-bearer-token to list of packages in root README
  • Update change log
  • Update docs for simple:rest to include detailed info on creating auth middleware (and maybe just middleware in general)

[json-routes] Make `method` param in JsonRoutes.add() case-insensitive

Right now, the method param in the first arg of JsonRoutes.add() is case-sensitive, and must be passed as lowercase. Since it is very common to see these capitalized in the wild, we should accept any capitalization, and just String.toLowercase() whatever is passed.

So both

JsonRoutes.add('get', 'widget', function (req, res, next) {});

and

JsonRoutes.add('GET', 'widget', function (req, res, next) {});

would work.

If this is an acceptable change, I can put together a quick PR for it.

[json-routes] Accept dictionary of headers in sendResult() and sendError()

It seems inconsistent to allow all response information to be passed into these methods except for the headers, when there is nothing unique about the headers. For those, a user has to pass the dictionary to JsonRoutes.setResponseHeaders(), which stores the headers in an object until they are later added to the response from within the sendResult() method](https://github.com/stubailo/meteor-rest/blob/devel/packages/json-routes/json-routes.js#L116), which calls a method [setHeaders()` to iterate over the headers dictionary and set each header in the response.

If that sounds kind of convoluted, it's because it is. I think it would make a lot more sense to just pass the dictionary of headers directly to sendResult() and sendError. Then the same setHeaders() function can be used to set those response headers.

We can still provide a method for endpoints or middleware to contribute to the headers if that's desirable.

published collection with MONGO idGeneration returns "Match failed" 400 error

The /publications/ url returns fine with the default meteor collection, but when I add the {idGeneration: 'MONGO'} option when creating the Collection, the url returns the following:
{
"error": 400,
"reason": "Match failed"
}
The collection example is:
Sensors = new Mongo.Collection('sensors', {idGeneration: 'MONGO'});
Meteor.publish('sensors', function() { return Sensors.find(); });
and the url is:
http://localhost:3000/publications/sensors

Looks like somehow the code did not handle the Mongo ObjectID correctly. any workaround or fix?

Add CORS support

    JsonRoutes.setResponseHeaders({
      "Cache-Control": "no-store",
      "Pragma": "no-cache",
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "GET, PUT, POST, DELETE, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With"
    });

I put the code above inside startup block, and it has no effect on setting the cors headers. Calls from outside the app are still blocked because `Access-Control-Allow-Origin' header is missing.

Add built-in support for versioning

Here are my rough thoughts regarding versioning.

GOALS:

  • HTTP and DDP use same version checking and same input/output migrations
  • Do not recommend versions in the path, but don't prohibit them. (Make more sense when trying to keep HTTP and DDP methods the same.)
  • Assume latest version
  • Allow REST requests to specify API version in multiple typical ways. Provide way for DDP request to specify API version, too.

IDEAS:

  • Regardless of whether DDP or HTTP, this.apiVersion will be set in the methods if a specific version is requested. For HTTP, middleware will do this based on checking "api-version" header or "v" query string param. (Does DDP spec provide a way to specify version?)
  • We do not care what format versions take. Could be semver, a date, etc. As long as app code understands what is meant.
  • If this.apiVersion is not set, assume latest version.
  • Provide simple way to convert input/output as method/pub options.

Example of last point:

Meteor.publish("widgets", function (all) {
  if (all) {
    return Widgets.find();
  }

  // could also check this.apiVersion in here for advanced cases

  return Widgets.find({userId: this.userId});
}, {
  convert: {
    in: function (apiVersion, args) {
      // In version 1, no args were accepted and "all" was the default
      if (apiVersion === 1) {
        return [true];
      }

      return args;
    },
    out: function (apiVersion, result) {
      // In version 1, property was called "foo_bar" instead of "fooBar"
      if (apiVersion === 1 && _.has(result, 'fooBar')) {
        result.foo_bar = result.fooBar;
        delete result.fooBar;
      }

      return result;
    }
  }
});

Deduplicate error handling code from rest-accounts-password and rest

There is code in two places that does the same thing:

function convertErrorToJson(err) {
if (err.sanitizedError) {
var sE = err.sanitizedError;
return {
error: sE.error,
reason: sE.reason
};
} else if (err.errorType === "Meteor.Error") {
return {
error: err.error,
reason: err.reason
};
} else {
return {
error: "internal-server-error",
reason: "Internal server error."
};
}
}

function catchAndReportErrors(url, res, func) {
try {
return func();
} catch (error) {
var errorJson;
if (error instanceof Meteor.Error) {
errorJson = {
error: error.error,
reason: error.reason,
details: error.details
};
} else if (error.sanitizedError instanceof Meteor.Error) {
errorJson = {
error: error.sanitizedError.error,
reason: error.sanitizedError.reason,
details: error.sanitizedError.details
};
} else {
console.log("Internal server error in " + url, error, error.stack);
errorJson = {
error: "internal-server-error",
reason: "Internal server error"
};
}
var code = 500;
if (_.isNumber(errorJson.error)) {
code = errorJson.error;
}
JsonRoutes.sendResult(res, code, errorJson);
}
}

Set devel as the default branch?

This seems like a fairly standard convention (as proposed in the Contributing Guidelines in ab5d357). Make all PRs to devel and then only push published code to master. I went ahead and created a devel branch, in case we decide to go that route.

Customise user not found text in simple:rest-accounts-password

Now simple:rest-accounts-password respond with "not-found", "User with that username or email address not found." when user not found, and 403, "Incorrect password" when password didn't match.
This is not good from a security standpoint. I made a quick hack to local copy of simple:rest-accounts-password, so now it respond "Login failed".
But maybe it will be better to make message customisable?

Add contributing guidelines

It's always best to have these written down somewhere, plus GitHub integrates them nicely when users open new issues or make pull requests. This is also a good place to layout any coding conventions to keep things consistent. We can try to find a good resource for one that's already well written, or use the one from Restivus as a starting point (I do plan to update that one soon with all that I've learned thus far). It should help streamline the contributing process a bit.

EDIT: Looks like you've already started something here: https://github.com/stubailo/meteor-rest#contributing. It just needs to be moved into a CONTRIBUTING.md file and GitHub will recognize and integrate it.

  • Move all contributing guidelines to CONTRIBUTING.md
  • Improve guidelines (add as much useful information as humanly possible)

Release new version?

Quick question: There is a list of unreleased functions in the readme of the json-routes package. Do you have a date or approximation when this is going to be released?

Match error: Missing key 'username'

This error occurs regardless of whether I include username or email key. I am using FlowRouter, simple:rest, and simple:rest-accounts-password. Let me attach a screenshot too just to make sure if I am making the POST request correctly.

screen shot 2015-09-19 at 4 22 44 pm

Error in login:  { [Error: Match error: Missing key 'username']
  path: '',
  sanitizedError: 
   { [Error: Match failed [400]]
     error: 400,
     reason: 'Match failed',
     details: undefined,
     message: 'Match failed [400]',
     errorType: 'Meteor.Error' },
  errorType: 'Match.Error' }

Content-Type required when using CURL?

Hi, just wanted to note that the content type is required also when calling through curl, I think this should be the default content type instead of forcing us to pass it along with the curl request.

Allow adding error hooks

In JsonRoutes.add, we catch errors and respond. There should be a way to add additional error hooks, for example to log all restpoint errors somewhere.

The easiest solution in short term would be to make a way to add hooks, and then call them, passing them the error, in sendError.

Use DELETE/POST/PUT/PATCH

POST /methods/<collection-name>/insert
POST /methods/<collection-name>/update
POST /methods/<collection-name>/remove

would in rest language make more sense to use:

POST /api/<collection-name>
PUT/PATCH /api/<collection-name>
DELETE /api/<collection-name>

Missing commit on devel

What happened to this commit on the latest version of devel? I have work based off of it in a feature branch. I suppose I'll get to learn something new about git to resolve it, which certainly isn't the worst thing in the world.

Allow middleware package to parse tokens and set userId

Here is my suggestion for how to refactor auth token checking and method/pub userId:

Step 1

Create a package that attaches middleware to JsonRoutes.middleWare. The middleware will parse the auth token (or any other type of auth) if it should, and set req.userId.

JsonRoutes.middleWare.use(function (req, res, next) {
  var userId = getUserIdFromRequest(req);
  if (userId) {
    req.userId = userId;
  }
  next();
});

For example, pkg name might be meteor-accounts-token-middleware.

Step 2

The rest-accounts-password package (and any future FB, etc.) can depend on this package. It is better to have the related rest login pkg depend on it than to have simple:rest depend on it.

Step 3

In simple:rest, remove the getUserIdFromRequest code and instead do var userId = req.userId || null.

Net Effect

If you use rest-accounts-password to log in and then supply token to method/pub calls, this.userId will be set correctly. That is no change from now, BUT it allows me and others to very easily drop in our own auth middleware that will set userId based on a different login/token scenario.

DDP methods should just match 1:1 on HTTP?

Meteor.publish("widgets-above-index", function (index) {
  return Widgets.find({index: {$gt: parseInt(index, 10)}});
}, {
  url: "widgets-with-index-above/:0"
});

Should be:

Meteor.publish("widgets-above-index", function (index /*, args */) {
  return Widgets.find({index: {$gt: parseInt(index, 10)}});
});

args is named arguments, its put last after positioned arguments

Deprecation warnings

I get these warnings in the terminal when using json-routes:

connect.multipart() will be removed in connect 3.0
visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
connect.limit() will be removed in connect 3.0

Everything works fine, though.

Add option for token refresh

When authenticating it should return:

{
  access_token: '',
  expires_in: 10, // Sec
  refresh_token: '' // Use this to refresh token login
}

add get method in meteor method

How to use meteor method to work with get request?

I don't want to use meteor publish for get request since I want to provide custom error when there is an issue. I'm creating method like this.

Meteor.method('notes', function() {
  if (this.userId) {
    var notes = Notes.find({userId: this.userId}).fetch();
    return {status: 'success', data: notes};
  } else {
    return {status: 'fail', reason: 'unauthorized access'};
  }
}, {
  url: 'api/v1/notes'
});

and from the api-routes I can see the below.

{
  _id: "/api/v1/notes",
  methods: [
   "options",
   "post"
  ],
  path: "/api/v1/notes"
},

How can I remove the post and add get in the methods array?

How to prevent meteor publish not automatically exposed as apis

There should be an option when publishing collections to not expose them as apis, same thing for methods.

from meteor publish

{
  _id: "/notes",
  methods: [
    "options",
    "post"
  ],
  path: "/notes"
},
{
  _id: "/notes/:_id",
  methods: [
    "options",
    "patch",
    "options",
    "delete"
  ],
  path: "/notes/:_id"
},

from meteor method

{
  _id: "/api/v1/notes",
  methods: [
    "options",
    "post"
  ],
  path: "/api/v1/notes"
},

it's actually creating a duplicate api endpoint that I don't want to expose.

Similarly the methods also should be able to prevented to expose.

from meteor methods

{
  _id: "/methods/addnote",
  methods: [
    "options",
    "post"
  ],
  path: "/methods/addnote"
},

from meteor method

{
  _id: "/api/v1/addnote",
  methods: [
    "options",
    "post"
  ],
  path: "/api/v1/addnote"
}

it's creating duplicate apis with multiple endpoints.

this.userId is null in collection2 autoValue when calling method using POST request.

I'm using autoValue in one of collections (collection2), where i call this.userId.
When i use Meteor.call (or ddpclient.call in node.js client) all working perfectly.
But when i call this method using post request to http://localhost:3000/methods/, i get error: 400, reason: 'User is required'. And this.userId in autoValue is null.

Is it normal behaviour and i need to set userId in method and check isFromTrustedCode in autoValue?

simple:rest 1.0 release

I don't think we are quite ready for 1.0 yet - there is a lot to figure out around error handling, configuration, documentation, etc. But we should start tracking what will go in the next release.

  • Merge bearer token middleware #40
  • Merge error handling #39
  • Merge error middleware #43
  • Document middleware system
  • Update version numbers for all packages
  • Figure out if there are any breaking changes
  • Update documentation in general

using numtel:mysql with simple:rest

Great stuff with this simple:rest package. Thank you very much.
Anybody else tried using numtel:mysql with this package?

I am using it but I'm getting stuck with the following errors:

I20150921-16:08:50.683(10)? Internal server error in publications/locations [TypeError: Object #<LiveMysqlSelect> has no method 'fetch'] TypeError: Object #<LiveMysqlSelect> has no method 'fetch'
I20150921-16:08:50.685(10)?     at httpPublishCursor (packages/simple:rest/rest.js:161:1)
I20150921-16:08:50.685(10)?     at packages/simple:rest/rest.js:44:1
I20150921-16:08:50.685(10)?     at catchAndReportErrors (packages/simple:rest/rest.js:241:1)
I20150921-16:08:50.685(10)?     at packages/simple:rest/rest.js:25:1
I20150921-16:08:50.685(10)?     at packages/simple:json-routes/json-routes.js:45:1

Any ideas?

The (redacted) code below:

Locations = new MysqlSubscription('locations');

var liveDb = new LiveMysql({
/*...*/
});

Meteor.publish('locations', function () {
  return liveDb.select(
    'select * from channel', [{
      table: 'channel'
    }]
  );
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.