cluster0:http-methods

v0.0.55Published 3 weeks ago

forked from cfs:http-methods Build Status

why fork? remove embedded cors handler res.setHeader("Access-Control-Allow-Origin", "http://meteor.local";)

Add server-side methods to the HTTP object your app. It's a server-side package only - no client simulations added.

Usage

The HTTP object gets a methods method:

1  HTTP.methods({
2    'list': function() {
3      return '<b>Default content type is text/html</b>';
4    }
5  });

Methods scope

The methods scope contains different kinds of inputs. We can also get user details if logged in.

  • this.userId - the user whose id and token was used to run this method, if set/found
  • this.method - GET, POST, PUT, DELETE
  • this.query - query params ?token=1&id=2 -> { token: 1, id: 2 }
  • this.params - set params /foo/:name/test/:id -> { name: '', id: '' }
  • this.userAgent - get the user agent string set in the request header
  • this.requestHeaders - request headers object
  • this.setUserId(id) - option for setting the this.userId
  • this.isSimulation - always false on the server
  • this.unblock - not implemented
  • this.setContentType('text/html') - set the content type in header, defaults to text/html
  • this.addHeader('Content-Disposition', 'attachment; filename="name.ext"')
  • this.setStatusCode(200) - set the status code in the response header
  • createReadStream - if a request, then get the read stream
  • createWriteStream - if you want to stream data to the client
  • Error - when streaming we have to be able to send error and close connection
  • this.request The original request object

Passing data via header

From the client:

1  HTTP.post('list', {
2    data: { foo: 'bar' }
3  }, function(err, result) {
4    console.log('Content: ' + result.content + ' === "Hello"');
5  });

HTTP Server method:

1  HTTP.methods({
2    'list': function(data) {
3      if (data.foo === 'bar') {
4        /* data we pass via the header is parsed by EJSON.parse
5        If not able, then it returns the raw data instead */
6      }
7      return 'Hello';
8    }
9  });

Parameters

The method name or URL can be used to pass parameters to the method. The parameters are available on the server under this.params:

Client

1  HTTP.post('/items/12/emails/5', function(err, result) {
2    console.log('Got back: ' + result.content);
3  });

Server

1  HTTP.methods({
2    '/items/:itemId/emails/:emailId': function() {
3      // this.params.itemId === '12'
4      // this.params.emailId === '5'
5    }
6  });

Extended usage

The HTTP.methods normally takes a function, but it can be set to an object for fine-grained handling.

Example:

1  HTTP.methods({
2    '/hello': {
3      get: function(data) {},
4      // post: function(data) {},
5      // put: function(data) {},
6      // delete: function(data) {},
7      // options: function() {
8      //   // Example of a simple options function
9      //   this.setStatusCode(200);
10      //   this.addHeader('Accept', 'POST,PUT');
11      //    // The options for this restpoint
12      //    var options = {
13      //      POST: {
14      //        description: 'Create an issue',
15      //        parameters: {
16      //          title: {
17      //            type: 'string',
18      //            description: 'Issue title'
19      //          }
20      //        }
21      //       }
22      //    };
23      //    // Print the options in pretty json
24      //    return JSON.stringify(options, null, '\t');
25      //  },
26      //  stream: true // flag whether to allow stream handling in the request
27    }
28  });

In this example the mounted http rest point will only support the get method

Example:

1  HTTP.methods({
2    '/hello': {
3      method: function(data) {},
4    }
5  });

In this example all methods get, put, post, delete will use the same function - This would be equal to setting the function directly on the http mount point

Authentication

The client needs the access_token to login in HTTP methods. One could create a HTTP login/logout method for allowing pure external access

Client

1  HTTP.post('/hello', {
2    params: {
3      token: Accounts && Accounts._storedLoginToken()
4    }
5  }, function(err, result) {
6    console.log('Got back: ' + result.content);
7  });

Server

1  'hello': function(data) {
2    if (this.userId) {
3      var user = Meteor.users.findOne({ _id: this.userId });
4      return 'Hello ' + (user && user.username || user && user.emails[0].address || 'user');
5    } else {
6      this.setStatusCode(401); // Unauthorized
7    }
8  }

Using custom authentication

It's possible to make your own function to set the userId - not using the built-in token pattern.

1  // My auth will return the userId
2  var myAuth = function() {
3    // Read the token from '/hello?token=5'
4    var userToken = self.query.token;
5    // Check the userToken before adding it to the db query
6    // Set the this.userId
7    if (userToken) {
8      var user = Meteor.users.findOne({ 'services.resume.loginTokens.token': userToken });
9
10      // Set the userId in the scope
11      return user && user._id;
12    }  
13  };
14
15  HTTP.methods({
16    '/hello': {
17      auth: myAuth,
18      method: function(data) {
19        // this.userId is set by myAuth
20        if (this.userId) { /**/ } else { /**/ }
21      }
22    }
23  });

The above resembles the builtin auth handler

Security

When buffering data instead of streaming we set the buffer limit to 5mb - This can be changed on the fly:

1  // Set the max data length
2  // 5mb = 5 * 1024 * 1024 = 5242880;
3  HTTP.methodsMaxDataLength = 5242880;

Login and logout (TODO)

These operations are not currently supported for off Meteor use - there are some security considerations.

basic-auth is broadly supported, but:

  • password should not be sent in clear text - hash with base64?
  • should be used on https connections
  • Its difficult / impossible to logout a user?

token the current access_token seems to be a better solution. Better control and options to logout users. But calling the initial login method still requires:

  • hashing of password
  • use https

HTTP Client-side usage

If you want to use the HTTP client-side functionality and find yourself having a hard time viewing all available options; these can be found on https://docs.meteor.com/#/full/http.