UNPKG

neft

Version:

Universal Platform

286 lines (198 loc) 7.01 kB
# Response 'use strict' utils = require 'src/utils' assert = require 'src/assert' log = require 'src/log' signal = require 'src/signal' assert = assert.scope 'Networking.Response' log = log.scope 'Networking', 'Response' # **Class** Response module.exports = (Networking, Impl) -> class Response extends signal.Emitter ## *Array* Response.STATUSES Contains abstract codes used to describe the response type. Each status corresponds to the HTTP numeral value. Check [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html]() for more. Contains: - Response.OK, - Response.CREATED, - Response.ACCEPTED, - Response.NO_CONTENT, - Response.MOVED, - Response.FOUND, - Response.NOT_MODIFIED, - Response.TEMPORARY_REDIRECT, - Response.BAD_REQUEST, - Response.UNAUTHORIZED, - Response.PAYMENT_REQUIRED, - Response.FORBIDDEN, - Response.NOT_FOUND, - Response.CONFLICT, - Response.PRECONDITION_FAILED, - Response.UNSUPPORTED_MEDIA_TYPE, - Response.INTERNAL_SERVER_ERROR, - Response.NOT_IMPLEMENTED, - Response.SERVICE_UNAVAILABLE. ```javascript console.log(Networking.Response.OK); console.log(Networking.Response.BAD_REQUEST); ``` @STATUSES = [ # Success (@OK = 200), (@CREATED = 201), (@ACCEPTED = 202), (@NO_CONTENT = 204), # Redirection (@MOVED = 301), (@FOUND = 302), (@NOT_MODIFIED = 304), (@TEMPORARY_REDIRECT = 307), # Client error (@BAD_REQUEST = 400), (@UNAUTHORIZED = 401), (@PAYMENT_REQUIRED = 402), (@FORBIDDEN = 403), (@NOT_FOUND = 404), (@METHOD_NOT_ALLOWED = 405), (@NOT_ACCEPTABLE = 406), (@CONFLICT = 409), (@PRECONDITION_FAILED = 412), (@UNSUPPORTED_MEDIA_TYPE = 415), # Server error (@INTERNAL_SERVER_ERROR = 500), (@NOT_IMPLEMENTED = 501), (@SERVICE_UNAVAILABLE = 503) ] @Error = require('./response/error') Networking, Response ## Response::constructor(*Object* options) Access it with: ```javascript var Networking = require('networking'); var Response = Networking.Response; ``` constructor: (opts) -> assert.isPlainObject opts, 'ctor options argument ...' assert.instanceOf opts.request, Networking.Request, 'ctor options.request argument ...' super() if opts.status? assert.ok utils.has(Response.STATUSES, opts.status), 'ctor options.status argument ...' {@status} = opts if opts.data? {@data} = opts if opts.encoding? {@encoding} = opts @headers = opts.headers or {} @cookies = opts.cookies or {} utils.defineProperty @, 'request', null, opts.request @pending = true # signal handlers if opts.onSend @onSend opts.onSend if opts.status? @send() ## *Signal* Response::onSend() Called when the response has been sent. ```javascript res.onSend(function(){ console.log("Response has been sent!"); }); ``` signal.Emitter.createSignal @, 'onSend' ## ReadOnly *Boolean* Response::pending Indicates whether the response is not destroyed. pending: false ## ReadOnly *Networking.Request* Response::request Refers to the [Request][networking/Request]. request: null ## *Integer* Response::status = Response.OK Keeps a normalized code determined the response type. It refers to one of the *Response.STATUSES* values. ```javascript res.status = Networking.Response.CREATED; res.status = Networking.Response.PAYMENT_REQUIRED; ``` status: @OK ## *Any* Response::data Value sent to the client. ```javascript res.data = {items: ['superhero toy', 'book']}; res.data = new Error("Wrong order"); res.data = Document.fromJSON(...); ``` data: null ## *Object* Response::headers headers: null ## *Object* Response::cookies cookies: null ## *String* Response::encoding = 'utf-8' encoding: 'utf-8' ## *Response* Response::setHeader(*String* name, *String* value) ```javascript res.setHeader('Location', '/redirect/to/url'); ``` setHeader: (name, val) -> assert.ok @request.pending assert.isString name, '::setHeader name argument ...' assert.notLengthOf name, 0, '::setHeader name argument ...' assert.isString val, '::setHeader value argument ...' assert.notLengthOf val, 0, '::setHeader value argument ...' Impl.setHeader @, name, val @ ## Response::send([*Integer* status, *Any* data]) This method calls the [onSend()][networking/Response::onSend()] signal. ```javascript res.onSend(function(){ console.log("Response has been sent"); }); res.send(Networking.Response.OK, {user: 'Max', age: 43}); ``` send: (status, data) -> assert.ok @request.pending if not data? and typeof status isnt 'number' data = status status = @status if status? assert.ok utils.has(Response.STATUSES, status) @status = status if data isnt undefined @data = data @request.destroy() {data} = @ Impl.send @, data, => @pending = false @onSend.emit() return ## Response::redirect(*Integer* status = `Response.FOUND`, *String* uri) The *Response.FOUND* status is typically used for the temporary redirection. The *Response.MOVED* for is a permanent redirection. redirect: (status, uri) -> if uri is undefined uri = status status = Response.FOUND assert.ok @request.pending assert.ok utils.has(Response.STATUSES, status) assert.isString uri log "#{status} redirect to '#{uri}'" @status = status @setHeader 'Location', uri @request.destroy() Impl.redirect @, status, uri, => @pending = false @onSend.emit() ## Response::raise(*Any* error) Finishes the response with an error. ```javascript res.raise(new Networking.Response.Error("Login first")); res.raise(new Networking.Response.Error(Networking.Response.UNAUTHORIZED, "Login first")); ``` raise: (error) -> if error instanceof Response.Error or isFinite(error?.status) @send error.status, error else @send Response.INTERNAL_SERVER_ERROR, error ## *Boolean* Response::isSucceed() Returns `true` if the response status is in range from 200 to 299. isSucceed: -> 300 > @status >= 200 # Glossary - [Networking.Response](#class-response)