Redirect/Rewrite to function seems broken?

Hi.

So I am having a bit of a problem with netlify redirects that I remember to have worked fine a few weeks ago.

I have a redirect to a netlify function for pages that aren’t built yet. The redirect sets some needed values on the function via query parameters:

[[redirects]]
from='/wishes.mine/*'
to='/.netlify/functions/wishes_render?key=:splat&type=mine'
status=200

That redirect has been working (at least I remember it so) 2 weeks ago but now I am getting the function called but with the original request. So there is no way for my function to know query parameters that have been set in the rewrite.

You can check out the problem here: https://twinkl.netlify.app/wishes.mine/i-dont-exist
What you see is an error response I generate from the render function that exposes the request object. And in that request object, there are NO query parameters set as well as the ORIGINAL path, rather than the redirected one.

netlify.dev doesn’t have this behaviour by the way and wortks as expected. :confused:

Thank’s so much for your help looking into this,

Josh

So I have done a bit more digging on this and it seems to me, that the something broke in how :splat values are forwarded to target addresses with query parameters.

This redirect config:

[[redirects]]
from='/foo/*'
to='/bar?foo=:splat&a=b'

Will actually redirect to /bar?foo=&a=b …notice the empty splat value?

…I am pretty sure that woked at the beginning of the month though. It also does still work as expected in the netlify-dev environment. :thinking:

Any Ideas? Should I report a bug? Is there a workaround? Is it NOT a bug and I am simply to stupid to figure out how this is meant to be done?

…any help is appreciated.

Josh

And even more info regarding this:

The :splat sting actually seems unrelated. BUT I did (on a hunch) remove the status=200 from my rewrites… essentially making them redirects…

And now it DOES work. So the Bug seems to be somewhere in the reWRITE logic, where the lambda function will then get the original request, rather than the rewritten request.

So to summarize:

It seems to be that there is a BUG in how the rewrite functionality works that got introduced somewhere within the last 3 weeks.
Since then, a rewrite (status=200) will call the target address NOT with the rewritten request (as would be expected and was the case before and is also how the netlify-dev works) BUT INSTEAD with the original request.

would someone please look into this and at least tell me, how I can move on now?

kind regards,
Josh

@j-o-sh I believe the :splat has to be the last item in the redirect URL for it to work.

Hi Greg,

Thx for looking into this.

As I wrote in my last post, I don’t think :splat has anything to do with the issue anymore. To make sure, I replaced the use of :splat everywhere with veriable names.

I still am getting the same behaviour and only on redirects with status=200 (rewrites) and only on the real netlify, not on netlify-dev. :thinking:

Hey Josh,

Can’t imagine this worked too well in the past! Docs:

For a proxy redirect, you’re gonna need something like:

/wishes.:type/:key /.netlify/functions/wishes_render?key=:key&type=:type 200

Or in netlify.toml currency:

[[redirects]]
from=‘/wishes.:type/:key’
to=‘/.netlify/functions/wishes_render?key=:key&type=:type’
status=200

Hi Pieparker,

Sorry to still be pestering you guys with this. And thanks for your patience :pray:

I did try your suggestion and even a sup[er simple version, where I don’t pass through any query parameters but simply call a function with statically set parameters:

[[redirects]]
from='/abrakadabra/'
to='/.netlify/functions/wishes_render?key=fca88cd7-3e21-491f-8391-c5fb4ebd0175'
status=200

I do however still get the same behaviour (which you can see for your self here: https://twinkl.netlify.app/abrakadabra

What seems to be happening from my perspective is that a redirect with status=200 set seems to now get passing on the original request to the function (the one to /abrakadabra) rather than the rewritten request (the one to /.netlify/functions/wishes_render?key=fca88cd7-3e21-491f-8391-c5fb4ebd0175).

This was not the case a few weeks ago and breaks calling the function with any parameters set in the rewrite.

And again: It DOES still function in netlify-dev :wink:

I could put the behaviour toget5her in a small repo if that helps?

As it stands now, there is no way for functions to know their ‘real’ (rewritten) call… rather they now have to know the logic behind the original call that was rewritten. :confused:

Hey @j-o-sh,

Interesting, appreciate that!

What happens if we try:

[[redirects]]
from='/abrakadabra key=:key
to='/.netlify/functions/wishes_render?key=:key'
status=200

Hey :slight_smile:

…that would work but not for the right reason :wink:

The reason this will work it that we will put a query parameter named ‘key’ into the original url and so the function is able to gather that query parameter again… That will EVEN work if we now completely leave the query parameter out of the ‘to=’ url. As I said, the function will get the orioginal request to work with rather than the rewritten one.

So even this:

[[redirects]]
from='/something key=:something'
to='/.netlify/functions/wishes_render'
status=200

would work :wink:

Your working example btw does work since it does a redirect rather than a rewrite (no status=200)

Have a look at the request object that I return into the browser on https://twinkl.netlify.app/abrakadabra?a=b for instance. You’ll notice that there is the original path ‘/abrakadabra’ as well as the original query parameter ‘a=b’ (which were never mentioned in my netlify.toml file).

I think I’m missing the point here, perhaps?

image

Unless the query param is in the ‘from’ condition, it won’t transpose in the ‘to’ condition. It’s still a query parameter at the end of the day and must abide by :point_up: the docs.

As for the fact that the original request is being transposed… well, that’s what a 200 rewrite does! You won’t see the path of the function.

I created a function called wishes_render with one rule configured where we pass the type=mine query string. Any request where this is omitted will 404:

/wishes.mine key=:key type=mine /.netlify/functions/wishes_render?key=:key&type=mine 200!

I have another rule configured where the query string is not passed through the redirect engine but is still parsed (if included):

/wishes.yours key=:key /.netlify/functions/wishes_render?key=:key 200!

In short, I’m not seeing anything out of the ordinary!

Yes I also think we are missing the point a bit. I am sorry, I guess I did a really poor job, describing my problem.

Let me try again:

We are not talking about redirects… Those work fine, as expected.

We are exclusively talking about rewrites.

  1. Imagine a lambda function that will take some information out of the query parameters like this:
export async function handler (req, ctx, cb) {
  cb(null, {
    statusCode: 200,
    body: `-- ${req.queryStringParameters.foo} --`
  })  
}
  1. Let’s hide that API behind a rewrite, so that we can call /api/something and have the function return -- something-specific --

In order to do that we would set up a rewrite like so:

[[redirects]]
from='/api/something'
to='/.functions/myfunction?foo=something-specific'
status=200

My point and problem is, that this exact scenario would have worked in June, still works in netlify-dev and is somewhat how one would intuitively think it should work, based on the fact that a nginx or apache rewrite would function exactly like that.

The key thing here being that the function’s req object contains the request to /.functions/myfunction?foo=something-specific.

That however seems to have changed on netlify recently, since now the req object given to my lambda function will contain the request to '/api/something instead.

  • So either this has changed by accident in which case this would be a bug
  • Or it changed on purpose in which case it is a bug in netlify-dev and should also be mentioned in the docs

But as it stands now, the ability to develop api functions that rely on information from the url is quite limited as I cannot replicate the life setup via netlify-dev and thus have to guess until deployment wether I am doing it right :confused:

Sorry again for not being clear enough.

I hope this explenation is better understandable?

Kind regards,
Josh

Hey @j-o-sh,

I absolutely get it now. I was jumping a few steps ahead! This topic explains some of your observations from earlier in the week.

We’re trying to pass a static query parameter to a function via a rewrite without having to specify it in the original path.

I’ve racked by brain and played with the demo site I set up before conceding and consulting our platform team. Turns out, it’s a known use case which we don’t currently support live. However, we strive to align this with Netlify Dev so, perhaps in future, we’ll see this working.

I understand that this perhaps isn’t the news you were expecting. However, there are a few workarounds which, I hope, allow you to perform what you’d like to achieve.

Firstly, the rule /wishes.mine /.netlify/functions/wishes_render?key=testkey 301! does pass the query string through (note the 301). So, your desired behaviour does work for redirects but not at present for rewrites. If this is a suitable workaround then great!

Depending on what’s important to you, and the significance/secrecy of the key, you may instead want to add the key as an environment variable within the Netlify UI and pass it to the function directly, thus hiding it.

Hi there,

So to get around this for now:

Using a 301 unfortunately is not an option for me.

I tries using custom header fields as mentioned in the rewrite documentation but unfortunately, while they do work, they do not get populated with :splat and it’s cousins.

So in the end I gave up and am now parsing the call path I get passed into the function for the fields I am interested in.

This works in dev as well as live, so problem solved for now. :+1:

I do however really dislike that solution, since it is very unelegant and forced me to be not DRY. Specifically it forces me to know the syntax of my paths in the netlify.toml as well as in the function itself, to parse the information out. :sob:

I do very much hope for the netlify team to implement a solid rewrite engine soon, that allows for more elegant solutions to this issue.

Regards,
Josh

1 Like

Glad you’re able to work around it, @j-o-sh, and let’s see what the proposed enhancements next quarter bring!

I too hope this gets fixed soon, but until then I would like to share another possible workaround.

The following line currently does NOT work (note 200):

/foo/* /.netlify/functions/app?foo=:splat 200

However this did the trick for me (note 200 and full url):

/foo/* https://example.netlify.app/.netlify/functions/app?foo=:splat 200

EDIT: Note if you use netlify dev with this setup, it will also route you to the production function. (not so useful after all)