Skip to content

Commit

Permalink
Contextualize cookies. Closes hapijs#3987
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Dec 28, 2019
1 parent 50d8d7d commit 783987e
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 22 deletions.
35 changes: 15 additions & 20 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -2673,8 +2673,7 @@ across multiple requests. Registers a cookie definitions where:

- `options` - are the optional cookie settings:

- `ttl` - time-to-live in milliseconds. Defaults to `null` (session time-life - cookies are
deleted when the browser is closed).
- `ttl` - time-to-live in milliseconds. Defaults to `null` (session time-life - cookies are deleted when the browser is closed).

- `isSecure` - sets the 'Secure' flag. Defaults to `true`.

Expand All @@ -2685,50 +2684,46 @@ across multiple requests. Registers a cookie definitions where:
- `false` - no flag.
- `'Strict'` - sets the value to `'Strict'` (this is the default value).
- `'Lax'` - sets the value to `'Lax'`.
- `'None'` - sets the value to `'None'`.

- `path` - the path scope. Defaults to `null` (no path).

- `domain` - the domain scope. Defaults to `null` (no domain).

- `autoValue` - if present and the cookie was not received from the client or explicitly set by
the route handler, the cookie is automatically added to the response with the provided value.
The value can be a function with signature `async function(request)` where:
- `autoValue` - if present and the cookie was not received from the client or explicitly set by the route handler, the cookie is automatically added to the response with the provided value. The value can be a function with signature `async function(request)` where:

- `request` - the [request object](#request).

- `encoding` - encoding performs on the provided value before serialization. Options are:

- `'none'` - no encoding. When used, the cookie value must be a string. This is the default
value.
- `'none'` - no encoding. When used, the cookie value must be a string. This is the default value.
- `'base64'` - string value is encoded using Base64.
- `'base64json'` - object value is JSON-stringified then encoded using Base64.
- `'form'` - object value is encoded using the _x-www-form-urlencoded_ method.
- `'iron'` - Encrypts and sign the value using
[**iron**](https://github.com/hueniverse/iron).
- `'iron'` - Encrypts and sign the value using [**iron**](https://github.com/hueniverse/iron).

- `sign` - an object used to calculate an HMAC for cookie integrity validation. This does not
provide privacy, only a mean to verify that the cookie value was generated by the server.
Redundant when `'iron'` encoding is used. Options are:
- `sign` - an object used to calculate an HMAC for cookie integrity validation. This does not provide privacy, only a mean to verify that the cookie value was generated by the server. Redundant when `'iron'` encoding is used. Options are:

- `integrity` - algorithm options. Defaults to
[`require('iron').defaults.integrity`](https://github.com/hueniverse/iron#options).
- `integrity` - algorithm options. Defaults to [`require('iron').defaults.integrity`](https://github.com/hueniverse/iron#options).
- `password` - password used for HMAC key generation (must be at least 32 characters long).

- `password` - password used for `'iron'` encoding (must be at least 32 characters long).

- `iron` - options for `'iron'` encoding. Defaults to
[`require('iron').defaults`](https://github.com/hueniverse/iron#options).
- `iron` - options for `'iron'` encoding. Defaults to [`require('iron').defaults`](https://github.com/hueniverse/iron#options).

- `ignoreErrors` - if `true`, errors are ignored and treated as missing cookies.

- `clearInvalid` - if `true`, automatically instruct the client to remove invalid
cookies. Defaults to `false`.
- `clearInvalid` - if `true`, automatically instruct the client to remove invalid cookies. Defaults to `false`.

- `strictHeader` - if `false`, allows any cookie value including values in
violation of [RFC 6265](https://tools.ietf.org/html/rfc6265). Defaults to `true`.
- `strictHeader` - if `false`, allows any cookie value including values in violation of [RFC 6265](https://tools.ietf.org/html/rfc6265). Defaults to `true`.

- `passThrough` - used by proxy plugins (e.g. [**h2o2**](https://github.com/hapijs/h2o2)).

- `contextualize` - a function using the signature `async function(definition, request)` used to override a request-specific cookie settings where:

- `definition` - a copy of the `options` to be used for formatting the cookie that can be manipulated by the function to customize the request cookie header. Note that changing the `definition.contextualize` property will be ignored.
- `request` - the current request object.

Return value: none.

State defaults can be modified via the [server.options.state](#server.options.state) configuration
Expand Down
2 changes: 1 addition & 1 deletion lib/headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ exports.state = async function (request) {
return;
}

let header = await request._core.states.format(states);
let header = await request._core.states.format(states, request);
const existing = response.headers['set-cookie'];
if (existing) {
header = (Array.isArray(existing) ? existing : [existing]).concat(header);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@hapi/podium": "3.x.x",
"@hapi/shot": "4.x.x",
"@hapi/somever": "2.x.x",
"@hapi/statehood": "6.x.x",
"@hapi/statehood": "7.x.x",
"@hapi/subtext": "6.x.x",
"@hapi/teamwork": "3.x.x",
"@hapi/topo": "3.x.x"
Expand Down
18 changes: 18 additions & 0 deletions test/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,22 @@ describe('state', () => {
expect(res.statusCode).to.equal(200);
expect(res.headers['set-cookie']).to.equal(['a=b; Secure; HttpOnly; SameSite=Strict']);
});

it('sets cookie value based on request', async () => {

const server = Hapi.server();

const contextualize = (definition, request) => {

definition.isSameSite = request.query.x;
definition.isSecure = false;
};

server.state('a', { contextualize });
server.route({ method: 'GET', path: '/', handler: (request, h) => h.response('ok').state('a', 'b') });

const res = await server.inject('/?x=TEST');
expect(res.statusCode).to.equal(200);
expect(res.headers['set-cookie']).to.equal(['a=b; HttpOnly; SameSite=TEST']);
});
});

0 comments on commit 783987e

Please sign in to comment.