You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							144 lines
						
					
					
						
							4.0 KiB
						
					
					
				
			
		
		
	
	
							144 lines
						
					
					
						
							4.0 KiB
						
					
					
				| 'use strict'
 | |
| 
 | |
| const fp = require('fastify-plugin')
 | |
| const cookie = require('cookie')
 | |
| 
 | |
| const { Signer, sign, unsign } = require('./signer')
 | |
| 
 | |
| function fastifyCookieSetCookie (reply, name, value, options, signer) {
 | |
|   const opts = Object.assign({}, options)
 | |
|   if (opts.expires && Number.isInteger(opts.expires)) {
 | |
|     opts.expires = new Date(opts.expires)
 | |
|   }
 | |
| 
 | |
|   if (opts.signed) {
 | |
|     value = signer.sign(value)
 | |
|   }
 | |
| 
 | |
|   if (opts.secure === 'auto') {
 | |
|     if (isConnectionSecure(reply.request)) {
 | |
|       opts.secure = true
 | |
|     } else {
 | |
|       opts.sameSite = 'lax'
 | |
|       opts.secure = false
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   const serialized = cookie.serialize(name, value, opts)
 | |
|   let setCookie = reply.getHeader('Set-Cookie')
 | |
|   if (!setCookie) {
 | |
|     reply.header('Set-Cookie', serialized)
 | |
|     return reply
 | |
|   }
 | |
| 
 | |
|   if (typeof setCookie === 'string') {
 | |
|     setCookie = [setCookie]
 | |
|   }
 | |
| 
 | |
|   setCookie.push(serialized)
 | |
|   reply.removeHeader('Set-Cookie')
 | |
|   reply.header('Set-Cookie', setCookie)
 | |
|   return reply
 | |
| }
 | |
| 
 | |
| function fastifyCookieClearCookie (reply, name, options) {
 | |
|   const opts = Object.assign({ path: '/' }, options || { }, {
 | |
|     expires: new Date(1),
 | |
|     signed: undefined,
 | |
|     maxAge: undefined
 | |
|   })
 | |
|   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)
 | |
|     }
 | |
|     done()
 | |
|   }
 | |
| }
 | |
| 
 | |
| function plugin (fastify, options, next) {
 | |
|   const secret = options.secret || ''
 | |
|   const enableRotation = Array.isArray(secret)
 | |
|   const algorithm = options.algorithm || 'sha256'
 | |
|   const signer = typeof secret === 'string' || enableRotation ? new Signer(secret, algorithm) : secret
 | |
| 
 | |
|   fastify.decorate('parseCookie', parseCookie)
 | |
|   fastify.decorate('signCookie', signCookie)
 | |
|   fastify.decorate('unsignCookie', unsignCookie)
 | |
| 
 | |
|   fastify.decorateRequest('cookies', null)
 | |
|   fastify.decorateRequest('unsignCookie', unsignCookie)
 | |
|   fastify.decorateReply('setCookie', setCookie)
 | |
|   fastify.decorateReply('cookie', setCookie)
 | |
|   fastify.decorateReply('clearCookie', clearCookie)
 | |
|   fastify.decorateReply('unsignCookie', unsignCookie)
 | |
| 
 | |
|   fastify.addHook('onRequest', onReqHandlerWrapper(fastify))
 | |
| 
 | |
|   next()
 | |
| 
 | |
|   // ***************************
 | |
|   function parseCookie (cookieHeader) {
 | |
|     return cookie.parse(cookieHeader, options.parseOptions)
 | |
|   }
 | |
| 
 | |
|   function signCookie (value) {
 | |
|     return signer.sign(value)
 | |
|   }
 | |
| 
 | |
|   function unsignCookie (value) {
 | |
|     return signer.unsign(value)
 | |
|   }
 | |
| 
 | |
|   function setCookie (name, value, cookieOptions) {
 | |
|     const opts = Object.assign({}, options.parseOptions, cookieOptions)
 | |
|     return fastifyCookieSetCookie(this, name, value, opts, signer)
 | |
|   }
 | |
| 
 | |
|   function clearCookie (name, options) {
 | |
|     return fastifyCookieClearCookie(this, name, options)
 | |
|   }
 | |
| }
 | |
| 
 | |
| function isConnectionSecure (request) {
 | |
|   return (
 | |
|     request.raw.socket?.encrypted === true ||
 | |
|     request.headers['x-forwarded-proto'] === 'https'
 | |
|   )
 | |
| }
 | |
| 
 | |
| const fastifyCookie = fp(plugin, {
 | |
|   fastify: '4.x',
 | |
|   name: '@fastify/cookie'
 | |
| })
 | |
| 
 | |
| /**
 | |
|  * These export configurations enable JS and TS developers
 | |
|  * to consume fastify-cookie in whatever way best suits their needs.
 | |
|  * Some examples of supported import syntax includes:
 | |
|  * - `const fastifyCookie = require('fastify-cookie')`
 | |
|  * - `const { fastifyCookie } = require('fastify-cookie')`
 | |
|  * - `import * as fastifyCookie from 'fastify-cookie'`
 | |
|  * - `import { fastifyCookie } from 'fastify-cookie'`
 | |
|  * - `import fastifyCookie from 'fastify-cookie'`
 | |
|  */
 | |
| fastifyCookie.signerFactory = Signer
 | |
| fastifyCookie.fastifyCookie = fastifyCookie
 | |
| fastifyCookie.default = fastifyCookie
 | |
| module.exports = fastifyCookie
 | |
| 
 | |
| fastifyCookie.fastifyCookie.signerFactory = Signer
 | |
| fastifyCookie.fastifyCookie.Signer = Signer
 | |
| fastifyCookie.fastifyCookie.sign = sign
 | |
| fastifyCookie.fastifyCookie.unsign = unsign
 | |
| 
 | |
| module.exports.signerFactory = Signer
 | |
| module.exports.Signer = Signer
 | |
| module.exports.sign = sign
 | |
| module.exports.unsign = unsign
 |