Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for declaring status code defaults and custom http headers #218

Merged
merged 4 commits into from
Jun 23, 2015

Conversation

ritch
Copy link
Member

@ritch ritch commented Jun 16, 2015

/to @bajtos
/cc @raymondfeng @dashby3000

This adds a few new features:

  • declare a default status and errorStatus code in your method.http options
  • returns.http.target
    • status sets the res.statusCode to the provided value
    • header sets the returns.header or returns.arg named header to the value
  • set a custom header name for a header arg: returns: {arg: 'length', {http: {target: 'header', header: 'Content-Length'}}}
describe('using a custom status code', function() {
  it('returns a custom status code', function(done) {
    var method = givenSharedStaticMethod(
      function fn(cb) {
        cb();
      },
      {
        http: { status: 201 }
      }
    );
    json(method.url)
      .expect(201, done);
  });
  it('returns a custom error status code', function(done) {
    var method = givenSharedStaticMethod(
      function fn(cb) {
        cb(new Error('test error'));
      },
      {
        http: { status: 201, errorStatus: 508 }
      }
    );
    json(method.url)
      .expect(508, done);
  });
  it('returns a custom status code from a callback arg', function(done) {
    var exampleStatus = 222;
    var method = givenSharedStaticMethod(
      function fn(status, cb) {
        cb(null, status);
      },
      {
        accepts: { arg: 'status', type: 'number' },
        returns: {
          arg: 'status',
          http: { target: 'status' }
        }
      }
    );
    json(method.url + '?status=' + exampleStatus)
      .expect(exampleStatus, done);
  });
});

Connect to #186

@ritch ritch force-pushed the feature/declare-status branch from e0dc34b to 730017d Compare June 16, 2015 18:37
@ritch
Copy link
Member Author

ritch commented Jun 16, 2015

test please

@@ -359,7 +359,9 @@ RestAdapter.errorHandler = function(options) {
err.status = err.statusCode = 500;
}

res.statusCode = err.statusCode || err.status || 500;
if (res.statusCode === undefined || res.statusCode === 200) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about other 2xx status codes, like 204 No Content? I am proposing to rewrite the condition to res.statusCode === undefined || res.statusCode < 400

@bajtos
Copy link
Member

bajtos commented Jun 17, 2015

I am not sure if it's a good idea to add a constant errorStatus code, I am concerned that it may mask useful status codes like 422 (validation failed), 400 (bad request, caused by a missing argument) etc. Could you please add a unit- test to verify that err.statusCode takes precedence over errorStatus defined in remoting metadata?

       var method = givenSharedStaticMethod(
         function fn(cb) {
           var err = new Error('test error');
           err.statusCode = 400;
           cb(err);
         },
         {
           http: { status: 201, errorStatus: 508 }
         }
       );
       json(method.url)
         .expect(400, done);

@bajtos bajtos self-assigned this Jun 17, 2015
@bajtos
Copy link
Member

bajtos commented Jun 17, 2015

Awesome stuff!

It seems to me that passing ctx to SharedMethod.prototype.invoke is a bit inelegant and creates coupling that may make future refactoring more difficult. I don't have a better solution at hand though, so don't worry about it too much.

@ritch
Copy link
Member Author

ritch commented Jun 18, 2015

I am not sure if it's a good idea to add a constant errorStatus code, I am concerned that it may mask useful status codes like 422 (validation failed), 400 (bad request, caused by a missing argument) etc.

Well we need some way of declaring the status code for a specific result (eg. when the result is ok send this status, when the result is an error send this status).

I think the err.status should take precedence. So if that is set we will just ignore the errorStatus default.

@ritch ritch force-pushed the feature/declare-status branch from 730017d to 04314ed Compare June 18, 2015 16:39
@ritch ritch force-pushed the feature/declare-status branch from 04314ed to e5d71a7 Compare June 18, 2015 16:50
@crandmck
Copy link
Contributor

@ritch Remote methods' accepts & returns are documented here: http://apidocs.strongloop.com/strong-remoting/#sharedmethod (in source file https://github.com/strongloop/strong-remoting/blob/master/lib/shared-method.js). It might be best for you to add docs, since I'm not familiar with this PR. But if you want me to do it, please just open a doc issue.

var defaultStatus = this.method.http.status;

if (defaultStatus) {
res.status(defaultStatus);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check that res.statusCode === undefined || res.statusCode === 200 before applying defaultStatus?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the check...

@bajtos
Copy link
Member

bajtos commented Jun 19, 2015

The code LGTM, although I left one comment/question for your consideration. Please make sure the CI builds are green before landing this patch.

@bajtos bajtos assigned raymondfeng and ritch and unassigned bajtos and raymondfeng Jun 19, 2015
@ritch ritch force-pushed the feature/declare-status branch from e5d71a7 to 730017d Compare June 23, 2015 17:27
@ritch ritch force-pushed the feature/declare-status branch 2 times, most recently from 86f39f2 to e5d71a7 Compare June 23, 2015 17:34
@ritch ritch force-pushed the feature/declare-status branch from 74d3a75 to f01b8a6 Compare June 23, 2015 20:00
ritch added a commit that referenced this pull request Jun 23, 2015
Add support for declaring status code defaults
@ritch ritch merged commit 2cbe900 into master Jun 23, 2015
@ritch ritch removed the #review label Jun 23, 2015
@bajtos bajtos changed the title Add support for declaring status code defaults Add support for declaring status code defaults and custom http headers Feb 24, 2016
@auguster
Copy link

I'm having a use case with long video processing, sometimes the video is ready (status code 200) or processing (202). You can get the detailed status on a specific method that returns a status 201 if the processing has finished with the URI on where to get it.

So far I'm setting the status code through new Error(...).statusCode the problem is that 2xx are not errors and strong-error-handler is replacing status code < 400 by 500.

What has been proposed so far (setting static return status) doesn't work in my use case as I can return 200 or 202.

I'm looking for the best way to return non-error status codes. I guess I could go into the ctx.res and manually set this but that feels so wrong. What should I do ?

@bajtos bajtos deleted the feature/declare-status branch August 22, 2017 13:16
@bajtos
Copy link
Member

bajtos commented Aug 22, 2017

@auguster Your method should have a callback argument that's annotated with http: {target: 'status'}. See https://loopback.io/doc/en/lb3/Remote-methods.html#argument-descriptions
and the test-cases checking this functionality:

it('returns a custom status code from a callback arg', function(done) {
var exampleStatus = 222;
var method = givenSharedStaticMethod(
function fn(status, cb) {
cb(null, status);
},
{
accepts: {arg: 'status', type: 'number'},
returns: {
arg: 'status',
http: {target: 'status'},
},
}
);
json(method.url + '?status=' + exampleStatus)
.expect(exampleStatus, done);
});
it('returns a custom status code from a promise returned value', function(done) {
var exampleStatus = 222;
var sentBody = {eiste: 'ligo', kopries: true};
var method = givenSharedStaticMethod(
function fn() {
return Promise.resolve([exampleStatus, sentBody]);
},
{
returns: [{
arg: 'status',
http: {target: 'status'},
}, {
arg: 'result',
root: true,
type: 'object',
}],
}
);
json(method.url)
.expect(exampleStatus)
.then(function(response) {
expect(response.body).to.deep.equal(sentBody);
done();
})
.catch(done);
});
});

@auguster
Copy link

@bajtos I will try that, thanks.

@bajtos bajtos self-assigned this Aug 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants