Name: js-handler/node_modules/restify/lib/plugins/cors.js
| 1: | // Copyright 2013 Mark Cavage, Inc. All rights reserved. |
| 2: | |
| 3: | var assert = require('assert-plus'); |
| 4: | |
| 5: | |
| 6: | |
| 7: | ///--- Globals |
| 8: | |
| 9: | var ALLOW_HEADERS = [ |
| 10: | 'accept', |
| 11: | 'accept-version', |
| 12: | 'content-type', |
| 13: | 'request-id', |
| 14: | 'origin', |
| 15: | 'x-api-version', |
| 16: | 'x-request-id' |
| 17: | ]; |
| 18: | |
| 19: | var EXPOSE_HEADERS = [ |
| 20: | 'api-version', |
| 21: | 'content-length', |
| 22: | 'content-md5', |
| 23: | 'content-type', |
| 24: | 'date', |
| 25: | 'request-id', |
| 26: | 'response-time' |
| 27: | ]; |
| 28: | |
| 29: | // Normal |
| 30: | var AC_ALLOW_ORIGIN = 'Access-Control-Allow-Origin'; |
| 31: | var AC_ALLOW_CREDS = 'Access-Control-Allow-Credentials'; |
| 32: | var AC_EXPOSE_HEADERS = 'Access-Control-Expose-Headers'; |
| 33: | |
| 34: | |
| 35: | |
| 36: | ///--- Internal Functions |
| 37: | |
| 38: | function matchOrigin(req, origins) { |
| 39: | var origin = req.headers['origin']; |
| 40: | |
| 41: | function belongs(o) { |
| 42: | if (origin === o || o === '*') { |
| 43: | origin = o; |
| 44: | return (true); |
| 45: | } |
| 46: | |
| 47: | return (false); |
| 48: | } |
| 49: | |
| 50: | return ((origin && origins.some(belongs)) ? origin : false); |
| 51: | } |
| 52: | |
| 53: | |
| 54: | |
| 55: | ///--- API |
| 56: | |
| 57: | // |
| 58: | // From http://www.w3.org/TR/cors/#resource-processing-model |
| 59: | // |
| 60: | // If "simple" request (paraphrased): |
| 61: | // |
| 62: | // 1. If the Origin header is not set, or if the value of Origin is not a |
| 63: | // case-senstive match to any values listed in `opts.origins`, do not |
| 64: | // send any CORS headers |
| 65: | // |
| 66: | // 2. If the resource supports credentials add a single |
| 67: | // 'Access-Controlw-Allow-Credentials' header with the value as "true", and |
| 68: | // ensure 'AC-Allow-Origin' is not '*', but is the request header value, |
| 69: | // otherwise add a single Access-Control-Allow-Origin header, with either the |
| 70: | // value of the Origin header or the string "*" as value |
| 71: | // |
| 72: | // 3. Add Access-Control-Expose-Headers as appropriate |
| 73: | // |
| 74: | // Preflight requests are handled by the router internally |
| 75: | // |
| 76: | function cors(opts) { |
| 77: | assert.optionalObject(opts, 'options'); |
| 78: | opts = opts || {}; |
| 79: | assert.optionalArrayOfString(opts.origins, 'options.origins'); |
| 80: | assert.optionalBool(opts.credentials, 'options.credentials'); |
| 81: | assert.optionalArrayOfString(opts.headers, 'options.headers'); |
| 82: | |
| 83: | var headers = (opts.headers || []).slice(0); |
| 84: | var origins = opts.origins || ['*']; |
| 85: | |
| 86: | EXPOSE_HEADERS.forEach(function (h) { |
| 87: | if (headers.indexOf(h) === -1) |
| 88: | headers.push(h); |
| 89: | }); |
| 90: | |
| 91: | // Handler for simple requests |
| 92: | function restifyCORSSimple(req, res, next) { |
| 93: | var origin; |
| 94: | if (!(origin = matchOrigin(req, origins))) { |
| 95: | next(); |
| 96: | return; |
| 97: | } |
| 98: | |
| 99: | function corsOnHeader() { |
| 100: | if (opts.credentials) { |
| 101: | origin = req.headers['origin']; |
| 102: | res.setHeader(AC_ALLOW_ORIGIN, origin); |
| 103: | res.setHeader(AC_ALLOW_CREDS, 'true'); |
| 104: | } else { |
| 105: | res.setHeader(AC_ALLOW_ORIGIN, origin); |
| 106: | } |
| 107: | |
| 108: | res.setHeader(AC_EXPOSE_HEADERS, headers.join(', ')); |
| 109: | } |
| 110: | |
| 111: | res.once('header', corsOnHeader); |
| 112: | next(); |
| 113: | } |
| 114: | |
| 115: | return (restifyCORSSimple); |
| 116: | } |
| 117: | |
| 118: | |
| 119: | |
| 120: | ///--- Exports |
| 121: | |
| 122: | module.exports = cors; |
| 123: | cors.ALLOW_HEADERS = ALLOW_HEADERS; |
