Comparing version 0.5.0 to 0.6.0
@@ -0,0 +0,0 @@ 'use strict'; |
'use strict'; | ||
module.exports = require('./lib/Apx') |
@@ -100,2 +100,8 @@ 'use strict'; | ||
/** | ||
* File Object | ||
* @type {Function} | ||
*/ | ||
Apx.prototype.File = require('./File') | ||
/** | ||
* Initial config schema | ||
@@ -324,3 +330,3 @@ * @type {*} | ||
if('object' === typeof item && !util.isArray(item) && 'string' !== typeof item){ | ||
self.sysLog.info('Loading object directly (' + item.name + ')') | ||
self.sysLog.debug('Loading object directly (' + item.name + ')') | ||
iterator(item,finish) | ||
@@ -341,7 +347,7 @@ /** | ||
){ | ||
self.sysLog.info('Loading package (' + item + ')') | ||
self.sysLog.debug('Loading package (' + item + ')') | ||
iterator(require(item),finish) | ||
//try to resolve the path with glob | ||
} else { | ||
self.sysLog.info('Trying to glob path (' + item + ')') | ||
self.sysLog.debug('Trying to glob path (' + item + ')') | ||
glob(item,{cwd: cwd},function(err,files){ | ||
@@ -352,3 +358,3 @@ if(err) throw err | ||
function(file,next){ | ||
self.sysLog.info('Loading package from path (' + self.resolvePath(file) + ')') | ||
self.sysLog.debug('Loading package from path (' + self.resolvePath(file) + ')') | ||
iterator(require(self.resolvePath(file)),next) | ||
@@ -395,3 +401,3 @@ }, | ||
if(self.config.exists('middleware')){ | ||
self.sysLog.info('Running ' + position + ' middleware for action ' + action.name + ':' + method) | ||
self.sysLog.debug('Running ' + position + ' middleware for action ' + action.name + ':' + method) | ||
self.loadItems( | ||
@@ -420,3 +426,3 @@ self.config.get('middleware'), | ||
var runAction = function(next){ | ||
self.sysLog.info('Running action ' + action.name + ' : ' + method) | ||
self.sysLog.debug('Running action ' + action.name + ' : ' + method) | ||
emitter.emit('runActionBefore',action) | ||
@@ -460,3 +466,3 @@ action[method](self,req,res,function(err){ | ||
req = new this.Request(req) | ||
this.sysLog.info('Running task ' + task.name) | ||
this.sysLog.debug('Running task ' + task.name) | ||
//run task | ||
@@ -478,4 +484,4 @@ emitter.emit('runTaskBefore',task) | ||
if('string' === typeof service) service = require(this.resolvePath(service)) | ||
this.sysLog.info('Returning new service instance for ' + service.name) | ||
return new service.module() | ||
this.sysLog.debug('Returning new service instance for ' + service.name) | ||
return new service.service() | ||
} | ||
@@ -492,5 +498,5 @@ | ||
if(!this.services[service.name]){ | ||
this.services[service.name] = new service.module() | ||
this.services[service.name] = new service.service() | ||
} | ||
this.sysLog.info('Returning service instance for ' + service.name) | ||
this.sysLog.debug('Returning service instance for ' + service.name) | ||
return this.services[service.name] | ||
@@ -497,0 +503,0 @@ } |
'use strict'; | ||
var ObjectManage = require('object-manage') | ||
, util = require('util') | ||
, File = require('./File') | ||
@@ -16,2 +17,16 @@ /** | ||
/** | ||
* Reference to an incoming file object should be set by the translator | ||
* @type {Array} | ||
*/ | ||
Request.prototype.files = [] | ||
/** | ||
* Add file to the request by path | ||
* @param path | ||
*/ | ||
Request.prototype.addFile = function(path){ | ||
this.files.push(new File(path)) | ||
} | ||
module.exports = Request |
'use strict'; | ||
var ObjectManage = require('object-manage') | ||
, util = require('util') | ||
, SysLog = require('./SysLog') | ||
, File = require('./File') | ||
, mmm = require('mmmagic') | ||
, magic = new mmm.Magic(mmm.MAGIC_MIME_TYPE) | ||
, sysLog = require('./SysLog') | ||
@@ -13,7 +16,6 @@ /** | ||
var Response = function(data){ | ||
var self = this | ||
ObjectManage.call(this,data) | ||
self.body = '' | ||
self.rendered = '' | ||
self.warnings = [] | ||
this.body = null | ||
this.mimeType = null | ||
this.file = null | ||
} | ||
@@ -23,16 +25,18 @@ util.inherits(Response,ObjectManage) | ||
/** | ||
* String containing raw response data | ||
* Mime type of the body response | ||
* @type {string} | ||
*/ | ||
Response.prototype.body = '' | ||
Response.prototype.mimeType = null | ||
/** | ||
* Rendered result of .send() | ||
* String containing raw response data | ||
* @type {string} | ||
*/ | ||
Response.prototype.rendered = '' | ||
Response.prototype.body = null | ||
/** | ||
* Warnings from rendering | ||
* @type {Array} | ||
* Reference to an outgoing file object that the translator should consume | ||
* @type {null} | ||
*/ | ||
Response.prototype.warnings = [] | ||
Response.prototype.file = null | ||
@@ -44,53 +48,119 @@ /** | ||
Response.prototype.add = function(content){ | ||
if('object' === typeof content){ | ||
this.load(content) | ||
} else if('string' === typeof content){ | ||
this.body = this.body + content | ||
if('string' !== typeof content){ | ||
throw new Error('Add only works with strings') | ||
} | ||
if('string' !== typeof this.body) this.body = '' | ||
this.body = this.body + content | ||
} | ||
/** | ||
* Send content to client | ||
* @param content Optional (will call .add(content) and then send()) | ||
* @returns {*} | ||
* Convenience method to call success | ||
* @param [message] message to send instead of success or an object containing additional params | ||
* @param [code] Code to be sent defaults to 0 | ||
* @param [obj] Object to be sent with the response | ||
*/ | ||
Response.prototype.send = function(content){ | ||
if(undefined === content){ | ||
this.rendered = JSON.stringify(this.data) | ||
if('{}' === this.rendered) this.rendered = '' | ||
//warn if sending a combo response | ||
if(this.body !== '' && this.rendered !== '') | ||
this.warn('JSON and String body rendered') | ||
this.rendered = this.rendered + this.body | ||
} else { | ||
this.add(content) | ||
this.send() | ||
Response.prototype.success = function(message,code,obj){ | ||
if('number' === typeof message){ | ||
code = message | ||
message = undefined | ||
} | ||
if('number' !== typeof code && 'object' === typeof code){ | ||
obj = code | ||
code = undefined | ||
} | ||
if('string' !== typeof message && 'object' === typeof message){ | ||
obj = message | ||
message = undefined | ||
} | ||
if(!code) code = 0 | ||
this.set('status','ok') | ||
this.set('code',code.toString()) | ||
this.set('message','success') | ||
if('string' === typeof message) | ||
this.set('message',message) | ||
if('object' === typeof obj) | ||
this.load(obj) | ||
} | ||
/** | ||
* Convenience method to call success | ||
* Convenience method to throw an error | ||
* @param [message] | ||
* @param [code] | ||
* @param [obj] | ||
*/ | ||
Response.prototype.success = function(){ | ||
this.send({status: 'ok', message: 'success'}) | ||
Response.prototype.error = function(message,code,obj){ | ||
if('number' === typeof message){ | ||
code = message | ||
message = undefined | ||
} | ||
if('number' !== typeof message && 'string' !== typeof message){ | ||
obj = message | ||
message = undefined | ||
} | ||
if(!message) message = 'error' | ||
if('string' !== typeof message) message = util.inspect(message) | ||
if(!code) code = 1 | ||
if('number' !== typeof code && 'object' === typeof code){ | ||
obj = code | ||
code = 1 | ||
} | ||
this.set('status','error') | ||
this.set('message',message) | ||
this.set('code',code.toString()) | ||
if(obj && 'object' === typeof obj) | ||
this.load(obj) | ||
} | ||
/** | ||
* Convenience method to throw an error | ||
* @param message | ||
* Prepare response to send a file | ||
* @param path Path to the file to be read | ||
* @param [opts] Options to be passed to the file object | ||
*/ | ||
Response.prototype.error = function(message){ | ||
if('string' !== typeof message) message = util.inspect(message) | ||
this.send({status: 'error', message: util.inspect(message)}) | ||
Response.prototype.sendFile = function(path,opts){ | ||
this.file = new File(path,opts) | ||
} | ||
/** | ||
* Internal warnings about rendering and parsing | ||
* @param message | ||
* Render response to be prepared for translation | ||
* @param next Callback function | ||
*/ | ||
Response.prototype.warn = function(message){ | ||
SysLog.warn('Response: ' + message,2) | ||
this.warnings.push(message) | ||
Response.prototype.render = function(next){ | ||
var self = this | ||
//check for a file | ||
if(null !== self.file){ | ||
self.file.populate(function(){ | ||
next(null,{ | ||
format: 'file', | ||
file: self.file, | ||
mimeType: self.file.mimeType | ||
}) | ||
}) | ||
} else if(null === self.mimeType && null !== self.body){ | ||
magic.detect(new Buffer(self.body),function(err,mimeType){ | ||
if(err){ | ||
sysLog.warn('Could not detect mime type of body: ' + err) | ||
mimeType = 'application/octet-stream' | ||
} | ||
self.mimeType = mimeType | ||
next(null,{ | ||
format: 'raw', | ||
body: self.body, | ||
mimeType: mimeType | ||
}) | ||
}) | ||
} else if(null !== self.mimeType && null !== self.body){ | ||
next(null,{ | ||
format: 'raw', | ||
body: self.body, | ||
mimeType: self.mimeType | ||
}) | ||
} else { | ||
next(null,{ | ||
format: 'object', | ||
data: self.data, | ||
mimeType: self.mimeType || 'text/json' | ||
}) | ||
} | ||
} | ||
module.exports = Response |
@@ -0,0 +0,0 @@ 'use strict'; |
@@ -0,0 +0,0 @@ The MIT License (MIT) |
{ | ||
"name": "apx", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "A scalable, extensible, modular API Server", | ||
@@ -41,3 +41,6 @@ "homepage": "https://github.com/snailjs/apx", | ||
"object-manage": "~0.6.0", | ||
"async": "~0.2.9" | ||
"async": "~0.2.9", | ||
"temp": "~0.6.0", | ||
"mime": "~1.2.11", | ||
"mmmagic": "~0.3.5" | ||
}, | ||
@@ -44,0 +47,0 @@ "devDependencies": { |
228
README.md
@@ -6,3 +6,3 @@ [SnailJS](//github.com/snailjs/).[APX](//github.com/snailjs/apx/) | ||
![Logo](snail-apx.png) | ||
![Logo](http://static.yucache.net/a4e63438eea25b486f1b41979ed12f0ef98b391f?client_file_id=688861) | ||
@@ -167,3 +167,4 @@ ## APX API Server | ||
* **stop** -- Used in initializers and translators to stop instances / listeners, and shutdown cleanly | ||
* **module** -- Used in helpers, models and services to export object to be used | ||
* **pre** -- Used in middleware to be executed before the action | ||
* **post** -- Used in middleware to be executed after the action | ||
@@ -183,3 +184,3 @@ ### Actions | ||
exports.description = 'description of model' //verbose description for generating maps | ||
exports.module = {} //object exported by the helper can also be a constructor | ||
exports.helper = {} //object exported by the helper can also be a constructor | ||
``` | ||
@@ -201,3 +202,8 @@ | ||
exports.description = 'description of middleware' //verbose description for generating maps | ||
exports.run = function(apx,req,res,next){} //constructor function with a prototype for instantiation | ||
//pre only | ||
exports.run = function(apx,req,res,next){} //constructor function with a prototype for instantiation (for pre run only) | ||
//-- or -- | ||
//pre and post | ||
exports.pre = function(apx,req,res,next){} //run this function before the action | ||
exports.post = function(apx,req,res,next){} //runt this function after the action | ||
``` | ||
@@ -210,3 +216,4 @@ | ||
exports.description = 'description of model' //verbose description for generating maps | ||
exports.module = {} //model object created by desired database software | ||
exports.schema = {} //schema used to create the model | ||
exports.model = {} //model object created by desired database software | ||
``` | ||
@@ -219,3 +226,3 @@ | ||
exports.description = 'description of service' //verbose description for generating maps | ||
exports.module = function(){} //constructor function with a prototype for instantiation | ||
exports.service = function(){} //constructor function with a prototype for instantiation | ||
``` | ||
@@ -553,4 +560,213 @@ | ||
## Request and Response Objects | ||
In APX the request and response objects create the common layer that translators iterate. They are instances of | ||
[object-manage](https://github.com/snailjs/object-manage) and expose all the available methods. These objects, | ||
however, **are not streams**. This is a limitation in some cases but it is the only to make the call stack for | ||
middleware usable. | ||
Nearly all API servers implement commands and it is up to the translator to supply any uploaded files which should | ||
be written to temporary files using a tool like [formidable](https://github.com/felixge/node-formidable). After | ||
that the action can direct the file to the correct location or transfer it to a storage cluster. | ||
The request and response objects support a file object that points to an incoming temporary file or a file that should | ||
be streamed to a file. | ||
If there is a situation where file support is more important than command support then raw stream iteration should be | ||
implemented in the translator. It is easy to take existing translators and modify them in userspace. | ||
### Request | ||
The request object contains information that is passed along from the request paths from the translator and is supplied | ||
in object notation. Thus, `req.get('propertyName')` is the most common usage to retrieve information. However to allow | ||
for the receiving of files there is a `req.files` array that shall be populated with files that were written to | ||
temporary files during the request. | ||
In order to access parts of the translator for more control over specific access mediums like the HTTP server the raw | ||
request object shall be provided via `req.raw` | ||
Example | ||
```js | ||
exports.name = 'myAction' | ||
exports.description = 'Example Action' | ||
exports.run = function(apx,req,res,next){ | ||
req.get('foo') //bar | ||
req.raw.query.foo //bar | ||
res.success() | ||
next() | ||
} | ||
``` | ||
#### Add File | ||
As a convenience for translators to add files to the request object the `addFile()` method exists. | ||
Example | ||
```js | ||
var req = new Request() | ||
req.addFile('foo.txt') | ||
req.addFile('bar.txt') | ||
``` | ||
### Response | ||
The response object is built by the action and middleware which is then passed on to the user through the translators | ||
desired output format. In most cases the output format is JSON but this is sometimes configurable at the translator | ||
level. | ||
#### Add Body Content | ||
To allow the sending of raw data rather than JSON or any other format that can be transformed from an object the `add()` | ||
method comes in handy. | ||
Example | ||
```js | ||
exports.name = 'myAction' | ||
exports.description = 'Example Action' | ||
exports.run = function(apx,req,res,next){ | ||
res.add('content to show') | ||
res.add('more content to show') | ||
next() | ||
} | ||
``` | ||
#### Success | ||
As a convenience method `success()` exists to signal success to the client. This method uses a standard response format. | ||
That resembles the following. Success also accepts a few argument combinations to allow more structured responses | ||
without additional function calls. | ||
Format | ||
```json | ||
{"status": "ok", "message": "success", "code": "0"} | ||
``` | ||
Example | ||
```js | ||
exports.name = 'myAction' | ||
exports.description = 'Example Action' | ||
exports.run = function(apx,req,res,next){ | ||
res.success() //sends message: 'success', code: '0' | ||
res.success('foo') //sends message: 'foo', code: '0' | ||
res.success('foo',4) //send message: 'foo', code: '4' | ||
res.success('foo',4,{id: 'bar'}) //sends message: 'foo', code: '4', id: 'bar' | ||
res.success('foo',{id: 'bar'}) //sends message: 'foo', code: '0', id: 'bar' | ||
res.success({id: 'bar'}) //sends message: 'success', code: '0', id: 'bar' | ||
next() | ||
} | ||
``` | ||
#### Error | ||
For easier error handling the error method can be used to pass an erroneous response to the client and accepts a | ||
few different combinations of arguments to supply the user with information about the error. | ||
Format | ||
```json | ||
{"status": "error", "message": "error", "code": "1"} | ||
``` | ||
Example | ||
```js | ||
exports.name = 'myAction' | ||
exports.description = 'Example Action' | ||
exports.run = function(apx,req,res,next){ | ||
res.error() //sends message: 'An error has occurred', code: '1' | ||
res.error('foo') //sends message: 'foo', code: '1' | ||
res.error('foo',4) //send message: 'foo', code: '4' | ||
res.error('foo',4,{id: 'bar'}) //sends message: 'foo', code: '4', id: 'bar' | ||
res.error('foo',{id: 'bar'}) //sends message: 'foo', code: '1', id: 'bar' | ||
res.error({id: 'bar'}) //sends message: 'An error has occurred', code: '1', id: 'bar' | ||
next() | ||
} | ||
``` | ||
#### Send File | ||
Sometimes it is useful to send clients a file thus the `sendFile(path)` method exists. This will notify the translator | ||
that a file should be sent to the user and allows the translator to properly handle streaming the file to the user. | ||
When a file by that path cannot be found it will throw an exception. | ||
**NOTE** Whenever this method is called it will supersede any other output that has been queued to be sent to the user | ||
by using `add()` or `set()`. Unless the translator is capable of sending multipart responses. | ||
Example | ||
```js | ||
exports.name = 'myAction' | ||
exports.description = 'Example Action' | ||
exports.run = function(apx,req,res,next){ | ||
res.sendFile('home.html') | ||
next() | ||
} | ||
``` | ||
#### Render | ||
In order for translators to properly handle sending data to their clients there are 3 scenarios which apply to how | ||
the render function will respond. | ||
* **format** this is the format of the response which will be **object**, **raw**, or **file** | ||
* **mimeType** the detected or manually set mime type of the response should be used to respond in various | ||
formats when using the **object** type. | ||
* **body** this is the content container for the **raw** format | ||
* **data** this is the content container for the **object** format and contains the data object to be exported | ||
* **file** this is a reference to the file object when using the **file** format | ||
#### Example | ||
In this example the output will simply be logged to the console. | ||
```js | ||
var xml = require('xml') | ||
, fs = require('fs') | ||
, Response = require('apx/lib/Response') | ||
, res = new Response() | ||
//create our response handler | ||
var responseHandler = function(err,response){ | ||
if(err) throw err | ||
if('object' === response.format){ | ||
if('text/json' === response.mimeType){ | ||
console.log(JSON.stringify(response.data)) | ||
} else if('text/xml' === response.mimeType){ | ||
console.log(xml(response.data)) | ||
} else { | ||
console.warn('desired output type of ' + response.mimeType + ' is not supported defaulting to JSON') | ||
console.log(JSON.stringify(response.data)) | ||
} | ||
} else if('raw' === response.format){ | ||
console.log(response.body) | ||
} else if('file' === response.format){ | ||
var stream = fs.createReadStream(response.file.path) | ||
stream.on('readable',function(){ | ||
var chunk | ||
while(null !== (chunk = stream.read())){ | ||
console.log(chunk) | ||
} | ||
} | ||
} else { | ||
console.warn('desired output format of ' + response.format + ' is not supported, not sending output') | ||
} | ||
} | ||
//implement the handler | ||
res.render(responseHandler) | ||
``` | ||
## Changelog | ||
### 0.6.0 | ||
* Request objects now implement the file object | ||
* Response objects now implement the file object | ||
* Response.send() removed in favor of the existing **object-manage** functions | ||
* In order to support `pre` and `post` middleware translators need to fire the `Response.render()` method and then send | ||
the rendered response to their client | ||
* Upgraded **middleware**, **model**, **service** and **helper** plugin format. This will require upgrading of existing | ||
plugins and makes this version incompatible with older plugins. | ||
* Added `Response.sendFile(path)` to allow sending of files to the user. Using this method still requires calling `next()` | ||
and will supersede any existing output. | ||
* Improved `Response.success()` and `Response.error()` to accept a better combination of arguments to produce | ||
usable responses with a single function call. | ||
### 0.5.0 | ||
@@ -557,0 +773,0 @@ |
@@ -104,3 +104,3 @@ 'use strict'; | ||
var service = { | ||
module: function(){ | ||
service: function(){ | ||
this.mystuff = 'val1' | ||
@@ -119,3 +119,3 @@ } | ||
var service = { | ||
module: function(){ | ||
service: function(){ | ||
this.mystuff = 'val1' | ||
@@ -122,0 +122,0 @@ } |
'use strict'; | ||
var expect = require('chai').expect | ||
, temp = require('temp') | ||
, fs = require('fs') | ||
, Request = require('../lib/Request') | ||
@@ -35,3 +37,3 @@ describe('APX Request',function(){ | ||
}) | ||
it('should be ale to remove a key and children',function(){ | ||
it('should be able to remove a key and children',function(){ | ||
var req = new Request([data1,data3]) | ||
@@ -41,2 +43,14 @@ req.remove('test5') | ||
}) | ||
it('should allow adding of files from translator',function(){ | ||
var tmpFile1 = temp.openSync() | ||
, tmpFile2 = temp.openSync() | ||
fs.writeSync(tmpFile1.fd,'foo') | ||
fs.writeSync(tmpFile2.fd,'bar') | ||
var req = new Request() | ||
req.addFile(tmpFile1.path) | ||
req.addFile(tmpFile2.path) | ||
expect(req.files[0].path).to.equal(tmpFile1.path) | ||
expect(req.files[1].path).to.equal(tmpFile2.path) | ||
temp.cleanup() | ||
}) | ||
}) |
'use strict'; | ||
var expect = require('chai').expect | ||
, Response = require('../lib/Response') | ||
, temp = require('temp') | ||
, fs = require('fs') | ||
describe('APX Response',function(){ | ||
@@ -14,32 +16,152 @@ describe('methods',function(){ | ||
}) | ||
it('should accept an object to add to the body',function(){ | ||
res.add({mydata: 'val1'}) | ||
it('should accept an object to add to the object',function(){ | ||
res.load({mydata: 'val1'}) | ||
expect(res.get('mydata')).to.equal('val1') | ||
}) | ||
it('should accept an array of objects to add to the body',function(){ | ||
res.add([{mydata: 'val1'},{mydata2: 'val2'}]) | ||
res.load([{mydata: 'val1'},{mydata2: 'val2'}]) | ||
expect(res.get('mydata')).to.equal('val1') | ||
expect(res.get('mydata2')).to.equal('val2') | ||
}) | ||
it('should send and fire the callback',function(){ | ||
res.send('foo') | ||
expect(res.rendered).to.equal('foo') | ||
}) | ||
it('should send JSON of the data object',function(){ | ||
res.send({mydata: 'val1'}) | ||
var obj = JSON.parse(res.rendered) | ||
res.load({mydata: 'val1'}) | ||
var obj = JSON.parse(JSON.stringify(res.get())) | ||
expect(obj.mydata).to.equal('val1') | ||
}) | ||
it('should send body for a string response',function(){ | ||
res.send('foo') | ||
expect(res.rendered).to.equal('foo') | ||
it('should support sending of a file',function(){ | ||
//create a temp file | ||
var tmpFile = temp.openSync() | ||
fs.writeSync(tmpFile.fd,'foo') | ||
res.sendFile(tmpFile.path) | ||
expect(res.file.path).to.equal(tmpFile.path) | ||
temp.cleanup() | ||
}) | ||
it('should send JSON + body if both were set by throw a warning',function(){ | ||
res.add({mydata: 'val1'}) | ||
res.send('foo') | ||
expect(res.warnings[0]).to.equal('JSON and String body rendered') | ||
expect(res.rendered).to.equal('{"mydata":"val1"}foo') | ||
it('should allow sending of success',function(){ | ||
res.success() | ||
expect(res.get('status')).to.equal('ok') | ||
expect(res.get('message')).to.equal('success') | ||
}) | ||
it('should allow sending of success with an object',function(){ | ||
res.success({id: 'foo'}) | ||
expect(res.get('status')).to.equal('ok') | ||
expect(res.get('code')).to.equal('0') | ||
expect(res.get('message')).to.equal('success') | ||
expect(res.get('id')).to.equal('foo') | ||
}) | ||
it('should allow sending of success with a message',function(){ | ||
res.success('foo') | ||
expect(res.get('status')).to.equal('ok') | ||
expect(res.get('code')).to.equal('0') | ||
expect(res.get('message')).to.equal('foo') | ||
}) | ||
it('should allow sending of success with a message and code',function(){ | ||
res.success('foo',2) | ||
expect(res.get('status')).to.equal('ok') | ||
expect(res.get('code')).to.equal('2') | ||
expect(res.get('message')).to.equal('foo') | ||
}) | ||
it('should allow sending of success with a message, code, and object',function(){ | ||
res.success('foo',2,{id: 'foo'}) | ||
expect(res.get('status')).to.equal('ok') | ||
expect(res.get('code')).to.equal('2') | ||
expect(res.get('message')).to.equal('foo') | ||
expect(res.get('id')).to.equal('foo') | ||
}) | ||
it('should allow sending of success with a message and object',function(){ | ||
res.success('foo',{id: 'foo'}) | ||
expect(res.get('status')).to.equal('ok') | ||
expect(res.get('code')).to.equal('0') | ||
expect(res.get('message')).to.equal('foo') | ||
expect(res.get('id')).to.equal('foo') | ||
}) | ||
it('should allow sending of errors',function(){ | ||
res.error() | ||
expect(res.get('status')).to.equal('error') | ||
expect(res.get('message')).to.equal('error') | ||
expect(res.get('code')).to.equal('1') | ||
}) | ||
it('should allow sending of errors with a customer message',function(){ | ||
res.error('foo') | ||
expect(res.get('status')).to.equal('error') | ||
expect(res.get('message')).to.equal('foo') | ||
expect(res.get('code')).to.equal('1') | ||
}) | ||
it('should allow sending of errors with only a code',function(){ | ||
res.error(4) | ||
expect(res.get('status')).to.equal('error') | ||
expect(res.get('message')).to.equal('error') | ||
expect(res.get('code')).to.equal('4') | ||
}) | ||
it('should allow sending of errors with only an object',function(){ | ||
res.error({foo: 'bar'}) | ||
expect(res.get('status')).to.equal('error') | ||
expect(res.get('message')).to.equal('error') | ||
expect(res.get('code')).to.equal('1') | ||
expect(res.get('foo')).to.equal('bar') | ||
}) | ||
it('should allow sending of errors with a messages, code and object',function(){ | ||
res.error('baz',2,{foo: 'bar'}) | ||
expect(res.get('status')).to.equal('error') | ||
expect(res.get('message')).to.equal('baz') | ||
expect(res.get('code')).to.equal('2') | ||
expect(res.get('foo')).to.equal('bar') | ||
}) | ||
it('should allow sending of errors with a message and object',function(){ | ||
res.error('baz',{foo: 'bar'}) | ||
expect(res.get('status')).to.equal('error') | ||
expect(res.get('message')).to.equal('baz') | ||
expect(res.get('code')).to.equal('1') | ||
expect(res.get('foo')).to.equal('bar') | ||
}) | ||
it('should render with an object intended for json',function(done){ | ||
res.success('foo') | ||
res.render(function(err,response){ | ||
expect(response.format).to.equal('object') | ||
expect(response.data.status).to.equal('ok') | ||
expect(response.mimeType).to.equal('text/json') | ||
done() | ||
}) | ||
}) | ||
it('should render with an object intended for xml by setting the mime type manually',function(done){ | ||
res.success('foo') | ||
res.mimeType = 'text/xml' | ||
res.render(function(err,response){ | ||
expect(response.format).to.equal('object') | ||
expect(response.data.status).to.equal('ok') | ||
expect(response.mimeType).to.equal('text/xml') | ||
done() | ||
}) | ||
}) | ||
it('should render a raw response and auto detect the mime type',function(done){ | ||
res.add('foo') | ||
res.render(function(err,response){ | ||
expect(response.format).to.equal('raw') | ||
expect(response.body).to.equal('foo') | ||
expect(response.mimeType).to.equal('text/plain') | ||
done() | ||
}) | ||
}) | ||
it('should render a raw response with a manually set mime type',function(done){ | ||
res.add('{"foo": "bar"}') | ||
res.mimeType = 'text/json' | ||
res.render(function(err,response){ | ||
expect(response.format).to.equal('raw') | ||
expect(response.body).to.equal('{"foo": "bar"}') | ||
expect(response.mimeType).to.equal('text/json') | ||
done() | ||
}) | ||
}) | ||
it('should render a file response and auto detect the mime type',function(done){ | ||
var tmpFile = temp.openSync() | ||
fs.writeSync(tmpFile.fd,'foo') | ||
res.sendFile(tmpFile.path) | ||
res.render(function(err,response){ | ||
expect(response.format).to.equal('file') | ||
expect(response.file).to.be.an('object') | ||
expect(response.mimeType).to.equal('text/plain') | ||
temp.cleanup() | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
100868
21
1309
819
6
11
+ Addedmime@~1.2.11
+ Addedmmmagic@~0.3.5
+ Addedtemp@~0.6.0
+ Addedgraceful-fs@1.2.3(transitive)
+ Addedmime@1.2.11(transitive)
+ Addedmmmagic@0.3.16(transitive)
+ Addednan@2.22.0(transitive)
+ Addedosenv@0.0.3(transitive)
+ Addedrimraf@2.1.4(transitive)
+ Addedtemp@0.6.0(transitive)