Search code examples
javascriptnode.jsexpressfeathersjs

Modifying response status code in feathers hook.result


I have been playing around with feathers.js lately, and I love it. I have the following issue but...

In a before hook placed for update (http put) server method I decide whether to create or update based on some condition. And if I choose create I skip the service method by using hook.result

let createLocation = (hook) => {
  return hook.app.service('locations').create({
    "user": hook.data.user,
    "location": [{
      "latitude": hook.data.location[0].latitude,
      "longitude": hook.data.location[0].longitude
    }]
  }).then(location => {
     hook.result = location;
     //************ change the response status code here?? **************\\
  });
};

But I am not able to change the response status code to stick to 201 created. Help would be appreciated. (Also please point at the source code where this is handled if possible, I did search but was not successful).


Solution

  • Services and hooks are transport independent which is why they can be used through both, websockets and HTTP. Any HTTP specific logic should live in its own middleware. There are two options. For setting the status code for all services you can implement a custom formatter, for only a specific service you can register service specific middleware.

    If there is no way to deduct the status code from the data, you could define a hidden property (that is not writeable and won't show up when converting it to JSON) on the data object:

    let createLocation = (hook) => {
      return hook.app.service('locations').create({
        "user": hook.data.user,
        "location": [{
          "latitude": hook.data.location[0].latitude,
          "longitude": hook.data.location[0].longitude
        }]
      }).then(location => {
        Object.defineProperty(location, '__status', {
          value: 201
        });
        hook.result = location;
      });
    };
    

    And use it in a custom formatter:

    const app = feathers();
    
    function restFormatter(req, res) {
      res.format({
        'application/json': function() {
          const data = res.data;
    
          res.status(data.__status || 200);
          res.json(data);
        }
      });
    }
    
    app.configure(rest(restFormatter));
    

    There are other options like passing the response to params or instead returning a wrapper object ({ status, data }) that has additional meta information.