Documentation
Context
Context is the only parameter that middleware receives and contains all the information available at this point of the request:
name | example | type |
---|---|---|
.options | { port: 3000, public: 'public' } |
Object |
.data | { firstName: 'Francisco '} |
Object |
.params | { id: 42 } |
Object |
.query | { search: '42' } |
Object |
.session | { user: { firstName: 'Francisco' } } |
Object |
.headers | { 'Content-Type': 'application/json' } |
Object |
.cookies | { acceptCookieLaw: true } |
Object |
.files | { profilepic: { ... } } |
Object |
.ip | '192.168.1.1' |
String |
.url | '/cats/?type=cute' |
String |
.method | 'GET' |
String |
.path | '/cats/' |
String |
.secure | true |
Boolean |
.xhr | false |
Boolean |
It can appear at several points, but the most important one is as a middleware parameter:
// Load the server from the dependencies
const server = require('server');
// Display "Hello 世界" for any request
const middleware = ctx => {
// ... (ctx is available here)
return 'Hello 世界';
};
// Launch the server with a single middleware
server(middleware);
.options
An object containing all of the parsed options used by server.js. It combines environment variables and explicit options from server({ a: 'b' });
:
const mid = ctx => {
expect(ctx.options.port).toBe(3012);
};
/* test */
const res = await run({ port: 3012 }, mid, () => 200).get('/');
expect(res.status).toBe(200);
If we have a variable set in the .env
or through some other environment variables, it'll use that instead as environment options take preference:
# .env
PORT=80
const mid = ctx => {
expect(ctx.options.port).toBe(7693);
};
/* test */
const res = await run({ port: 7693 }, mid, () => 200).get('/');
expect(res.status).toBe(200);
.data
This is aliased as body
as in other libraries. It is the data sent with the request. It can be part of a POST or PUT request, but it can also be set by others such as websockets:
const middle = ctx => {
expect(ctx.data).toBe('Hello 世界');
};
// Test it (csrf set to false for testing purposes)
run(noCsrf, middle).post('/', { body: 'Hello 世界' });
run(middle).emit('message', 'Hello 世界');
To handle forms sent normally:
//- index.pug
form(method="POST" action="/contact")
input(name="email")
input(name="_csrf" value=csrf type="hidden")
input(type="submit" value="Subscribe")
Then to parse the data from the back-end:
const server = require('server');
const { get, post } = server.router;
const { render, redirect } = server.reply;
server([
get(ctx => render('index.pug')),
post(ctx => {
console.log(ctx.data); // Logs the email
return redirect('/');
})
]);
.params
Parameters from the URL as specified in the route:
const mid = get('/:type/:id', ctx => {
expect(ctx.params.type).toBe('dog');
expect(ctx.params.id).toBe('42');
});
// Test it
run(mid).get('/dog/42');
They come from parsing the ctx.path
with the package path-to-regexp
. Go there to see more information about it.
const mid = del('/user/:id', ctx => {
console.log('Delete user:', ctx.params.id);
});
.query
The parameters from the query when making a request. These come from the url fragment ?answer=42&...
:
const mid = ctx => {
expect(ctx.query.answer).toBe('42');
expect(ctx.query.name).toBe('Francisco');
};
// Test it
run(mid).get('/question?answer=42&name=Francisco');
.session
After following the sessions in production tutorial, sessions should be ready to get rolling. This is an object that persist among the user refreshing the page and navigation:
// Count how many pages the visitor sees
const mid = ctx => {
ctx.session.counter = (ctx.session.counter || 0) + 1;
return ctx.session.counter;
};
// Test that it works
run(ctx).alive(async ctx => {
await api.get('/');
await api.get('/');
const res = await api.get('/');
expect(res.body).toBe('3');
});
.headers
Get the headers that were sent with the request:
const mid = ctx => {
expect(ctx.headers.answer).toBe(42);
};
// Test it
run(mid).get('/', { headers: { answer: 42 } });
.cookies
Object that holds the cookies sent by the client:
const mid = ctx => {
console.log(ctx.cookies);
};
run(mid).get('/');
.files
Contains any and all of the files sent by a request. It would normally be sent through a form with an <input type="file">
field or through a FormData
in front-end javascript:
<form method="POST" action="/profilepic" enctype="multipart/form-data">
<input name="profilepic" type="input">
<input type="hidden" name="_csrf" value="{{_csrf}}">
<input type="submit" value="Send picture">
</form>
Note the csrf token and the enctype="multipart/form-data"
, both of them needed. Then to handle it with Node.js:
const mid = post('/profilepic', ctx => {
// This comes from the "name" in the input field
console.log(ctx.files.profilepic);
return redirect('/profile');
});
.ip
The IP of the client. If your server is running behind a proxy, it uses the de-facto standard x-forwarded-for
header to get the right client IP:
const mid = ctx => {
console.log(ctx.ip);
};
run(mid).get('/');
It can be useful with services like geoip-lite
to find the user's location:
// Localize user depending on their IP
const geoip = require('geoip-lite');
module.exports = ctx => {
ctx.geo = geoip.lookup(ctx.ip);
};
// {
// range: [ 3531655168, 3531657215 ],
// country: 'JP',
// region: '24',
// eu: '0',
// timezone: 'Asia/Tokyo',
// city: 'Yokkaichi',
// ll: [ 34.9667, 136.6167 ],
// metro: 0,
// area: 50
// }
.url
The full cuantified URL:
const mid = ctx => {
expect(ctx.url).toBe('/hello?answer=42');
};
run(mid).get('/hello?answer=42');
.method
The request method, it can be GET
, POST
, PUT
, DELETE
:
const mid = ctx => {
expect(ctx.method).toBe('GET');
};
// Test it
run(mid).get('/');
Or other methods:
const mid = ctx => {
expect(ctx.method).toBe('POST');
};
// Test it
run(noCsrf, mid).post('/');
.path
Only the path part from the URL. It is the full URL except for the query:
const mid = ctx => {
expect(ctx.path).toBe('/question');
};
// Test it
run(mid).get('/question?answer=42');
.secure
Returns true if the request is made through HTTPS. Take into account that if you are behind Cloudflare or similar it might be reported as false even though your clients see https
:
const mid = ctx => {
expect(ctx.secure).toBe(false);
};
// Test it
run(mid).get('/');
.xhr
A boolean set to true if the request was done through AJAX. Specifically, if X-Requested-With
is “XMLHttpRequest”
:
const mid = ctx => {
expect(mid.xhr).toBe(false);
};
run(mid).get('/');
Keep reading
List of all the topics: