UNPKG

mojito

Version:

Mojito provides an architecture, components and tools for developers to build complex web applications faster.

212 lines (175 loc) 5.82 kB
/* * Copyright (c) 2011-2013, Yahoo! Inc. All rights reserved. * Copyrights licensed under the New BSD License. * See the accompanying LICENSE file for terms. */ /*jslint anon:true, sloppy:true, nomen:true*/ /*global YUI*/ /** * @module ActionContextAddon */ YUI.add('mojito-http-addon', function(Y, NAME) { var XHR_HDR = 'x-requested-with', XHR_HDR_REGEX = /^XMLHttpRequest$/i; /** * <strong>Access point:</strong> <em>ac.http.*</em> * This is a server-only utility plugin that makes many server side * resources available for mojit code that will never run on the client. * @class Http.server */ function Addon(command, adapter, ac) { this.adapter = adapter; this.ac = ac; this._respHeaders = {}; this._statusCode = null; } Addon.prototype = { namespace: 'http', /** * Returns the HTTP request. * @method getRequest * @return {ServerRequest} The node.js http.ServerRequest instance. */ getRequest: function() { return this.adapter.req; }, /** * Returns the HTTP response object from the request. * @method getResponse * @return {ServerResponse} The node.js http.ServerResponse instance. */ getResponse: function() { return this.adapter.res; }, /** * Adds a header to the response without overriding previous values * @method addHeader * @param {String} key header name. * @param {String} val header value. */ addHeader: function(k, v) { // multiline values are against HTTP spec, and a SECURITY RISK var key = (k || '').split('\n')[0].toLowerCase(), val = (v || '').split('\n')[0], dup = false, hdrs = this._respHeaders; if (!hdrs[key]) { hdrs[key] = []; } hdrs[key].forEach(function(i) { if (i === val) { dup = true; } }); if (!dup) { hdrs[key].push(val); } }, /** * Adds a object of headers all at once, adding to previous values * @method addHeaders * @param {object} hdrs header values to add. */ addHeaders: function(hdrs) { Y.Object.each(hdrs, function(val, key) { this.addHeader(key, val); }, this); }, /** * Sets a header by key, overriding previous values * @method setHeader * @param {string} key header name. * @param {string} val header value. */ setHeader: function(key, val) { this._respHeaders[key.toLowerCase()] = [val]; }, /** * Sets a object full of headers all at once, overriding previous values * @method setHeaders * @param {object} hdrs header values to set. */ setHeaders: function(hdrs) { Y.Object.each(hdrs, function(val, key) { this.setHeader(key, val); }, this); }, /** * Returns one request header value * @method getHeader * @param {string} name header name. * @return {object} header value. */ getHeader: function(name) { var n = name.toLowerCase(), val; // have to loop through these because the header keys must be case // insensitive Y.Object.some(this.getHeaders(), function(v, k) { if (k.toLowerCase() === n) { val = v; return true; } }); return val; }, /** * Returns all request headers * @method getHeaders * @return {object} all headers. */ getHeaders: function() { return this.adapter.req.headers; }, /** * Helper to tell you if this is an XHR request. Checks specifically * for the 'x-requested-with' header. * @method isXhr * @return {boolean} True if the receiver is associated with an XHR * request. */ isXhr: function() { return XHR_HDR_REGEX.test(this.getHeader(XHR_HDR)); }, /** * This redirect is an external redirect. It causes an HTTP * status code 301 by default. * @method redirect * @param {string} uri the URI to redirect to. * @param {Number} code [optional] if not specifed, 301. */ redirect: function(uri, code) { code = code || 301; var meta = { http: { code: code } }; Y.log('redirect(' + uri + ', ' + code + ')', 'debug', NAME); this._statusCode = code; this.addHeader('location', uri); this.addHeader('content-type', 'text/html'); this.ac.done(null, meta); }, mergeMetaInto: function(meta) { if (Object.keys(this._respHeaders).length === 0) { return meta; } if (!meta.http) { meta.http = {}; } if (!meta.http.headers) { meta.http.headers = {}; } Y.mojito.util.metaMerge(meta.http.headers, this._respHeaders); return meta; }, getGlobal: function() { return global._mojito; } }; Y.namespace('mojito.addons.ac').http = Addon; }, '0.1.0', {requires: [ 'mojito', 'mojito-util' ]});