restify / node-restify Goto Github PK
View Code? Open in Web Editor NEWThe future of Node.js REST development
Home Page: http://restify.com
License: MIT License
The future of Node.js REST development
Home Page: http://restify.com
License: MIT License
I like the logging of error responses:
2011-11-24 18:35:00Z WARN: ErrorSent(requestId=095b86af-d734-4ee5-99bf-9156f4eedc92): HttpCode=500, RestCode=InternalError, message=error determining account for 'admin':
InternalError: error determining account for 'admin'
at EventEmitter.<anonymous> (/Users/trentm/widget.js:292:33)
at EventEmitter.emit (events.js:64:17)
...
and I want to use res.sendError
for all my error responses for the common response formatting:
{
"code": "ResourceNotFound",
"message": "no such login: 'adminasdf'"
}
However, I'd like to NOT bother logging the response and stack for some error responses, e.g. a simple 404 for some cases. Would you be amenable to a "noLog" boolean to skip logging on a one-off? If so, I can impl. it.
So instead of newError({httpCode: 409}), we can do newError({httpCode: HTTP.Conflict});
I'm seeing a response like this:
HTTP/1.1 406 Not Acceptable
...
Access-Control-Expose-Headers: X-Api-Version, X-Request-Id, X-Response-Time
Date: Thu, 10 Nov 2011 00:27:01 GMT
X-Request-Id: ea4ca8a5-c827-4cf7-baa0-5e7111d7eaea
Content-MD5: FEGnkJwIfbvnzlmIG534uQ==
Access-Control-Allow-Origin: *
X-Response-Time: 1
Connection: Keep-Alive
Access-Control-Allow-Methods: OPTIONS
Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Date, X-Api-Version
Content-Length: 15
[object Object]
That might be an old restify tho, not sure.
X-Request-Id: CEAE078D-2E96-4FEF-ABDA-A4FA2AC15D94
Automagically figure this out in the framework based on defined routes.
Hi
I'm just getting to grips with Restify and all is looking nice so far apart from the following issue.
The issue I'm currently facing is that I'd like to serve dynamic images using a route e.g /image/myimageid. I've got it serving png's for chrome (chrome sends the wildcard * / * accept header) however I'm hitting issues with firefox and IE as they send Accept headers as follows:
image/png,image/;q=0.8,/*;q=0.5"
which is causing the following 400 response:
{"code":"InvalidArgument","message":"Accept header invalid: image/png,image/* ;q=0.8,* / *;q=0.5"}
Is there a way to allow these accept types to be accepted by restify??? I've looked at passing them in as options on createServer but this doesn't seem to work e.g
var server = restify.createServer({
accept: [
"image/png",
"image/;q=0.8",
" * /;q=0.5"
]
});
Thanks
Some users want regex's, even though we sort of don't want them in core. If the match function is a "plugin", problem solved.
Don't send back/check API versions if not set, and if it is, we really don't need a separate "enforce" param.
I'm unable to install the latest version of restify - or at least the version of code seen on github.
npm install restify
installs version 0.5.6
Attempting to
npm install restify@1.0.0
finds no such version.
Attempting to
npm install https://github.com/mcavage/node-restify.git
results in an error.
The same is true of downloading the zip from github and npm installing that.
I might be doing something wrong, but I haven't come across this before. I'd love to work with the latest version if it's available - it looks like that could be v1.0.0?
Enforce a configurable clock skew.
Running a basic server on Linux (code below) works for about 5-10 seconds, then crashes with "Bad system call"
var restify = require('restify');
var server = restify.createServer();
server.get("/foo",function(req,res,next){
console.log("hello");
res.write("hello");
res.end();
});
server.listen(8090);
....
hello
hello
hello
Bad system call
Do you have any plans on supporting eTags?
I don't think I would be that difficult, I'm happy to see if I can get this working...
Hey,
I have been stupid at some point - either now or when I suggested pull request #33. I have been playing around with my custom content writer and the only way I seem to be able to call it within the scope of the response object (for access to _code etc) is to explictly do (at around line 85 of http_extra.js):
else if (this._config.contentWriters[this._accept]) {
var fn = this._config.contentWriters[this._accept];
data = fn.call(this, _opts.body); //use .call() to force the scope
}
Other than doing this, I seem to be having no luck due to all the references and mayhem with scopes that are going on elsewhere.
If you agree that this is the way to go then I will ping you a pull request (and even make sure its got semi-colons where needed!)
Cheers,
Ben
npm ERR! Not compatible with your version of node/npm: [email protected] npm ERR! Required: {"node":"~0.4"} npm ERR! Actual: {"npm":"1.0.14","node":"v0.5.4"}
Hi,
Does restify not work with node 0.5? I think it should.
Hey Mark,
Great work with restify - we are moving a lot of our current API centric apps across to using restify from express. One thing I'd love some flexibility on is the ability to have the req.body contain the JSON parsed object rather than automatically mapping those values across to the req.params object.
I'm not sure what the default behaviour should be, but it is something that tripped me up on the move over from Express. Perhaps if the body parser initialisation accepted some options for initialization that allowed you to specify whether you wanted parameter mapping on or off, e.g.
server.use(restify.jsonBodyParser({ mapParams: true }));
Thanks,
Damon.
Let errors marshall back an arbitrary thing of the application's choosing for extra data.
Just looking at using pre handlers to authenticate but I seem to have hit a stumbling block.
I have test code as follows which is marked as a pre handler for a route:
function authenticate(req, res, next) {
console.log("authentication");
models.User.findOne({email: "[email protected]"}, function(err, user){
console.log("getAuthenticatedUser");
return next();
})
}
This seems to cause the request to hang so I guess it's to do with calling return next() in the callback - am I doing something wrong?? is there a way to do this currently?
Thanks
I have a restify server and have NOT specified a formatError callback. With code like the following to respond with an error for one of my server's endpoints:
if (!zone) {
var e = restify.newError({
httpCode: HttpCodes.Conflict,
restCode: RestCodes.MissingParameter,
message: "'zone' is a required parameter"
});
res.sendError(e)
return next();
}
and the response is:
HTTP/1.1 409 Conflict
Connection: close
Date: Thu, 10 Nov 2011 00:46:09 GMT
Server: Joyent
X-Api-Version: 1.0.0
X-Request-Id: dc4aae6f-7877-4fe1-97a1-363946646c56
X-Response-Time: 3
Content-Length: 97
Content-MD5: 6t3n7nTlQh/SN9/cZ5QtLg==
Content-Type: application/json
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: OPTIONS, GET, HEAD
Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Date, X-Api-Version
Access-Control-Expose-Headers: X-Api-Version, X-Request-Id, X-Response-Time
{
"code": {
"httpCode": 409,
"message": "MissingParameter"
},
"message": "'zone' is a required parameter"
}
Mark said "well that's fucked up."
It would be nice to have a configuration option for suppressing MD5 digest calculation in case of performance-sensitive usage with large entities.
Thanks!
I wanted to write a complete application using restify, which would be mostly a webservice, but with a few (2-3) client. The issue is that I am unable to server simple static resources using restify as it automatically json-encodes them.
If file test.html
contains 1234
Then
server.get('/',function(req,res){
fs.readFile('test.html','utf-8',function(err,data){
if(err){
res.send(100,{msg:"There was an error in handling your request"});
err.next();
}
else{
console.log(data);
res.send(200,data,{'Content-Type':'text/html; charset=utf-8'});
}
});
});
gives me "1234\n" as the output on opening localhost:8080/
on the browser.
I was able to make this work by following the example in http://mcavage.github.com/node-restify/restify-response.7.html but I feel that it should be easier to send simple html responses. (Instead of going around res.write
)
While playing with cloudapi... I set the server time back an hour without restarting the restify server. As a result I hit the throttling error response for every request:
$ sdc-listmachines
You have exceeded your request rate of 10 r/s.
After restarting the server, everything was fine. I wonder however if there is a DST issue here. Perhaps something like:
if the curr time is waay off from the last time you checked ... or went backwards then: reset()
Hi again :)
I'm trying to use restify.createClient to connect to Blip's (twitter-like site) API and for unknown reason callback's body is empty.
Code:
var client = restify.createClient({
url: 'http://api.blip.pl:80',
contentType: 'application/json',
headers: {
'x-blip-api': '0.02',
accept: 'application/json'
}
});
client.get('/tags/bieganie', function (err, body, headers, res) {
if (err)
return console.log(err);
console.log('Body: ', body);
console.log('Res.body: ', res.body);
console.log('Headers: ', headers);
});
Gives me:
Body: {}
Res.body: [{"type":"Status","created_at":"2011-07-06 22:38:25","body":"#Bi (.............) ":"www","id":6}}]
Headers: { date: 'Wed, 06 Jul 2011 20:59:13 GMT',
server: 'Apache/2.2.3 (Debian) Phusion_Passenger/2.2.11',
'x-powered-by': 'Phusion Passenger (mod_rails/mod_rack) 2.2.11',
etag: '"95f97da75aa49a4ab421f2161398bee6"',
'x-runtime': '17',
'cache-control': 'private, max-age=0, must-revalidate',
'content-length': '4113',
status: '200',
connection: 'close',
'content-type': 'application/json; charset=utf-8' }
Test with CURL:
piotrus@dragonus:/www/ideas/blibi$ curl -v -H'Accept: application/json' -H'X-Blip-api: 0.02' http://api.blip.pl:80/tags/bieganie
* About to connect() to api.blip.pl port 80 (#0)
* Trying 91.197.13.170... connected
* Connected to api.blip.pl (91.197.13.170) port 80 (#0)
> GET /tags/bieganie HTTP/1.1
> User-Agent: curl/7.21.0 (i686-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18
> Host: api.blip.pl
> Accept: application/json
> X-Blip-api: 0.02
>
< HTTP/1.1 200 OK
< Date: Wed, 06 Jul 2011 21:09:06 GMT
< Server: Apache/2.2.3 (Debian) Phusion_Passenger/2.2.11
< X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 2.2.11
< ETag: "95f97da75aa49a4ab421f2161398bee6"
< X-Runtime: 37
< Cache-Control: private, max-age=0, must-revalidate
< Content-Length: 4113
< Status: 200
< Connection: close
< Content-Type: application/json; charset=utf-8
<
[{"type":"Status","created_at":"2011-07-06 22:38:25","body":"#Bi(....................)#bieganie","transport_description":"WWW","user_path":"/users/piotrekmitura","id":590558657,"transport":{"name* Closing connection #0
What's the reason why body parameter is empty? Is this caused by this service response or am I doing something wrong?
Running the sample code:
var restify = require('restify');
var server = restify.createServer();
server.get('/my/:name', function(req, res) {
res.send(200, {
message: 'Hello ' + req.uriParams.name
});
});
server.listen(8080);
causes:
TypeError: Cannot read property 'exceptionHandler' of undefined
at Object.createServer (/home/kcbanner/local/node/lib/node_modules/restify/lib/restify.js:439:17)
at [object Context]:1:25
at Interface.<anonymous> (repl.js:171:22)
at Interface.emit (events.js:64:17)
at Interface._onLine (readline.js:153:10)
at Interface._line (readline.js:408:8)
at Interface._ttyWrite (readline.js:585:14)
at ReadStream.<anonymous> (readline.js:73:12)
at ReadStream.emit (events.js:81:20)
at ReadStream._emitKey (tty_posix.js:307:10)
Using node 0.4.7.
Great work, I've just finished my API but now i want to put a placeholder webpage for the ones who visits the root.
I've managed to send text fine but when i try to serve images or another binaries it crashes...
any idea on how to solve this? or how to bind this to a static server like node-static at the same port as restify?
thanks.
Greetings,
Is it any way to handle upload with Restify? I've tried following curl request
curl -F [email protected] http://localhost:8080/upload
And it works fine with standard node-formidable manual code.
But with Restify i can't do that.
server.post('/upload', function(request, response) {
request.on('file', function() { // "end" doesn't work either, callback never called
console.log(arguments);
});
});
server.post('/upload', function(request, response) {
console.log(arguments); // no files in any request properties
});
Another problem is, why user does not have access to variable "form" which comes from formidable "incomingForm" to (for example) listen some events.
If I'm too stupid to understand upload handle with restify, please tell me that :)
Shouldn't get that. :)
I got this when hitting an endpoints with PUT, when only GET is defined for it.
I have been using restify since 0.5.x and while using it I made a few mistakes, like setting non valid semver api version and because of that, now with rangeVersioning it would be nice to have a way to fix those requests before they are routed.
Actual process: Routing -> run sever.use chain -> run route
Process needed: Pre Routing Chain -> Routing -> run sever.use chain -> run route
Like this:
var checkAPIVersion = function(req, res, next) {
if (req.path == "/a/nice/path" && !req.headers['x-api-version'])
req.headers['x-api-version'] = "1.1.0";
if(req.headers['x-api-version'] == "1.1")
req.headers['x-api-version'] = "1.1.0";
return next();
};
And then run the routing.
Right now it's a static list of HEAD/GET/PUT/POST/DELETE. Should be dynamically generated off the routes on that particular URL.
The "next" function should be able to take an error as its first argument. This is really handy, because then next() can be passed as a callback to functions where all you care about is that it didn't fail.
Here's what I'm doing now to work around it:
doSomething(arg, arg, arg, function (er) {
if (er) {
res.sendError(newError({
httpCode: er.statusCode || 500,
restCode: RestCodes.InternalError,
message: er.message
});
}
return next();
});
It'd be better to just do this:
doSomething(arg, arg, arg, next);
If you create a route, and pass in something like foo="bar / foo" restify will fail to parse that and throw a 404. it appears to be parsing the route and including any "/" found in query params.
var restify = require('restify');
var server = restify.createServer();
server.get("/", function(req,res){
console.log("hello");
res.write("hello");
res.end();
});
server.listen(8090);
if you call it like this, you'll never see the request as restify will 404 it:
Cause of isaacs/npm#926
{code}
2011-11-22 23:13:42Z TRACE: GET /pub/trent.mick route found -> { method: 'GET',
url: '/pub/:login',
regex: false,
handlers:
{ pre: [ [Function: setup] ],
post: [ [Function: w3cLog] ],
main: [ [Function: getAccount] ] },
version: '1.0.0',
semver: true,
urlComponents: [ 'pub', ':login' ] }
2011-11-22 23:13:42Z TRACE: _parseRequest: params parsed as: {}
XXX login is 'trent'
XXX req.uriParams is: { login: 'trent' }
{code}
MarkC said:
oh crap.
i remember what this was now.
this was some goofy shit to handle .json or .xml at the end.
i.e. if you specified /foo/type that would allow /foo/type.json /foo/type.xml, etc.
and override the content-type, but make sure the uriParam was 'type'.
grr...
Please add the ability to disable logger altogether, and to make it take any output stream
16:42:59
Mark Cavage
if you would, file a restify bug ;)
that should throw a typeerror
it's probably just checking that it's not undefined, and not doing a typeof
16:43:20
Isaac Schlueter
awesome
16:43:30
Mark Cavage
sorry :\
16:43:41
Isaac Schlueter
or, it should treat strings as {path: theString}
client.get("foo" is a nice pattern
16:43:58
Mark Cavage
yes, that would be friendlier.
so, yeah, i can definitely do that. that's nicer for sure.
16:44:35
Isaac Schlueter
posting issue now
The Restify docs http://mcavage.github.com/node-restify/restify-versions.7.html state that a 'Retry with an x-api-version header' should be sent back along with the 449 error. However, that is not the case.
Sample response:
{ stack: [Getter/Setter],
arguments: undefined,
type: undefined,
_isError: true,
name: 'HttpError',
httpCode: 449,
restCode: 'UnknownError',
message: 'Unknown error occured.',
details: ...
}
It's me again, the string length vs. byte size error ;-)
Hi,
I've tried to connect to restify server via browser's XMLHttpRequest. To do that for each request I'm manually adding headers needed by CORS (Access-Control-Allow-(Origin|Methods|Headers)). But I've encountered error with preflighted requests which are handled by restify automatically. For those requests browser sends Content-Type: application/json header but receives no Access-Control-Allow-Headers so it fails.
As a fast hack I've added in server.js:426 line like:
headers['Access-Control-Allow-Headers'] = 'Content-Type';
but of course this is not a god way. Unfortunately it seems there is no other at this time.
IMHO there should be option to set headers globally in options parameter. Because now the only way I've found to deal with CORS is adding headers option in each response.send call. Global server setting will help with this and also with preflighted requests.
I also want to say that we've got in Poland SSJS DevCamp, we've tested a lot of node modules and we've really liked Yours :) Thank You.
If you try the guide suggested approach to a DELETE
request with a 204
status code:
server.del('hello/:name', function rm(req, res, next) {
res.send(204);
return next();
});
you get a response status code of 200
instead of the desired 204
, and a response
body
of 204
, literally. So, either docs are incorrect, or code is not behaving as
expected :-)
Complete test case to illustrate it here: https://gist.github.com/1711761
I installed restify via npm which got me the latest version - v0.5 and put together a simple test:
var mod_rest = require('restify')
That ended up erroring with:
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
ReferenceError: util is not defined
at Object. (/home/rm/src/node-mplayer/node_modules/restify/lib/error.js:23:1)
at Module._compile (module.js:402:26)
at Object..js (module.js:408:10)
at Module.load (module.js:334:31)
at Function._load (module.js:293:12)
at require (module.js:346:19)
at Object. (/home/rm/src/node-mplayer/node_modules/restify/lib/restify.js:3:14)
at Module._compile (module.js:402:26)
at Object..js (module.js:408:10)
at Module.load (module.js:334:31)
I was able to get it to seemingly work by adding the following to lib/error.js with the other module declarations:
var util = require('util');
Not sure if this is something weird I'm doing with npm configuration or otherwise.
Users want to be able to have first-class separation of params like:
/path/:foo from ?foo=bar.
This is restify 1.0 (https://github.com/mcavage/node-restify/tarball/master#0dfba4fdfd9def5111c29dffd241f344ff1293a8).
...
server.get("/foo.txt", function (req, res, next) {
filed('tmp/foo.txt').pipe(res);
next();
});
...
where "filed" is node-filed. The client does not get the "foo.txt" contents before the connection is closed, although the headers look right.
$ curl -iSs http://0.0.0.0:8080/foo.txt
HTTP/1.1 200 OK
content-type: application/octet-stream
etag: 5138fda15066d6ef868a67d3328b72d6
last-modified: Fri, 20 Jan 2012 16:30:33 -0800
Connection: keep-alive
Transfer-Encoding: chunked
$
No need to do what we're doing right now, as it doesn't play nice with express.
Use semver version matching and add version-specific routing.
Right now the max amount of data is hard-coded. Also, validate that it is correct when Content-Length is not specified.
2011-07-10 18:21:53Z INFO: RestClient...
2011-07-10 18:21:53Z INFO: RestClient...
But moments later...
$date -u
August 10, 2011 06:27:40 PM GMT
Hi!
I want to stream a file to my API but I find no way to handle the Content-Type validation. Despite the fact that I add a new Content-Type to the "accept" server configuration (I know - not useful yet :D) I have no possibility to pass the content type control to handle the request.
Is there a way to skip the content-type validation if it's not implemented yet?
Example:
var restify = require('restify'); var server = restify.createServer({ accept: ['application/json', 'application/x-chess-pgn'] }); server.post('/pgn', function(req, res, next) { res.send(200, { success: true }); return next(); }) server.listen(3020);
curl -i -T test.pgn -H "Content-Type: application/x-chess-pgn" -X POST http://localhost:3020/pgn
HTTP/1.1 415 Unsupported Media Type Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST Content-Type: application/json (...) {"code":"InvalidArgument","message":"application/x-chess-pgn unsupported"}
I'm using the restify client to talk to CAPI. Say CAPI is down (nothing listening on that port)... currently with retries and no timeout that means that with the current (apparently) 75 second timeout on hitting ... it ends up being 5 minutes before my request attempt comes back with RestCodes.RetriesExceeded.
Is there something like this in restify?
Aside: I see there is one reference to "minTimeout" on "retryOptions" in client.js... not used?
14.13 Content-Length
The Content-Length entity-header field indicates the size of the entity-body, in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
Hi!
Following use case: If I use the same prehandler for multiple request types, e.g. for checking if a requested resource exists, I want to send an error with res.sendError(...). While this is correct for GET routes, it will create an "[HttpError: Content-Length 62 didn't match: 0]" error with HEAD.
Example:
var restify = require('restify');
var server = restify.createServer();
function handler(req, res, next) {
res.send(200);
}
function pre(req, res, next) {
res.sendError(restify.newError({
httpCode: 404
}));
}
server.head('/test', [pre], handler);
server.get('/test', [pre], handler);
server.listen(3000);
var client = restify.createClient({
url: 'http://localhost:3000',
retryOptions: { retries: 0 }
});
client.head('/test', function(err, headers, res) {
if (err) {
console.log(err);
}
});
will return:
{ [HttpError: Content-Length 62 didn't match: 0]
_isError: true,
name: 'HttpError',
httpCode: 500,
restCode: { httpCode: [Getter], message: [Getter] },
message: 'Content-Length 62 didn\'t match: 0',
headers:
{ connection: 'close',
date: 'Fri, 23 Dec 2011 21:33:48 GMT',
server: 'node.js',
'x-request-id': '6738b428-d152-4bbb-a44b-0a4016d97a5d',
'x-response-time': '2',
'content-length': '62',
'content-md5': 'U8+IRkYtzh/Ck7k6mGUxrA==',
'content-type': 'application/json',
'access-control-allow-origin': '*',
'access-control-allow-methods': 'OPTIONS, HEAD, GET',
'access-control-allow-headers': 'Accept, Content-Type, Content-Length, Date, X-Api-Version',
'access-control-expose-headers': 'X-Api-Version, X-Request-Id, X-Response-Time' } }
When the clients requests per GET everything is fine.
I know that I could check which type of request it is in the handler and use a res.send(404) for HEADs. But it would be nice and more simple if it would be checked automatically.
Merry Christmas,
Falco
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.