kwhitley / itty-router

A little router.
MIT License
1.75k stars 78 forks source link

Modify request headers #76

Closed js0cha closed 2 years ago

js0cha commented 2 years ago

Hi,

I would like to modify request headers in one of my middleware steps. Example:

  const newHeaders = new Headers(request.headers);
  newHeaders.set("X-Super-header", isSuper);

  const modifiedRequest = new Request(request.url, {
    body: request.body,
    headers: request.headers,
    method: request.method,
    redirect: request.redirect
  })

  request = modifiedRequest

I know if I make a return it has to be Response but when reassigning the var request, it's not being changed.

kwhitley commented 2 years ago

Hey @js0cha - you're basically trying to do something illegal in JavaScript. You can't reassigned a locally scoped variable and affect anything other than the local scope. For example:

function noMutation(a) {
  a = "replaced" // this does nothing aside from replace the locally-scoped reference to a

  console.log(a) // "replaced"... so it worked, right?
}

// let's create a variable
let m = "foo"

// now let's send it to a function like the request in itty
noMutation(m)

console.log(m) // still "foo", because that statement above only affected the local function scope

If you want to modify headers via middleware, you need to mutate the request, not replace it. Example:

const middleware = request => {
  request.headers.set('X-Super-header', true) // we just mutate a property on the existing request
}

Hope this helps!

js0cha commented 2 years ago

Hey @js0cha - you're basically trying to do something illegal in JavaScript. You can't reassigned a locally scoped variable and affect anything other than the local scope. For example:

function noMutation(a) {
  a = "replaced" // this does nothing aside from replace the locally-scoped reference to a

  console.log(a) // "replaced"... so it worked, right?
}

// let's create a variable
let m = "foo"

// now let's send it to a function like the request in itty
noMutation(m)

console.log(m) // still "foo", because that statement above only affected the local function scope

If you want to modify headers via middleware, you need to mutate the request, not replace it. Example:

const middleware = request => {
  request.headers.set('X-Super-header', true) // we just mutate a property on the existing request
}

Hope this helps!

Yes, i get it. @kwhitley But Cloudflare do not allow us to modify request headers like you proposed = TypeError: can't modify immutable headers

kwhitley commented 2 years ago

Ah yes gotcha... so in that case, you were so close!

If you need to pass a reformed request onto downstream handlers, just re-embed the new request INTO the existing one (anywhere) - just think of the original request as a transport mechanism/vehicle from handler to handler:

const middleware = request => {
  const newRequest = new Request() // etc etc
  request.newRequest = newRequest
}

const downstream = ({ newRequest }) => {
  // tada!
}

Otherwise, in the scenario you want to just exit with the Request itself (itty has no requirements for WHAT you return, making it universally applicable), just return that new Request directly. Just make sure (with CF) that something in your request/response handlers you DO return something or you'll crash obv.

const middleware = request => {
  const newRequest = new Request() // etc etc
  return newRequest
}

// assuming your routes are in place

const maybeARequest = await router.handle(request) // might now return your Request