How can I support cors when using restify
Asked Answered
B

14

47

I have a REST api created with the restify module and I want to allow cross-origin resource sharing. What is the best way to do it?

Brisesoleil answered 15/1, 2013 at 13:21 Comment(1)
There is an issue on: github.com/mcavage/node-restify/issues/284Brisesoleil
T
66

You have to set the server up to set cross origin headers. Not sure if there is a built in use function or not, so I wrote my own.

server.use(
  function crossOrigin(req,res,next){
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    return next();
  }
);

I found this from this tutorial. http://backbonetutorials.com/nodejs-restify-mongodb-mongoose/

Turman answered 24/1, 2013 at 17:9 Comment(4)
Since this answer has been around for a while and people are asking about versions in the comments below other questions, I'd like to report that this answer is still valid for me with Restify 4.1.0.Jonasjonathan
i am using restify 5.0.1, and can't find the solution regarding CORSElmaleh
I use it with 6.0.1Achaemenid
Nowadays, browsers send preflight requests (method = 'OPTIONS') so the solution in this answer is no longer complete. See also server.opts() in @cyrusmith's answser.Gabrielson
H
64

The latest version of Restify provides a plugin to handle CORS.

So you can now use it like this:

server.use(restify.CORS({

  // Defaults to ['*'].
  origins: ['https://foo.com', 'http://bar.com', 'http://baz.com:8081'], 

  // Defaults to false.
  credentials: true,

  // Sets expose-headers.
  headers: ['x-foo']   

}));
Historied answered 6/3, 2013 at 2:49 Comment(7)
which version of restify? (you said "last version of restify...")Milliemillieme
@Jean-MichelTrayaud: this doesn't work for me... I'm getting Origin 192.168.2.124 is not allowed by Access-Control-Allow-Origin. Any help will be apreciated :)Intercrop
think we need more information... GET or POST in first time (POST is really a nightmare with CORS)Historied
Testing against Restify 3.0.3, using restify.CORS() by itself was sufficient. No need for restify.fullResponse(), but in the request, you need to specify the Origin header. See related code comment in cors.js.Wilda
This plugin has a strange behavior. If the origin matches one of the array, it will return the matching origin in the response header, which is expected. If it doesn't match however, it will return a wildcard. It will still fail if you make a credentialized cors request, because then the origin must not be *. But why return * anyway?Kelle
i am using restify 5.0.1, and can't find the solution regarding CORSElmaleh
Note that this plugin has been removed in favour of a middleware solution (source)Fascism
K
14

This works for me:

var restify = require('restify');

var server = restify.createServer();

server.use(restify.CORS());

server.opts(/.*/, function (req,res,next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Methods", req.header("Access-Control-Request-Method"));
    res.header("Access-Control-Allow-Headers", req.header("Access-Control-Request-Headers"));
    res.send(200);
    return next();
});

server.get('/test', function (req,res,next) {

    res.send({
        status: "ok"
    });
    return next();
});

server.listen(3000, function () {
    console.log('%s listening at %s', server.name, server.url);
});
Kennithkennon answered 8/10, 2014 at 8:59 Comment(1)
For some reason, the other answers did not work for me. Yours did. I wonder if it has something to do with changes made to latest versions of restify.Wetnurse
N
10

This is what worked for me:

function unknownMethodHandler(req, res) {
  if (req.method.toLowerCase() === 'options') {
      console.log('received an options method request');
    var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With']; // added Origin & X-Requested-With

    if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');

    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
    res.header('Access-Control-Allow-Methods', res.methods.join(', '));
    res.header('Access-Control-Allow-Origin', req.headers.origin);

    return res.send(204);
  }
  else
    return res.send(new restify.MethodNotAllowedError());
}

server.on('MethodNotAllowed', unknownMethodHandler);

I this code was taken from https://github.com/mcavage/node-restify/issues/284

Neckwear answered 12/4, 2013 at 21:26 Comment(3)
This worked for me, but I also needed to add server.use(restify.fullResponse()); prior to the call to server.on(...).Milliemillieme
This almost worked for me. I had to use server.opts({path: '/customers', version: '0.0.1'}, unknownMethodHandler);. With on, the method just wasn't called.Soule
This avoids the 404 "Method not allowed" response from restify for OPTIONS preflight requests. The CORS cross-origin problem must be handled separately--see "crossOrigin function above for a fix that problem.Tray
N
6

CORS Plugin is deprecated in favor of https://github.com/Tabcorp/restify-cors-middleware. (Source: https://github.com/restify/node-restify/issues/1091.)

Below is a sample code regarding how to use

const corsMiddleware = require('restify-cors-middleware')

const cors = corsMiddleware({
  preflightMaxAge: 5, //Optional
  origins: ['http://api.myapp.com', 'http://web.myapp.com'],
  allowHeaders: ['API-Token'],
  exposeHeaders: ['API-Token-Expiry']
})

server.pre(cors.preflight)
server.use(cors.actual)
Nudicaul answered 9/10, 2017 at 4:55 Comment(0)
F
5

If anyone comes across this as of Feb 2018 there seems to be a bug that's been introduced, I couldn't get the restify-cors-middleware to work.

I'm using this work around for now:

server.pre((req, res, next) => {
   res.header("Access-Control-Allow-Origin", "*");
   next();
});
Fania answered 22/2, 2018 at 11:53 Comment(3)
This is the only solution which works right now in 07/2021, everything else is obsolete or has a bug, also the "new" middleware. restify is a mess, I recommending anyone new to NOT use it.Alumnus
So it's not just me who's had trouble with the plugins! Phew.Tiphani
Btw, when I use this, I get 404s on my endpoints. :(Tiphani
S
4

To enable CORS for basic authentication I did the following. It did not work until the .pre methods were used instead of the .use methods

server.pre(restify.CORS({
  origins: ['https://www.allowedip.com'],  // defaults to ['*']
  credentials: true,
  headers: ['X-Requested-With', 'Authorization']
}));
server.pre(restify.fullResponse());

function unknownMethodHandler(req, res) {
    if (req.method.toLowerCase() === 'options') {
      var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With', 'Authorization']; // added Origin & X-Requested-With & **Authorization**

      if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');

      res.header('Access-Control-Allow-Credentials', true);
      res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
      res.header('Access-Control-Allow-Methods', res.methods.join(', '));
      res.header('Access-Control-Allow-Origin', req.headers.origin);

      return res.send(200);
   } else {
      return res.send(new restify.MethodNotAllowedError());
   }
}

server.on('MethodNotAllowed', unknownMethodHandler);
Simaroubaceous answered 27/8, 2014 at 16:15 Comment(1)
typo alert: the last else needs an extra bracketBoar
K
3

I do it like this on my restify base app:

//setup cors
restify.CORS.ALLOW_HEADERS.push('accept');
restify.CORS.ALLOW_HEADERS.push('sid');
restify.CORS.ALLOW_HEADERS.push('lang');
restify.CORS.ALLOW_HEADERS.push('origin');
restify.CORS.ALLOW_HEADERS.push('withcredentials');
restify.CORS.ALLOW_HEADERS.push('x-requested-with');
server.use(restify.CORS());

you need to use restify.CORS.ALLOW_HEADERS.push method to push the header u want into restify first, then using the CORS middleware to boot the CORS function.

Knave answered 6/10, 2013 at 23:15 Comment(1)
I'm using Restify v2.8.3, and some of these headers are already enabled by default. Check out the defaults in ./node_modules/restify/lib/plugins/cors.js.Eldwon
P
3

MOST OF THE PREVIOUS ANSWERS ARE FROM 2013 AND USE DEPRECATED EXAMPLES! The solution (in 2017 at least) is as follows:

npm install restify-cors-middleware

Then in your server javascript file:

var corsMiddleware = require('restify-cors-middleware');

var cors = corsMiddleware({
  preflightMaxAge: 5,
  origins: ['*']
});

var server = restify.createServer();

server.pre(cors.preflight);
server.use(cors.actual);

And add whatever additional other options work for you. My use case was creating a localhost proxy to get around browser CORS issues during devolopment. FYI I am using restify as my server, but then my POST from the server (and to the server) is with Axios. My preference there.

npm listing for restify-cors-middleware

Prisoner answered 20/11, 2017 at 23:1 Comment(1)
doesnt work, it's bugged, broken or whateverAlumnus
A
2

This sufficed in my case:

var server = restify.createServer();
server.use(restify.fullResponse());
server.get('/foo',  respond(req, res, next) {
   res.send('bar');
   next();
});

It wasn't necessary to server.use(restify.CORS()); Also, it appears server.use() calls must precede server.get() calls in order to work.

Attachment answered 28/5, 2013 at 17:43 Comment(0)
E
1

This worked for me with restify 7

server.pre((req, res, next) => {

    res.header('Access-Control-Allow-Origin', req.header('origin'));
    res.header('Access-Control-Allow-Headers', req.header('Access-Control-Request-Headers'));
    res.header('Access-Control-Allow-Credentials', 'true');
    // other headers go here..

    if(req.method === 'OPTIONS') // if is preflight(OPTIONS) then response status 204(NO CONTENT)
        return res.send(204);

    next();

});
Exterminate answered 19/1, 2019 at 10:57 Comment(0)
H
0

I am using Restify 7.2.3 version and this code worked for me very well. You need to install the restify-cors-middleware plugin.

const corsMiddleware = require('restify-cors-middleware')

const cors = corsMiddleware({
    preflightMaxAge: 5, //Optional
    origins: ['http://ronnie.botsnbytes.com', 'http://web.myapp.com'],
    allowHeaders: ['API-Token'],
    exposeHeaders: ['API-Token-Expiry']
})

server.pre(cors.preflight)
server.use(cors.actual)
Humiliation answered 20/3, 2019 at 1:23 Comment(0)
S
-1
   const cors = require('cors');


   const server = restify.createServer();

   server.use(cors());

This worked for me

Spanish answered 28/12, 2018 at 9:13 Comment(0)
S
-1
const restify = require('restify');
const corsMiddleware = require('restify-cors-middleware');

const cors = corsMiddleware({
  origins: ['*']
});

const server = restify.createServer();
server.pre(cors.preflight);
server.use(cors.actual);

server.get('/api/products', (request, response) => {
  response.json({ message: 'hello REST API' });
});

server.listen(3000, () => console.info(`port 3000`));

... is one brute-force solution, though you should be very careful doing that.

Sluggard answered 10/5, 2019 at 11:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.