ima
Version:
IMA.js framework for isomorphic javascript application
327 lines (271 loc) • 8.42 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _GenericError = require("../error/GenericError");
var _GenericError2 = _interopRequireDefault(_GenericError);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// @server-side class Response {__CLEAR__}\nexports.default = Response;
/**
* Wrapper for the ExpressJS response, exposing only the necessary minimum.
*/
class Response {
static get $dependencies() {
return [];
}
/**
* Initializes the response.
*/
constructor() {
/**
* The ExpressJS response object, or {@code null} if running at the
* client side.
*
* @type {?Express.Response}
*/
this._response = null;
/**
* It is flag for sent response for request.
*
* @type {boolean}
*/
this._isSent = false;
/**
* HTTP Status code.
*
* @type {number}
*/
this._status = 500;
/**
* The content of response.
*
* @type {string}
*/
this._content = '';
/**
* The rendered page state.
*
* @type {Object<string, *>}
*/
this._pageState = {};
/**
* Internal cookie storage for Set-Cookie header.
*
* @type {Map<string, {
* value: string,
* options: {domain: string=, expires: (number|string)=}
* }>}
*/
this._internalCookieStorage = new Map();
/**
* Transform function for cookie value.
*
* @type {{encode: function, decode: function}}
*/
this._cookieTransformFunction = {
encode: value => value,
decode: value => value
};
}
/**
* Initializes this response wrapper with the provided ExpressJS response
* object.
*
* @param {?Express.Response} response The ExpressJS response, or
* {@code null} if the code is running at the client side.
* @param {{
* encode: function(string): string=,
* decode: function(string): string
* }=} cookieTransformFunction
* @return {ima.router.Response} This response.
*/
init(response, cookieTransformFunction = {}) {
this._cookieTransformFunction = Object.assign(this._cookieTransformFunction, cookieTransformFunction);
this._response = response;
this._isSent = false;
this._status = 500;
this._content = '';
this._pageState = {};
this._internalCookieStorage = new Map();
return this;
}
/**
* Redirects the client to the specified location, with the specified
* redirect HTTP response code.
*
* For full list of HTTP response status codes see
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
*
* Use this method only at the server side.
*
* @param {string} url The URL to which the client should be redirected.
* @param {number=} [status=302] The HTTP status code to send to the
* client.
* @return {Response} This response.
*/
redirect(url, status = 302) {
if ($Debug) {
if (this._isSent === true) {
let params = this.getResponseParams();
params.url = url;
throw new _GenericError2.default('ima.router.Response:redirect The response has already ' + 'been sent. Check your workflow.', params);
}
}
this._isSent = true;
this._status = status;
this._setCookieHeaders();
this._response.redirect(status, url);
return this;
}
/**
* Sets the HTTP status code that will be sent to the client when the
* response is sent.
*
* For full list of available response codes see
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
*
* Use this method only at the server side.
*
* @param {number} httpStatus HTTP response status code to send to the
* client.
* @return {Response} This response.
*/
status(httpStatus) {
if ($Debug) {
if (this._isSent === true) {
let params = this.getResponseParams();
throw new _GenericError2.default('ima.router.Response:status The response has already ' + 'been sent. Check your workflow.', params);
}
}
this._status = httpStatus;
this._response.status(httpStatus);
return this;
}
/**
* Sends the response to the client with the provided content. Use this
* method only at the server side.
*
* @param {string} content The response body.
* @return {Response} This response.
*/
send(content) {
if ($Debug) {
if (this._isSent === true) {
let params = this.getResponseParams();
params.content = content;
throw new _GenericError2.default('ima.router.Response:send The response has already been ' + 'sent. Check your workflow.', params);
}
}
this._isSent = true;
this._content = content;
this._setCookieHeaders();
this._response.send(content);
return this;
}
/**
* Sets the rendered page state.
*
* @param {Object<string, *>} pageState The rendered page state.
* @return {Response} This response.
*/
setPageState(pageState) {
if ($Debug) {
if (this._isSent === true) {
let params = this.getResponseParams();
params.pageState = pageState;
throw new _GenericError2.default('ima.router.Response:setState The response has already ' + 'been sent. Check your workflow.', params);
}
}
this._pageState = pageState;
return this;
}
/**
* Sets a cookie, which will be sent to the client with the response.
*
* @param {string} name The cookie name.
* @param {(boolean|number|string)} value The cookie value, will be
* converted to string.
* @param {{domain: string=, expires: (number|string)=, maxAge: number=}}
* options Cookie attributes. Only the attributes listed in the type
* annotation of this field are supported. For documentation and full
* list of cookie attributes
* see http://tools.ietf.org/html/rfc2965#page-5
* @return {Response} This response.
*/
setCookie(name, value, options = {}) {
if ($Debug) {
if (this._isSent === true) {
let params = this.getResponseParams();
params.name = name;
params.value = value;
params.options = options;
throw new _GenericError2.default('ima.router.Response:setCookie The response has already ' + 'been sent. Check your workflow.', params);
}
}
let advancedOptions = Object.assign({}, this._cookieTransformFunction, options);
this._internalCookieStorage.set(name, {
value,
options: advancedOptions
});
return this;
}
/**
* Return object which contains response status, content and rendered
* page state.
*
* @return {{status: number, content: string, pageState: Object<string, *>}}
*/
getResponseParams() {
return {
status: this._status,
content: this._content,
pageState: this._pageState
};
}
/**
* Return true if response is sent from server to client.
*
* @return {boolean}
*/
isResponseSent() {
return this._isSent;
}
/**
* Set cookie headers for response.
*/
_setCookieHeaders() {
for (let [name, param] of this._internalCookieStorage) {
let options = this._prepareCookieOptionsForExpress(param.options);
this._response.cookie(name, param.value, options);
}
}
/**
* Prepares cookie options for Express.
*
* @param {{domain: string=, expires: (number|string)=, maxAge: number=}}
* options Cookie attributes. Only the attributes listed in the type
* annotation of this field are supported. For documentation and full
* list of cookie attributes
* see http://tools.ietf.org/html/rfc2965#page-5
* @return {Object} Cookie options prepared for Express.
*/
_prepareCookieOptionsForExpress(options) {
let expressOptions = Object.assign({}, options);
if (typeof expressOptions.maxAge === 'number') {
expressOptions.maxAge *= 1000;
} else {
delete expressOptions.maxAge;
}
return expressOptions;
}
}
exports.default = Response;
typeof $IMA !== 'undefined' && $IMA !== null && $IMA.Loader && $IMA.Loader.register('ima/router/Response', [], function (_export, _context) {
'use strict';
return {
setters: [],
execute: function () {
_export('default', exports.default);
}
};
});