Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to read response cookies until onSend #269

Open
2 tasks done
Galienna opened this issue Jan 10, 2024 · 6 comments
Open
2 tasks done

Unable to read response cookies until onSend #269

Galienna opened this issue Jan 10, 2024 · 6 comments
Labels
feature request New feature to be added good first issue Good for newcomers

Comments

@Galienna
Copy link

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.25.2

Plugin version

9.2.0

Node.js version

20.9.0

Operating system

Linux

Operating system version (i.e. 20.04, 11.3, 10)

20.04

Description

Hello,

In my route handler, if I use reply.setCookie to set a response cookie, I'm unable to read it inside my handler by calling reply.getHeader('set-cookie'). However, I can read my resp cookie later in the lifecycle (onSend and onResponse).

I need to read it inside my handler. Maybe it's working as intended or I missed something ?

Steps to Reproduce

Server :

const fastify = require('fastify');
const fastifyCookie = require('@fastify/cookie');

async function testCookiePlugin() {
    const server = fastify();
    server.register(fastifyCookie);

    server.addHook('preSerialization', async function (request, reply) {
        console.log('--------- server preSerialization -------------');
        console.log('Read response cookies through reply.getHeader(\'set-cookie\')', reply.getHeader('set-cookie'));
    });

    server.addHook('onSend', async function (request, reply) {
        console.log('--------- server onSend -------------');
        console.log('Read response cookies through reply.getHeader(\'set-cookie\')', reply.getHeader('set-cookie'));
    });

    server.addHook('onResponse', async function (request, reply) {
        console.log('--------- server onResponse -------------');
        console.log('Read response cookies through reply.getHeader(\'set-cookie\')', reply.getHeader('set-cookie'));
    });

    server.route({
        method: 'GET',
        url: '/',
        handler: async function (request, reply) {
            console.log('--> Set resp cookie through reply.setCookie');
            reply.setCookie('through-plugin', 'cookie set through reply.setCookie');
            console.log('Read response cookies through reply.getHeader(\'set-cookie\')', reply.getHeader('set-cookie'));

            console.log('--> Set resp cookie through reply.header');
            reply.header('set-cookie', 'through-header=cookie set through reply.header; Secure; HttpOnly');
            console.log('Read response cookies through reply.getHeader(\'set-cookie\')', reply.getHeader('set-cookie'));

            return {
                setCookieHeader: reply.getHeader('set-cookie')
            };
        },
        preSerialization: async function (request, reply) {
            console.log('--------- route preSerialization -------------');
            console.log('Read response cookies through reply.getHeader(\'set-cookie\')', reply.getHeader('set-cookie'));
        },
        onSend: async function (request, reply) {
            console.log('--------- route onSend -------------');
            console.log('Read response cookies through reply.getHeader(\'set-cookie\')', reply.getHeader('set-cookie'));
        },
        onResponse: async function (request, reply) {
            console.log('--------- route onResponse -------------');
            console.log('Read response cookies through reply.getHeader(\'set-cookie\')', reply.getHeader('set-cookie'));
        }
    });

    return server.listen({port: 8080, host: '0.0.0.0'});
}

return testCookiePlugin();

The following curl curl -i http://localhost:8080/ gives me this :

HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
set-cookie: through-header=cookie set through reply.header; Secure; HttpOnly
set-cookie: through-plugin=cookie%20set%20through%20reply.setCookie
content-length: 86
Date: Wed, 10 Jan 2024 11:22:13 GMT
Connection: keep-alive
Keep-Alive: timeout=72

{"setCookieHeader":"through-header=cookie set through reply.header; Secure; HttpOnly"}

And server logs :

--> Set resp cookie through reply.setCookie
Read response cookies through reply.getHeader('set-cookie') undefined

--> Set resp cookie through reply.header
Read response cookies through reply.getHeader('set-cookie') through-header=cookie set through reply.header; Secure; HttpOnly

--------- server preSerialization -------------
Read response cookies through reply.getHeader('set-cookie') through-header=cookie set through reply.header; Secure; HttpOnly

--------- route preSerialization -------------
Read response cookies through reply.getHeader('set-cookie') through-header=cookie set through reply.header; Secure; HttpOnly

--------- server onSend -------------
Read response cookies through reply.getHeader('set-cookie') [
  'through-header=cookie set through reply.header; Secure; HttpOnly',
  'through-plugin=cookie%20set%20through%20reply.setCookie'
]

--------- route onSend -------------
Read response cookies through reply.getHeader('set-cookie') [
  'through-header=cookie set through reply.header; Secure; HttpOnly',
  'through-plugin=cookie%20set%20through%20reply.setCookie'
]

--------- server onResponse -------------
Read response cookies through reply.getHeader('set-cookie') [
  'through-header=cookie set through reply.header; Secure; HttpOnly',
  'through-plugin=cookie%20set%20through%20reply.setCookie'
]

--------- route onResponse -------------
Read response cookies through reply.getHeader('set-cookie') [
  'through-header=cookie set through reply.header; Secure; HttpOnly',
  'through-plugin=cookie%20set%20through%20reply.setCookie'
]

Expected Behavior

I expect I can write/read response cookies through the plugin the "same way" I do through reply.header('set-cookie', ...).
I would like the plugin to modify the set-cookie response header as soon as i call the reply.setCookie method.
I find it misleading to "hide" the cookies that will be sent until the onSend lifecycle step.

@Uzlopak
Copy link
Contributor

Uzlopak commented Jan 10, 2024

So you want a getCookie function.

@Uzlopak Uzlopak added good first issue Good for newcomers feature request New feature to be added labels Jan 10, 2024
@Galienna
Copy link
Author

Galienna commented Jan 10, 2024

A reply.getCookie function that returns parsed cookies would be nice. But more precisely, I'd like reply.getHeaders() to reflect what will be sent back to the client, even if we're still inside the handler.
In my mind, reply.setCookie is just a syntactic sugar for reply.header('set-cookie', ...). But it's not. If you define cookies through reply.header('set-cookie', ...) you can read it by calling reply.getHeaders(). If you define cookies through reply.setCookie, then your headers are not in sync and you cannot read it by calling reply.getHeaders().

@Uzlopak
Copy link
Contributor

Uzlopak commented Jan 10, 2024

You either use setCookie or you use .header('set-cookie'). Mxing both is not recommended.

If you are willing to provide a PR, which is not breaking with the current test set, then I guess we can discuss it.

@gurgunday
Copy link
Member

There could indeed be a getCookie method

@Galienna
Copy link
Author

Galienna commented Jan 10, 2024

You either use setCookie or you use .header('set-cookie'). Mxing both is not recommended.

If you are willing to provide a PR, which is not breaking with the current test set, then I guess we can discuss it.

We're using business logic plugins from different teams. They don't know if fastify-cookie is used inside the final server. So how can one know how to read response cookies ?
Every plugin that wants to read resp cookie should check "is reply.setCookie a function ? if so, read cookie through reply.getCookies, otherwise read cookie through reply.getHeader('set-cookie')". A bit harsh

Why isn't it a good thing to mix both ways ?

I'm not sure I'll have time for the PR, but I'll try :)

@jsumners
Copy link
Member

Define the dependencies for your plugins (https://github.com/fastify/fastify-plugin#dependencies) so that your plugins are guaranteed to have access to the methods they require.

As for the issue at hand, I would say that the reply is missing the equivalent:

fastify.decorateRequest('cookies', null)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature to be added good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants