How do I return specific http status codes from a remote method in loopback?
Asked Answered
C

7

11

I would like to know if there is a way to returns a specific HTTP status code from within a remote method.

I can see that there is a callback function which we can pass an error object, but how do we define the HTTP status code?

Cowage answered 22/12, 2014 at 19:32 Comment(2)
which technology do you use?Hedgehop
if loopback is what we are talking about, here's a response by its authors: groups.google.com/d/msg/loopbackjs/oK2g5A_h6vI/VNTD3_GDMQkJBackground
M
25

If you wish to use an HTTP status code to notify of an error, you can pass an error in the remote methods callback method:

var error = new Error("New password and confirmation do not match");
error.status = 400;
return cb(error);

You can find more information about the error object here: Error object

If you wish to just alter the HTTP response status without using an error, you can use one of the two methods defined by either #danielrvt or #superkhau. To obtain the reference to the request object mentioned by #superkhau, in your method registration you can define an additional argument that will be passed to your remote method. See HTTP mapping of input arguments

Mcwherter answered 10/8, 2016 at 2:4 Comment(1)
Doesn't this return an entire stack trace though? If you wanted to return { status: 404, message: 'Not found'} is there a better approach?Stortz
E
4

Lets assume that you have a CoffeShop Model and you want to send status 404 if the item is not in your db.

CoffeeShop.getName = function(req, res, cb) {
    var shopId = req.query.id;
    CoffeeShop.findById(shopId, function(err, instance) {
      if (instance && instance.name){
        var response = instance.name;
        cb(null, response);
      }
      else {
        res.status(404);
        cb(null);
      }
    });
  }

CoffeeShop.remoteMethod(
    'getName',
    {
      http: { path: '/getname', verb: 'get' },
      accepts: [{arg: 'req', type: 'object', http: { source: 'req' }},
                { arg: 'res', type: 'object', http: { source: 'res' }}],
      returns: { arg: 'name', type: 'string' }
    }
  );
Excavate answered 27/9, 2018 at 15:0 Comment(0)
G
4

When using an async remote method function, you need to let the async function throw any encountered errors, rather than trying to catch them and call return. By calling return you're telling LoopBack that it should respond as if it were successful.

Here's an example working structure.

AdminDashboard.login = async(body) => {
  let username = body.username
  let password = body.password
  await isDomainAdmin(username, password)
}
AdminDashboard.remoteMethod(
  'login',
  {
    http: {path: '/login', verb: 'put'},
    consumes: ['application/json'],
    produces: ['application/json'],
    accepts: [
      {arg: 'body', type: 'Credentials', http: {source: 'body'}}
    ]
  }
)

Just make sure that any internal functions you call like isDomainAdmin are also either throwing their errors directly, or that you catch them and convert them to an error object like this:

{
  statusCode: 401,
  message: 'Unauthorized'
}

Where err.statusCode is the HTTP status code you want LoopBack to return.

Glister answered 3/4, 2019 at 3:56 Comment(0)
C
3

You can return any status code just like you would in ExpressJS.

...
res.status(400).send('Bad Request');
...

See http://expressjs.com/api.html

Cruise answered 22/12, 2014 at 20:2 Comment(4)
I understand that; but how do you get an instance of express response?Cowage
Depends what part of the lifecycle you're in. In some places, you have access to ctx, in which case you can do ctx.req. There are also major discussions around getCurrentContext: github.com/strongloop/loopback/issues/1676.Cruise
Why is it downvoted? It works and it's not deprecated api, expressjs.com/en/api.html#res.statusGingili
How to get a reference of res ?Excavate
H
2

In your remote method registration:

YourModel.remoteMethod('yourMethod', {
    accepts: [
      {arg: 'res', type: 'object', http:{source: 'res'}}
    ],
    ...
    returns: {root: true, type: 'string'},
    http: {path: '/:id/data', verb: 'get'}
  });
Hallett answered 14/8, 2015 at 16:25 Comment(0)
B
1

If you just need to modify response status, just do:

ctx.res.status(400);
return cb(null);
Boiler answered 6/8, 2017 at 9:52 Comment(0)
B
0

In Loopback 4 there is an HttpErrors class for this. Here are just a few:

// Throw a 400 error
throw new HttpErrors.BadRequest("Invalid request");

// Throw a 403 error
throw new HttpErrors.Forbidden("You don't have permission to do this");

// Throw a 404 error
throw new HttpErrors.NotFound("The data was not found")

You can also inject the Response object in the controller's constructor and explicitly call it:

// As a constructor argument
@inject(RestBindings.Http.RESPONSE) private res: Response

// In your method
this.res.status(400).send("Invalid request");
Byroad answered 26/7, 2023 at 22:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.