I'm using Express 4.x, and I'm trying to customize the automatically generated OPTIONS response, without having to re-implement all of the functionality that express is already providing for free.
So, for example, if I have PUT and POST handlers registered on /foo, making an OPTIONS call to /foo will return an Allow header with PUT,POST, and a body with the same value. What I am trying to do is to just customize this response. So where express normally returns a body with
PUT,POST
I would like to return something like
{"methods":["PUT","POST"]}
Is there any way to do this without fully re-implementing everything express is doing behind the scenes?
The solution I found was to handle options explicitly on each route, and pull the allowed methods from req.route.methods.
app
.route('/foo')
.post(...)
.put(...)
.options(funtion(req, res, next){
var allowMethods = req.route.methods;
});
Related
I am overall clueless about how and why you set up a node.js app, and how any of the app.use functions work - the tutorials on it don't explain the why of anything.
Anyway, I have socket.io, res.locals and index.js set up like so in the app.js root file.
const sockets = require('./models/socket')(io)
app.use(function (req, res, next) {
res.locals.user_id = req.session.user_id;
next();
});
const routes = require('./routes/index');
app.use('/', routes);
I'd like to be able to access res.locals in the socket.js model, like I can in index.js found in the routes folder.
I can't guess how to go about doing this. If anybody is able to explain how and why I can or can't that would be a bonus. Thanks!
Welcome to Expressjs, there are a few fundamentals you should probably research before going any further, they'll help solve some of your confusion. I'll give a brief explanation of them but I suggest you do further research. I'll then answer your actual question at the end.
Middleware and app.use
Expressjs is built upon an idea that everything is just "middleware". Middleware is a function which runs as part of a request chain. A request chain is essentially a single client request, which then goes through a chain of a number of middleware functions until it either reaches the end of the chain, exits early by returning a response to the client, or errors.
Express middleware is a function which takes the following three arguments.
req (request) - Representing the request made by a client to your
server.
res (response) - Representing the response you will return to
the client.
next - A way of telling express that your current
middleware function is done, and it should now call the next piece of
middleware. This can either be called "empty" as next(); or with an
error next(new Error());. If it is called empty, it will trigger
the next piece of middleware, if it is called with an error then it
will call the first piece of error middleware. If next is not called at the
end of a piece of middleware, then the request is deemed finished and the
response object is sent to the user.
app.use is a way of setting middleware, this means it will run for every request (unless next() is either not called by the previous piece of middleware for some reason, or it's called with an error). This middleware will run for any HTTP request type (GET, POST, PUT, DELETE, etc).
app.use can take multiple arguments, the important ones for beginners to learn are: app.use(func) and app.use(path, func). The former sets "global" middleware which runs no matter what endpoint (url path) the client requests, the latter (with a specific path) is run only if that specific path is hit. I.e. app.use('/hello', (req, res, next) => { res.send('world'); }); will return "world" when the endpoint "/hello" is hit, but not if the client requests "/hi". Where as app.use((req, res, next) => { res.send('world'); }); would return "world" when you hit any endpoint.
There are more complex things you can do with this, but that's the basics of attaching middleware to your application. The order they are attached to the application, is the order in which they will run.
One more thing, this will blow your mind, an express application made with the standard const app = express() can also be used as middleware. This means you can create several express applications, and then mount them using app.use to a single express application. This is pretty advanced, but does allow you to do some really great things with Express.
Why can you not access res.locals in socket.io? (The real question)
Within your middleware handler, you are setting up a res.locals.use_id property. This only lives with that individual request, you can pass it around as long as the request is alive by passing it into other functions, but outside of that request it doesn't exist. res is literally the response object that tells Express how to respond to the clients request, you can set properties of it during the request but once that HTTP request has ended it's gone.
Socket.io is a way of handling web socket requests, not standard HTTP requests. Thus, in a standard express HTTP request you will not be able to hand off the connection to anything with socket.io, because the connection is a single short lived HTTP request. Likewise, you won't be able to do the same the other way.
If you wish to find the users id in a socket.io request, you'll have to do this within the socket.io request itself.
Right now, you're entering a piece of middleware for an Express.js request, you are then calling next() which runs the next piece of express middleware, at no point does it cross over into Socket.io realms. This is often confused by tutorials because Socket.io can handle requests across the same port as Express is listening on, but the two are not crossed over. So you will need to write separate middleware for both Express.js requests chains, and socket.io request chains. There are ways of writing this code once and then writing an adapter to use it across both platforms, but that's not what you've tried to do here.
I would suggest you look at doing just nodejs and express for a time before taking on socket.io as well, otherwise you're trying to learn a whole heap of technologies all at once is quite a lot to try and take on board all at once.
I am working in a Node.js RESTful API project with Express framework.
Every response of APIs has to include the "status" field in the response body, also in the header.
I think that I may have to use a middleware(Express Middleware) to achieve this goal, not containing the "status" by:
res.send({status:200, ...})
From the documentation I understood that there is a middleware to pre-process the requests.
Even I found a question:Connect or Express middleware to modify the response.body but it is to add a normal data.
But I am not sure if there is a middleware to add a specific field to the response body from catching the specific field in the field, the after processing the api requests.
I need your help.
Thanks!
You can just write your own middleware to do it. Here's a simple inline middleware (not refactored to use modules):
app.use(function(req, res, next) {
res.status(200);
next();
});
The above sets the status code to 200 as default to all handlers.
However, I don't think you need to do this as express by default assume a 200 status response. If you find yourself needing to do this then you've got some middleware that's setting the status code to something else.
I'm building a REST backend for an SPA with NodeJS, Restify and PassportJS for authentication. Everything's working except the last step, which is redirecting the client from the backends /login/facebook/callback to the home page of the application.
I've searched online and found lots of answers for ExpressJS but nothing useful for Node-Restify yet. I've managed to pick up a few snippets of code and this is what I'm attempting at the moment:
app.get('/api/v1/login/facebook/cb', passport.authenticate('facebook', { scope: 'email' }), function(req, res) {
req.session.user = req.user._id;
res.header('Location', '/#/home');
res.send();
});
The response is sent but the location header is not included and the client is presented with a white screen. How do I do a proper redirect using the Node-Restify API?
Restify's Response interface now has a redirect method.
As of this writing, there's a test showing how to use it here.
The contents of that test are:
server.get('/1', function (req, res, next) {
res.redirect('https://www.foo.com', next);
});
Many folks who use Restify are more familiar with ExpressJS. It's important to understand that (again, as of this writing) one of the three main public API differences affecting porting of Express plugins is that the res.redirect method in Restify requires you to pass next (or an InternalError is thrown). I've personally ported several modules from Express to Restify and the main API differences at first are (in Restify):
server.use is only for path & HTTP-method-agnostic middleware
res.redirect requires that you pass next
Some members or the Request interface are methods rather than values, such as req.path. req.path is an alias of req.getPath in Restify
I am NOT saying that under-the-hood they are similar, but that the above three things are the main obstacles to porting over Express plugins. Under-the-hood, Restify has many advantages over Express in my experience using it in both large enterprise applications and personal projects.
You need to use redirection status code 302.
res.send(302); or res.send(302, 'your response');
I am pretty new to node and express.js and I'm new to the concept of REST applications as well. I want to code a typical CRUD app, some sort of diary. Hence, I have a collection of entries, can view a single entry and can add, edit and delete an entry.
I'm not quite getting yet, how URi's have to be set up to represent a REST conform API. I would create something like this in my app.js:
// GET REQUEST ROUTING
app.get('/', diary_router.home);
app.get('/entries/', diary_router.listEntries);
app.get('/entries/:id', diary_router.getSingleEntry);
// POST REQUEST ROUTING
app.post('/entries/', diary_router.addEntry);
// PUT REQUEST ROUTING
app.put('/entries/', diary_router.updateEntry);
// DELETE REQUEST ROUTING
app.delete('/entries/', diary_router.deleteEntry);
Could that be called a REST conform interface? Should I rather add the respective action in the routes, such as this and does the item-ID need to be shown in the URL for PUT and DELETE actions, too?:
// GET REQUEST ROUTING
app.get('/', diary_router.home);
app.get('/entries/', diary_router.listEntries);
app.get('/entries/show/:id', diary_router.getSingleEntry);
// POST REQUEST ROUTING
app.post('/entries/add/', diary_router.addEntry);
// PUT REQUEST ROUTING
app.put('/entries/update/:id', diary_router.updateEntry);
// DELETE REQUEST ROUTING
app.delete('/entries/delete/:id', diary_router.deleteEntry);
What would be best practice here? Any help is much appreciated.
B.
In the loose definition of REST that we seem to have converged on in web-land, the first option seems to fit best.
Edit: and yes, you should specify the ID in the PUT and DELETE routes.
HTTP is a really cool protocol for applying verbs (request methods) to nouns (URLs). In that spirit, it's probably best to use the request method to differentiate what you want to do to the resource that you're requesting.
Note: you can use the methodOverride middleware in express if you're worried about browsers not being able to use arbitrary HTTP methods.
The way the methodOverride middleware works is that you use an <input type="hidden" name="_method" value="PUT"> or similar to specify the method, despite it just being a regular POST request, and the methodOverride middleware will set the method property on the request that you get in your express application. This way, you can signal the intended request method without the client actually having to support that method.
I have an api written in node.js that handles calls coming in from websites, desktop applications, iOS applications etc. There are probably 50+ endpoints and each end point can accept anywhere from 1 parameter to possibly 10-20 depending on what is intendeding to be accomplished. These can be GET/POST/PUT/DEL
I want to start load testing my API and simulating users activities.
What I am looking for is suggestions on how you can capture the API call and the parameters that were passed along with it in a logical way.
I use forever to run my app and everything is written to a log file so my initial reaction was to do something like add a piece of middleware to the express routes that would capture the endpoint as well as the req.params and req.body but then I need to put this middleware in all 50+ routes kind of tedious.
Anyone done something like this before and has a good idea on how to capture calls / data with those calls as well as possibly capturing what is returned from my API.
Perhaps some module?
I need to have this in a readable format to provide to other people so they can structure a fake set of calls... so raw log files aren't really helpful unless they are outputted.... "pretty".
Thanks!
You're on the right track – just add your logger middleware via app.use, which runs the middleware on every request (rather than adding it to each route).
In fact, the Express docs give an example of using logger middleware:
var express = require('express');
var app = express();
// simple logger
app.use(function(req, res, next){
console.log('%s %s', req.method, req.url);
next();
});
Connect (on which Express is built) provides logger middleware, so you can just do:
var logFile = fs.createWriteStream('./myLogFile.log', {flags: 'a'});
app.use(express.logger({stream: logFile}));