Skip to content

Commit

Permalink
feat: option disabling parsing in the onRequest phase (#204)
Browse files Browse the repository at this point in the history
* feat: option disabling parsing in the onRequest phase

* fix: revert version

* fix: the test is more accurate

* feat: disable hook or set custom hooks: onRequest, preParsing, preHandler, preValidation

* Update test/cookie.test.js

Co-authored-by: Uzlopak <[email protected]>

* Update test/cookie.test.js

Co-authored-by: Uzlopak <[email protected]>

* Update test/cookie.test.js

Co-authored-by: Uzlopak <[email protected]>

* Update plugin.js

Co-authored-by: Uzlopak <[email protected]>

* fix: test corrected && Error message corrected

* Update types/plugin.d.ts

Co-authored-by: Manuel Spigolon <[email protected]>

* Update test/cookie.test.js

Co-authored-by: Manuel Spigolon <[email protected]>

* Update test/cookie.test.js

Co-authored-by: Manuel Spigolon <[email protected]>

* fix: implementation of suggestions & fix bugs

* fix: change onReqHandlerWrapper for better perfomance && added tests

* Update plugin.js

Co-authored-by: Uzlopak <[email protected]>

* Update plugin.js

Co-authored-by: Uzlopak <[email protected]>

* feat: add test for the new type "HookType"

* Update README.md

Co-authored-by: Uzlopak <[email protected]>

* Update test/cookie.test.js

Co-authored-by: Uzlopak <[email protected]>

* Update test/cookie.test.js

Co-authored-by: Uzlopak <[email protected]>

Co-authored-by: Uzlopak <[email protected]>
Co-authored-by: Manuel Spigolon <[email protected]>
  • Loading branch information
3 people authored Aug 29, 2022
1 parent 9c31275 commit 045f65b
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 12 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ const fastify = require('fastify')()

fastify.register(require('@fastify/cookie'), {
secret: "my-secret", // for cookies signature
parseOptions: {} // options for parsing cookies
hook: 'onRequest', // set to false to disable cookie autoparsing or set autoparsing on any of the following hooks: 'onRequest', 'preParsing', 'preHandler', 'preValidation'. default: 'onRequest'
parseOptions: {} // options for parsing cookies
})

fastify.get('/', (req, reply) => {
Expand Down
43 changes: 35 additions & 8 deletions plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,44 @@ function fastifyCookieClearCookie (reply, name, options) {
return fastifyCookieSetCookie(reply, name, '', opts)
}

function onReqHandlerWrapper (fastify) {
return function fastifyCookieOnReqHandler (fastifyReq, fastifyRes, done) {
fastifyReq.cookies = {} // New container per request. Issue #53
const cookieHeader = fastifyReq.raw.headers.cookie
if (cookieHeader) {
fastifyReq.cookies = fastify.parseCookie(cookieHeader)
function onReqHandlerWrapper (fastify, hook) {
return hook === 'preParsing'
? function fastifyCookieHandler (fastifyReq, fastifyRes, payload, done) {
fastifyReq.cookies = {} // New container per request. Issue #53
const cookieHeader = fastifyReq.raw.headers.cookie
if (cookieHeader) {
fastifyReq.cookies = fastify.parseCookie(cookieHeader)
}
done()
}
done()
: function fastifyCookieHandler (fastifyReq, fastifyRes, done) {
fastifyReq.cookies = {} // New container per request. Issue #53
const cookieHeader = fastifyReq.raw.headers.cookie
if (cookieHeader) {
fastifyReq.cookies = fastify.parseCookie(cookieHeader)
}
done()
}
}

function getHook (hook = 'onRequest') {
const hooks = {
onRequest: 'onRequest',
preParsing: 'preParsing',
preValidation: 'preValidation',
preHandler: 'preHandler',
[false]: false
}

return hooks[hook]
}

function plugin (fastify, options, next) {
const secret = options.secret
const hook = getHook(options.hook)
if (hook === undefined) {
return next(new Error('@fastify/cookie: Invalid value provided for the hook-option. You can set the hook-option only to false, \'onRequest\' , \'preParsing\' , \'preValidation\' or \'preHandler\''))
}
const enableRotation = Array.isArray(secret)
const algorithm = options.algorithm || 'sha256'
const signer = typeof secret === 'string' || enableRotation ? new Signer(secret, algorithm) : secret
Expand All @@ -86,7 +111,9 @@ function plugin (fastify, options, next) {
fastify.decorateReply('setCookie', setCookie)
fastify.decorateReply('clearCookie', clearCookie)

fastify.addHook('onRequest', onReqHandlerWrapper(fastify))
if (hook) {
fastify.addHook(hook, onReqHandlerWrapper(fastify, hook))
}

next()

Expand Down
95 changes: 95 additions & 0 deletions test/cookie.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -847,3 +847,98 @@ test('should not decorate fastify, request and reply if no secret was provided',
message: 'req.unsignCookie is not a function'
})
})

test('dont add auto cookie parsing to onRequest-hook if hook-option is set to false', (t) => {
t.plan(6)
const fastify = Fastify()
fastify.register(plugin, { hook: false })

for (const hook of ['preValidation', 'preHandler', 'preParsing']) {
fastify.addHook(hook, async (req) => {
t.equal(req.cookies, null)
})
}

fastify.get('/disable', (req, reply) => {
t.equal(req.cookies, null)
reply.send()
})

fastify.inject({
method: 'GET',
url: '/disable',
headers: {
cookie: 'bar=bar'
}
}, (err, res) => {
t.error(err)
t.equal(res.statusCode, 200)
})
})

test('result in an error if hook-option is set to an invalid value', (t) => {
t.plan(1)
const fastify = Fastify()

t.rejects(
() => fastify.register(plugin, { hook: true }),
new Error("@fastify/cookie: Invalid value provided for the hook-option. You can set the hook-option only to false, 'onRequest' , 'preParsing' , 'preValidation' or 'preHandler'")
)
})

test('correct working plugin if hook-option to preParsing', (t) => {
t.plan(5)
const fastify = Fastify()
fastify.register(plugin, { hook: 'preParsing' })

fastify.addHook('onRequest', async (req) => {
t.equal(req.cookies, null)
})

fastify.addHook('preValidation', async (req) => {
t.equal(req.cookies.bar, 'bar')
})

fastify.get('/preparsing', (req, reply) => {
t.equal(req.cookies.bar, 'bar')
reply.send()
})

fastify.inject({
method: 'GET',
url: '/preparsing',
headers: {
cookie: 'bar=bar'
}
}, (err, res) => {
t.error(err)
t.equal(res.statusCode, 200)
})
})

test('if cookies are not set, then the handler creates an empty req.cookies object', (t) => {
t.plan(5)
const fastify = Fastify()
fastify.register(plugin, { hook: 'preParsing' })

fastify.addHook('onRequest', async (req) => {
t.equal(req.cookies, null)
})

fastify.addHook('preValidation', async (req) => {
t.ok(req.cookies)
})

fastify.get('/preparsing', (req, reply) => {
t.ok(req.cookies)
reply.send()
})

fastify.inject({
method: 'GET',
url: '/preparsing'
}, (err, res) => {
t.error(err)
t.equal(res.statusCode, 200)
})
})
3 changes: 3 additions & 0 deletions types/plugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,11 @@ declare namespace fastifyCookie {
signed?: boolean;
}

type HookType = 'onRequest' | 'preParsing' | 'preValidation' | 'preHandler' | 'preSerialization';

export interface FastifyCookieOptions {
secret?: string | string[] | Signer;
hook?: HookType | false;
parseOptions?: fastifyCookie.CookieSerializeOptions;
}

Expand Down
18 changes: 15 additions & 3 deletions types/plugin.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import cookie from '..';
import { expectType } from 'tsd';
import { expectError, expectType } from 'tsd';
import * as fastifyCookieStar from '..';
import fastifyCookieCjsImport = require('..');
import fastifyCookieDefault, { fastifyCookie as fastifyCookieNamed } from '..';
import fastify, { FastifyInstance, FastifyReply, setCookieWrapper } from 'fastify';
import fastify, { FastifyInstance, FastifyPluginCallback, FastifyReply, setCookieWrapper } from 'fastify';
import { Server } from 'http';

const fastifyCookieCjs = require('..');

Expand Down Expand Up @@ -213,4 +214,15 @@ new fastifyCookieStar.Signer('secretString')
new fastifyCookieStar.Signer(['secretStringInArray'])
const signer = new fastifyCookieStar.Signer(['secretStringInArray'], 'sha256')
signer.sign('Lorem Ipsum')
signer.unsign('Lorem Ipsum')
signer.unsign('Lorem Ipsum')

const appWithHook: FastifyInstance = fastify();

appWithHook.register(cookie, { hook: false });
appWithHook.register(cookie, { hook: 'onRequest' });
appWithHook.register(cookie, { hook: 'preHandler' });
appWithHook.register(cookie, { hook: 'preParsing' });
appWithHook.register(cookie, { hook: 'preSerialization' });
appWithHook.register(cookie, { hook: 'preValidation' });
expectError(appWithHook.register(cookie, { hook: true }));
expectError(appWithHook.register(cookie, { hook: 'false' }));

0 comments on commit 045f65b

Please sign in to comment.