src/respond.js

Method respond

Send a response

Parameters:

  • req must be an Object.
    (Request Object)

  • res must be an Object.
    (Response Object)

  • body can be of any type.
    (Primitive, Buffer or Stream)

  • status must be a Number.
    ([Optional] HTTP status, default is 200)

  • headers must be an Object.
    ([Optional] HTTP headers)

  • file must be a Boolean.
    ([Optional] Indicates body is a file path)

Returns an Object
(TurtleIO instance)

TurtleIO.prototype.respond = function ( req, res, body, status, headers, file ) { var self = this, ua = req.headers["user-agent"], encoding = req.headers["accept-encoding"], type; status = status || this.codes.SUCCESS; headers = this.headers( headers || {"Content-Type": "text/plain"}, status, req.method === "GET" ); file = ( file === true ); if ( !headers.Allow ) { headers["Access-Control-Allow-Methods"] = headers.Allow = this.allows( req.parsed.pathname, req.parsed.hostname ); } if ( body ) { body = this.encode( body );

Ensuring JSON has proper mimetype

if ( $.regex.json_wrap.test( body ) ) { headers["Content-Type"] = "application/json"; } if ( req.method === "GET" ) {

CSV hook

if ( status === this.codes.SUCCESS && body && headers["Content-Type"] === "application/json" && req.headers.accept && REGEX_CSV.test( req.headers.accept.explode()[0].replace( REGEX_NVAL, "" ) ) ) { headers["Content-Type"] = "text/csv"; if ( !headers["Content-Disposition"] ) { headers["Content-Disposition"] = "attachment; filename=\"" + req.url.replace( REGEX_NURI, "" ) + ".csv\""; } body = $.json.csv( body ); } } } if ( req.method === "GET" && ( status === this.codes.SUCCESS || status === this.codes.NOT_MODIFIED ) ) {

Ensuring an Etag

if ( !headers.Etag ) { headers.Etag = "\"" + this.etag( req.parsed.href, body.length || 0, headers["Last-Modified"] || 0, body || 0 ) + "\""; }

Updating cache

if ( !$.regex.no.test( headers["Cache-Control"] ) && !$.regex.priv.test( headers["Cache-Control"] ) ) { this.register( req.parsed.href, {etag: headers.Etag.replace( /"/g, "" ), mimetype: headers["Content-Type"]}, true ); }

Setting a watcher on the local path

if ( req.path ) { this.watch( req.parsed.href, req.path, headers["Content-Type"] ); } }

Determining if response should be compressed

if ( status === this.codes.SUCCESS && body && this.config.compress && ( type = this.compression( ua, encoding, headers["Content-Type"] ) ) && type !== null ) { headers["Content-Encoding"] = REGEX_GZIP.test( type ) ? "gzip" : "deflate"; headers["Transfer-Encoding"] = "chunked"; res.writeHead( status, headers ); this.compress( req, res, body, type, headers.Etag.replace( /"/g, "" ), file ); } else if ( file ) { headers["Transfer-Encoding"] = "chunked"; res.writeHead( status, headers ); fs.createReadStream( body ).on( "error", function ( e ) { self.log( e ); self.error( req, res, self.codes.SERVER_ERROR ); } ).pipe( res ); } else { if ( body instanceof Buffer ) { headers["Content-Length"] = body.toString().length; } else if ( typeof body === "string" ) { headers["Content-Length"] = body.length; } res.writeHead( status, headers ); res.end( body ); } return this.log( this.prep( req, res ) ); };