UNPKG

sleeprest

Version:

Resource driven REST server.

138 lines (106 loc) 3.16 kB
# Little response placeholder class SleepHttpError extends Error constructor: (@statusCode, @message) -> @name = "MyCustomError" Error.captureStackTrace(this, SleepHttpError) module.exports = class Response constructor: (req) -> @req = req @options = {} # Default headers @headers = 'Content-Type': 'application/octet-stream' @_status = 200 @body = null # HAL! (Do it anyway, in the end we will see # whether or not hall is enabled) @_links = self: href: req.url.match(/(.*\/[^/]+)\/?$/)?[1] or '/' parents = @_links.self.href.split('/').slice(0, -1) if parents.length > 0 @_links.parent = href: '/' + parents.join('/') @_embedded = {} # Used by the latest resource that recieves the bound request setBody: (promise) -> promise.then (body) => if not body? body = {} if body.statusCode? @status body.statusCode delete body.statusCode @body = body this .catch (err) => if @options.debug console.log 'Error in Sleep Response:' console.log err.stack if (match = err.message.match /^HTTP:(\d{3}) (.*)$/)? [..., status, message] = match err.statusCode = +status # Type conversion err.message = message @status err.statusCode or 500 @body = message: err.message this require: (object, key) -> if not object[key]? throw new "Required '#{key}' not present!" object[key] # Easy error spawning throw: (status, message) -> if typeof status is 'string' message = status status = 400 # Throw it, so it will /most likely/ bubble to setBody console.log 'Throwing', status, message throw new SleepHttpError status, message # Easy set response status and headers header: (name, value) -> if not value? return @headers[name] @headers[name] = value this # Chaining status: (status) -> if not status? return @_status @_status = status this # Chaining # HAL Helpers embed: (rel, obj, list=false) -> if list container = @_embedded[rel] ||= [] container.push obj else @_embedded[rel] = obj link: (rel, href, opts) -> opts ||= {} link = href: href if opts.templated link.templated = true if opts.list (@_links[rel] ||= []).push link else @_links[rel] = link # Send te response to a http response object applyTo: (res) -> res.statusCode = @_status for header, value of @headers res.setHeader header, value # If it is a stream or a non-object, just send it and do nothing else if @body.pipe? @body.pipe res return else if typeof @body isnt 'object' res.end @body return # If it is an object, HAL-ify it! if @body instanceof Array @body = item: @body # Using json for now, makes things easier for clients res.setHeader 'Content-Type', 'application/json' # If HAL, add HAL if @options.hal @body._links = @_links @body._embedded = @_embedded res.end JSON.stringify @body