Express Middleware is nothing more than a function with one of
two signatures: function (request, response, next)
, or function (error, request, response, next)
. Let's talk about
the first, and most basic signature first.
The request
object provides all the details about the user's request, including any data they've provided. As an
example of what middleware typically does, the fluid.express.middleware.bodyparser.json
and
fluid.express.middleware.bodyparser.urlencoded
grades included with this package inspect the original request, break
down information found there, and add variables that present the same data in a more usable form. See below for details.
The response
object gives you a way to send information (headers, content) back to the user. A lot of what we refer to
as middleware in this package doesn't make use of the request
, but the original request will only receive a response
if some piece of middleware eventually makes use of the response
object.
The next
function gives your middleware control over whether processing should continue. At the time it is given a
chance to process a request
, each piece of middleware is aware of the next piece of middleware in the chain. It can
do one of three things with this:
- Not call the
next
function (ending the conversation, presumably after sending something to the user using theresponse
object). - Call the
next
function with anerror
argument (see "Error Handling Middleware" below), indicating that an error was encountered by this piece of middleware. - Call the
next
function with no arguments, allowing the next piece of middleware to start its work.
A middleware function with the alternate signature function (error, request, response, next)
is designed to respond to
an error
passed to the next
function by a piece of upstream middleware. Once an error is thrown, only middleware
with this signature is given the chance to respond. As with the above, each piece of error handling middleware has the
chance to decide whether to allow additional error handlers to respond after it has completed its work. To allow
downstream error handlers to respond, a piece of errorMiddleware must pass along the error
it received, typically by
calling next(error)
.¯
As each link in the chain gets to decide whether the remaining links will even get to see a particular request, the order in which middleware is called is very important. This package uses namespaces and priorities to control the order in which middleware is called.
Unless you are only working with a single router or piece of middleware, it is strongly recommended that you use this
mechanism to ensure that your middleware is called at the right time. Take a look at this example, which might be found
inside a fluid.express
or fluid.express.router
instance:
components: {
cookie: {
type: "fluid.express.middleware.cookieparser",
options: {
priority: "first"
}
},
session: {
type: "fluid.express.middleware.session",
options: {
priority: "after:cookie"
}
},
router: {
type: "my.router.grade",
options: {
priority: "after:session"
}
}
}
In this example, we have explicitly ordered our middleware. First, we ensured that cookies are parsed first, so that the session middleware will be able to find its cookie and look up the user's data. We have also placed our router after all middleware, to ensure that our router only sees requests that already have cookie and session data.
Note that we were only able to use priorities like after:session
and after:cookie
because the "wrapper" grades
included with this package include priorities. When writing your own middleware or routers, best practice is to include
a distinct namespace option in your grade definition.
The base grade you will extend to define your own middleware. An instance of fluid.express
or fluid.express.router
will automatically attempt to wire a component with this grade name into itself. To use this grade, you must implement
the middleware
invoker (see below).
Option | Type | Description |
---|---|---|
method |
{String} |
This grade provides the ability to limit itself to only operate on requests that match a particular HTTP method. Support lowercased string values, such as get , post , put , or delete . Defaults to use , or "any method". |
path |
{String} or {Array} |
Which part(s) of the relative URL space this router wants to work with. May contain wildcards and path variables. Defaults to / , or "any path". |
namespace (optional) |
{String} |
The namespace to use when ordering other middleware relative to this one, as in after:<namespace> . |
priority (optional) |
{String} |
The priority of this middleware relative to other pieces of middleware (see "Ordering Middleware by Priority" above). |
Please note that although middleware may also be limited to a particular method
or path
, it does not do any routing
at all to child components. Only the middleware itself will be given the chance to work with an appropriate response.
Routing is only handled by fluid.express
and fluid.express.router
components.
request {Object}
An Express Request object (see the docs for details).response {Object}
An Express Response object (see the docs for details).next
: The next Express middleware or router function in the chain.- Returns: Nothing.
This function is called when your middleware is given the chance to work with an individual request. An invoker definition for standard middleware might look something like:
invokers: {
middleware: {
funcName: "your.namespaced.function",
args: ["{that}", "{arguments}.0", "{arguments}.1", "{arguments}.2"] // request, response, next
}
}
If you want to define a middleware that handles errors (see above), you would simply use a different invoker definition, as in:
invokers: {
errorMiddleware: {
funcName: "your.namespaced.errorFunction",
args: ["{that}", "{arguments}.0", "{arguments}.1", "{arguments}.2", "{arguments}.3"] // error, request, response, next
}
}
For a reference example of an error handler, see the "error handler" middleware docs.
The base grade for all "wrapped" third-party middleware, such as fluid.express.middleware.cookieparser
,
fluid.express.middleware.urlencoded
and fluid.express.middleware.json
(see below).
Option | Type | Description |
---|---|---|
middlewareOptions |
{Object} |
The configuration options to pass on to the underlying third-party middleware. |
middlewareImpl |
{Function} |
The underlying third-party middleware function which will field all requests. |
request {Object}
An Express Request object (see the docs for details).response {Object}
An Express Response object (see the docs for details).next
: The next Express middleware or router function in the chain.- Returns: Nothing.
Passes through request
, response
, and next
to the underlying middleware implementation, which is expected to be
found at middleware.options.middlewareImpl
. You must provide your own middlewareImpl
to use this grade, as
demonstrated in the following example:
var fluid = require("infusion");
fluid.require("%fluid-express");
fluid.require("third-party-middleware", require, "my.middleware.npm.thirdPartyMiddleware");
fluid.defaults("my.middleware.wrapper", {
gradeNames: ["fluid.express.middleware.wrappedMiddleware"],
middlewareImpl: "@expand:my.middleware.npm.thirdPartyMiddleware({that}.middlewareOptions)"
});
This example assumes that the third-party-middleware
package exports its constructor, and that it accepts
configuration options as its only argument. The expander will take care of creating the middlewareImpl
option,
and the middleware
invoker will use this middleware to handle incoming requests.
Parses client cookie headers and makes them available via request.cookies
. Wraps the standard
cookie parser middleware previously bundled with Express.
Option | Type | Description |
---|---|---|
middlewareOptions |
{Object} |
The configuration options to pass on to cookie parser middleware. See the cookie-parser docs for more details. |
middlewareOptions.secret |
{Object} |
The only required configuration option within the above. Defines a secret key that will be used to sign the session cookie. |
Parses JSON data passed by the client and makes it available via request.body
. Wraps part of the body parser
middleware previously bundled with Express.
Option | Type | Description |
---|---|---|
middlewareOptions |
{Object} |
The configuration options to pass on to the underlying JSON body parser instance. |
Parses client session cookies makes server-side session data associated with the cookie available via
request.sesssion
. Wraps the standard session middleware previously bundled
with Express. Requires the cookieparser
middleware above to be in the middleware chain before it.
Option | Type | Description |
---|---|---|
middlewareOptions |
{Object} |
The configuration options to pass on to the underlying express-session instance. |
middlewareOptions.secret |
{Object} |
The only required configuration option within the above. Defines a secret key that will be used to sign the session cookie. |
Parses URL encoded data passed by the client and makes it available via request.query
. Wraps part of the
body parser middleware previously bundled with Express.
Option | Type | Description |
---|---|---|
middlewareOptions |
{Object} |
The configuration options to pass on to the underlying JSON body parser instance. |
See the "error handler" middleware documentation.
See the "header setter" middleware documentation.
See the contentAwareMiddleware
documentation.
See the requestAwareMiddleware
documentation.
See the "redirect" middleware documentation.