Skip to content

location headers is rewritten without the possibility to disable this behavior #296

@efr00

Description

@efr00

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.14.1

Plugin version

9.0.0

Node.js version

16

Operating system

Linux

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

22.04

Description

When a request redirects to a relative path.
The proxy modifies the location but this is not the behavior I want.
Moreover, this behavior is not indicated in the documentation.

According to the tests written in @fastify/http-proxy, this is intended.
See test('rewrite location headers') from : fastify-http-proxy/blob/master/test/test.js#L544

However, we have no way to change this behavior.
I had hope via the rewriteHeaders option of @fastify/reply-from :
https://github.com/fastify/fastify-reply-from#rewriteheadersheaders-request

rewriteHeaders(headers, request)
Called to rewrite the headers of the response, before them being copied over to the outer response. Parameters are the original headers and the Fastify request. It must return the new headers object.

But the headers parameter of this function is not the original, as specified in the documentation.
Because it is always modified due to the following code:
fastify-http-proxy/blob/master/index.js#L252

function rewriteHeaders (headers, req) {
    const location = headers.location
    if (location && !isExternalUrl(location)) {
      headers.location = location.replace(rewritePrefix, fastify.prefix) // because of this line
    }
    if (oldRewriteHeaders) {
      headers = oldRewriteHeaders(headers, req)
    }
    return headers
  }

Steps to Reproduce

I wrote a test to illustrate this :

'use strict'

const { teardown, test } = require('tap')
const Fastify = require('fastify')
const proxy = require('../')
const got = require('got')

async function run () {
  const origin = Fastify()
  origin.post('/aaa', async (request, reply) => {
    reply.header('location', '/bbb')
    return { status: 'ok' }
  })
  await origin.listen({ port: 0 })

  teardown(() => origin.close())

  test('location headers is preserved', async t => {
    const proxyServer = Fastify()

    proxyServer.register(proxy, {
      upstream: `http://localhost:${origin.server.address().port}`,
      prefix: '/my-prefix'
    })

    await proxyServer.listen({ port: 0 })

    t.teardown(() => {
      proxyServer.close()
    })

    const {
      headers: { location }
    } = await got(
      `http://localhost:${proxyServer.server.address().port}/my-prefix/aaa`,
      {
        method: 'POST'
      }
    )
    t.equal(location, '/bbb') // fail, location is /my-prefix/bbb
  })
}

run()

Expected Behavior

When I redirect to a relative url, the location is unchanged.
GET .../my-prefix/aaa?redirect=/bbb => 302 /bbb with headers.location: /bbb
Is it possible to add an option to disable location rewriting? or something else?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions