« index
Coverage for /Users/kris/q-io/http-apps/negotiate.js : 68%
90 lines |
62 run |
28 missing |
0 partial |
19 blocks |
2 blocks run |
17 blocks missing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | var Q = require("q"); var MimeParse = require("mimeparse"); exports.negotiate = negotiate; function negotiate(request, types, header) { var keys = Object.keys(types); var accept = request.headers[header || "accept"] || "*"; var best = MimeParse.bestMatch(keys, accept); return types[best]; } /// branch on HTTP method /** * @param {Object * App} methods * @param {App} notAllowed (optional) * @returns {App} */ exports.Method = function (methods, methodNotAllowed) { var keys = Object.keys(methods); if (!methodNotAllowed) methodNotAllowed = exports.methodNotAllowed; return function (request, response) { var method = request.method; if (Object.has(keys, method)) { return Object.get(methods, method)(request, response); } else { return methodNotAllowed(request, response); } }; }; var Negotiator = function (requestHeader, responseHeader, respond) { return function (types, notAcceptable) { var keys = Object.keys(types); if (!notAcceptable) notAcceptable = exports.notAcceptable; return function (request, response) { var header = requestHeader; if (typeof header === "function") { header = requestHeader(request); } var accept = request.headers[requestHeader] || "*"; var type = MimeParse.bestMatch(keys, accept); request.terms = request.terms || {}; request.terms[responseHeader] = type; if (Object.has(keys, type)) { return Q.when(types[type](request, response), function (response) { if ( respond !== null && response && response.status === 200 && response.headers ) { response.headers[responseHeader] = type; } return response; }); } else { return notAcceptable(request, response); } }; }; }; /// branch on HTTP content negotiation /** * Routes based on content negotiation, between the request's `accept` * header and the application's list of possible content types. * * @param {Object * App} types mapping content types to apps that can * handle them. * @param {App} notAcceptable * @returns {App} */ exports.ContentType = Negotiator("accept", "content-type"); exports.Language = Negotiator("accept-language", "language"); exports.Charset = Negotiator("accept-charset", "charset"); exports.Encoding = Negotiator("accept-encoding", "encoding"); exports.Host = Negotiator(function (request) { return (request.headers.host || "*") + ":" + request.port; }, "host", null); // Branch on a selector function based on the request exports.Select = function (select) { return function (request, response) { return Q.when(select(request, response), function (app) { return app(request, response); }); }; }; |