I have an express API with a bunch of routes.
routes.get('/', perms('read', 'document'), r(CRUD.getAll))
routes.get('/search', perms('read', 'document'), r(CRUD.search))
routes.get('/:id', perms('read', 'document'), r(CRUD.getById))
I made sure to have /search above /:id, however, when a new request comes in to /search, I see both endpoints getting a hit (I added a console.log inside of each function).
I tried flipping the two and in that case, only /:id gets a hit.
Any idea of why this may be happening?
Think about Express routing as an array of handlers (middlewares), that have a matching rule (url). When a request comes in, the router starts checking each item in the array from the beginning. If it matches the rule, then the handler is run (some don't have conditions, so they just run on each request :)). The request chain does not end when a single url is matched! You can execute multiple handlers on the same request (and that's exactly how middlewares work).
Therefore, it really depends on what happens inside your handler. You can tell it to continue with the next item in the list, and if there's a match - the next handler will be executed (like /search and /:id, which will be search again).
Make sure you end your response. Beware if you call next and with what parameters. Post some samples of the handlers in order to debug it more :)
Related
I am looking for some advice on how to design the code to handle the fulfillment of requests sent by Dialogflow to my server. Dialogflow only lets setup a single webhook to handle all the intents. Let's say that I have 5 different intents; all of them will call the same webhook on my server. Now, how can I elegantly manage server-side different workflows depending on the intent?
The parameter that I would ideally use to make a distinction is contained in req.body.queryResult.intent.displayName; and indicates the name of the current intent. Right now I have two ideas, using express redirect method using the intent as part of the path, or creating a dictionary of handlers where the intents are the key.
Do you have any suggestions?
The dialogflow-fulfillment library, although deprecated, uses your latter approach - creating a Map from Intent name to Handler function and handing this map to a Dispatcher. It is a simple, straightforward, and speedy approach.
The multivocal library takes a similar, tho more expansive, approach, letting you register a handler against either the Intent name or the Action value assigned and having separate configurations for the response based on either Intent, Action, or another value that is set in the handler.
Redirecting to a new, path-based, method does not seem to give you anything.
I am very new to express.js and am reading through the documentation. I understand that the purpose of the next parameter in express middleware is to invoke the subsequent middleware function for the given route. I had assumed that next() was a function defined in the express API. However, the documentation specifically says the following:
Notice the call above to next(). Calling this function invokes the next middleware function in the app. The next() function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The next() function could be named anything, but by convention it is always named “next”. To avoid confusion, always use this convention.
What confuses me about next is that it doesn't appear to be defined anywhere, and so the claim that it is not part of the API is odd. The only thing I can think of is that express automatically rewrites next to be the subsequent middleware function behind the scenes (passes it as the third argument to the first middleware callback function).
My question is essentially this-- I know what next does, but exactly is it?
The next parameter is a callback provided by Express. It's a function that takes one parameter which indicates whether the next middleware function should be proceeded to.
If you pass a non-null/non-undefined value to next it indicates an error and no further processing happens.
If you pass no parameter or null then the Express continues to the next thing it will do.
To answer your question, next is a callback function provided by Express that controls when Express should move along to the next step. Its implementation is internal to Express.
Note that if your middleware is finishing the request (say by calling res.json("done!")) then you don't need to call next at all since there's nothing more to do.
As you noted, the name of the function is local at this point and can be called anything, but is usually called next.
Just want to say at the beginning. I'm really sorry if you will consider this as a duplicate but I'd like to ask you what is the middleware. I know stackoverflow has some similar questions but I'd be glad if you could answer this one. Also what is the .use ? Where do we use it? Thank you very much!
Middleware is a term that refers to request handlers that "pre-process" an incoming request. A given middleware will typically run on lots of incoming requests. Usually, it doesn't send the final response, it just does some setup or pre-processing on the request and then passes the request on to its eventual handler. There are thousands on things that people find to do with middleware.
The general idea is that it's easier to put middleware in one place and configure it to apply to lots of requests rather than have to add it to every single request handler that its supposed to apply to.
I'll offer a few examples:
Check to see if the requester is authenticated/loggedin on the site. If not, then redirect to the login page. If so, then pass the request through to the actual page request handler.
Log usage or performance statistics.
Pre-parse query parameters so they're already parsed for the request handler
Pre-parse post bodies so they're already parsed for the request handler
Preset desired cross origin headers for the response
Hopefully, you can see the general idea that middleware is often used as pre-setup work that can be done in one place rather than having to be added to every single request handler.
Keep in mind that middleware can be configured to determine which incoming requests it gets run for. It can be only for a single URL (not typical), a whole group of URLs such as everything start with a particular path, or all URLs on the entire site.
The scenario is to save the data in cache. We have numerous express routes written with complicated logic.
I have to find a way to save the response data in cache. I cannot go to each and every route and check whether this needs to be saved and save the data before sending the response. (If no other go, then this may be the way)
I have tried the following approaches.
https://nodejs.org/api/http.html#http_event_close_1 - using 'close' or 'finish', which fires after sending the response would do the trick. But there is no way I could get the response data in these events.
Also my node version is v0.10.31
Thought of using app.all('*', callback), but i am not sure how to catch the response data for cacheing.
Finally i thought of adding a second callback for routing, app.VERB(path, [callback...], callback), but upon returning the response in first callback, second callback is never called.
Hoping there is a solution for this, and I am stuck in this for more than a week.
The reason why adding logic into each and every routes is a tedious job is that, I need to add a configuration entry specifying which route needs to be cached with an expiry time.
Response needs to be cached in redis server. A cache key will be generated based on the route data and query strings. All those complete user specific information will be saved in a key.
So when the user hits the same route the key will be generated to check if it already exists using app.use and the data will be served without precedding to the successive middlewares.
Define a callback middleware as,
var storeResponseMiddleware = function(req, res, next) {
console.log("storing data in redis....")
..........more stuff
}
Add it to expressJs app as,
app.use(logicRoute)
app.use(storeResponseMiddleware)
Now, for all the responses storeResponseMiddleware will be called. you must call next() inside the route handlers.
I'm having an issue with the domain module. Currently, I'm trying to catch any uncaught errors that are thrown in a request. Using an express middleware and domains. All requests are routed through this function before calling next and moving on to it's proper route.
app.use (req, res, next) ->
domain = createDomain()
domain.on "error", (err) ->
res.send(500)
domain.dispose()
domain.enter()
next()
The problem is, how do I dispose of the domain if an error is never thrown?
I could hoist the domain and event outside the middlewear so I don't ever have to dispose, but then I won't have access to middlewear args that I need to send a 500.
Does anyone have a better solution to how I am handling this? I've spent way too much time trying to figure out a way (and many hacky ways) to handle this. Thanks.
You do not need to call domain.dispose() if no errors occurred. The purpose of domain.dispose() is to clean up any resources that were left in an indeterminate state after jumping out out the middle of the stack, and to squelch subsequent errors that would occur due to the bad state. The inverse call of domain.enter() is simply domain.exit().
That said, browsing through the code for domains, it looks like you don't want to use domain.enter/exit this way. Each domain.enter/exit corresponds to a stack push/pop of a shared array in the domain module code. So, for example, if a second request comes in before the first one has completed, and then the first one exits before the second one does, calling exit in the first domains handler will pop the domain for the second request. It seems quite likely that enter and exit should not be split across asynchronous things.
Have you tried simply using domain.run(next)? That seems to do the trick for me. It basically enters the domain for you and then calls the callback you give to it, and then immediately exits the domain after the callback returns. Any timers or event emitters created while you are in the domain will associate themselves with that domain, as well. Event emitters then also use a similar enter-call-exit pattern when calling event handlers. It appears in the code that it is not domains that track event handlers, but rather event handlers that track domains.
In short, don't try to pair an enter with a dispose, and don't try to use enter/exit across asynchronous boundaries. Use run/bind/add/remove.