UNPKG

waffle

Version:

シンプルなWEBアプリケーションフレームワークです。(ALL YOUR NODE ARE BELONG TO US)

287 lines (251 loc) 7.46 kB
/* * Copyright 2012 Katsunori Koyanagi * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ /** * @overview リクエストとレスポンスを対とした、クライアントとの対話を管理する機能を提供します。 */ "use strict"; var parse = require("url").parse; var util = require("../utils/Util"); var log = require("../utils/Log"); var EventEmitter = require("events").EventEmitter; var id = 0; /** * コンテキストのクラスです。 * <p> * クライアントからのリクエストとレスポンスを表現します。直接Node.jsがサポートするリクエストとレスポンスを操作するのも可能です。 その場合は{@link Context#req}と{@link Context#req}を参照してください。 * </p> * <p> * このクラスはEventEmitterを継承し、"close"イベントをサポートします。リスナにはタイムアウトの場合はtrueであるフラグが渡されます。 * </p> * * @property {Object} req リクエスト * @property {Object} res レスポンス * @property {Object} app アプリケーション * @property {String} id リクエストID * @property {Object} url URL情報 * @class コンテキストのクラスです。 * @constructor */ var Context = function(req, res, app) { EventEmitter.call(this); this.url = parse(req.url); this.req = req; this.res = res; this.app = app; this.id = "req_" + util.generateUID(); res.setHeader("X-Powered-By", "Waffle"); }; require("util").inherits(Context, EventEmitter); // // コンテキストクラスのプロトタイプ定義 // /** * リクエストボディに含まれるポストされたパラメータを示す文字列です。この値はフィルタよって設定されます。 * * @type String * @see Filters#postParameter */ Context.prototype.postParameter = null; /** * セッションです。この値はフィルタよって設定されます。 * * @type SessionObject * @see Filters#session */ Context.prototype.session = null; /** * サードパティモジュールの<a href="https://github.com/jed/cookies">cookies</a>のインスタンスです。 * この値はフィルタによって設定されます。 * * @type Object * @see Filters#cookies */ Context.prototype.cookies = null; /** * パラメータを取得して返します。 * <p> * リクエストボディを取得済みであれば、自動的にリクエストボディを含めてパラメータのパースが行われます。 * </p> * * @param {Boolean} * phpStyle PHPスタイルでパースする場合はtrue、省略時はfalseとみなされる * @return {Object} パラメータ */ Context.prototype.getParameters = function(phpStyle) { if (this.__parameters__) { return this.__parameters__; } var query = this.url.query || ""; if (this.postParameter) { if (query) { query += "&"; } query += this.postParameter; } var params; if (phpStyle) { params = util.parsePHPStyleParameters(query); } else { params = util.parseServletStyleParameters(query); } this.__parameters__ = params; return params; }; /** * リクエストヘッダのAccept-Languagesに基づいて、言語を配列で返します。 * * @return {Array} 言語の配列、存在しない場合は空の配列 */ Context.prototype.getLanguages = function() { var lang = this.req.headers["accept-language"]; if (!lang) { return []; } var index = lang.indexOf(";"); if (index > -1) { lang = lang.substr(0, index); } if (lang.length === 0) { return []; } return lang.split(","); }; /** * ルータによって正規表現によるパスのマッチングを行った結果です。 * * @type Array */ Context.prototype.matches = null; /** * コントローラ等で設定されたエラーです。 * * @type String|Error * @see Context#error */ Context.prototype.errorInfo = null; /** * エラーページへのディスパッチを行います。 * * @param {Number} * code エラーコード * @param {Error|String} * error エラー(省略可) */ Context.prototype.error = function(code, error) { if (this.__callback__ == null) { return; } var callback = this.__callback__; this.__callback__ = null; callback("error", null, null, code, error); }; /** * 指定のパスの処理を行うコントローラへのディスパッチを行います。 * * @param {String} * path パス */ Context.prototype.dispatch = function(path) { if (this.__callback__ == null) { return; } var callback = this.__callback__; this.__callback__ = null; callback("dispatch", null, path); }; /** * 指定のURLへのリダイレクトを行います。 * * @param {String} * url URL */ Context.prototype.redirect = function(url) { if (this.__callback__ == null) { return; } var callback = this.__callback__; this.__callback__ = null; callback("redirect", null, url); }; /** * 指定のビューのレンダリングを行います。 * * @param {String} * view ビューを示す文字列 * @param {Object} * data ビューで使用するデータ */ Context.prototype.render = function(view, data) { if (this.__callback__ == null) { return; } var callback = this.__callback__; this.__callback__ = null; callback("render", data, view); }; /** * 何もせずにコントローラの処理を終了します。 */ Context.prototype.complete = function() { if (this.__callback__ == null) { return; } var callback = this.__callback__; this.__callback__ = null; callback("complete"); }; /** * コネクションのタイムアウトのミリ秒の時間を設定します。 * * @param {Number} * timeout タイムアウトまでの時間、不正な値、0以下の値の場合は120000(2分) */ Context.prototype.setConnectionTimeout = function(timeout) { if (timeout * 0.0 !== 0.0) { timeout = parseInt(timeout); } if (timeout * 0.0 !== 0.0) { timeout = 0; } if (timeout <= 0) { timeout = 120000; } this.req.socket.setTimeout(timeout); }; /** * @private */ Context.prototype.__start__ = function(timeout) { this.setConnectionTimeout(timeout); var self = this; this.__onTimeout__ = function() { self.req.socket.removeListener("timeout", self.__onTimeout__); log.error("request timeout"); self.emit("close", true); }; this.req.socket.on("timeout", this.__onTimeout__); }; /** * @private */ Context.prototype.__close__ = function() { this.req.socket.removeListener("timeout", this.__onTimeout__); this.emit("close", false); }; // // expose // module.exports = Context;