Azure-Functions icon indicating copy to clipboard operation
Azure-Functions copied to clipboard

Routing fails if parameters contains slash

Open russgove opened this issue 6 years ago • 17 comments

Hi, I see this was reported a while back and resolved, but i cannot find the resolution.

I need to be able to pass slashes in the final segment of my route:

i.e for a department called 'A/P'for i want to be able

https://somefunction/api/departments/A%2FP

I set up my route like this: Route = "departments/{dept}"

it works fine if there are no slashes (encoded as %2F) in the department, but if there is a slash it returns a 404.

How can I fix this?

russgove avatar Nov 20 '18 16:11 russgove

@mattchenderson to redirect

ColbyTresness avatar Mar 13 '19 19:03 ColbyTresness

@ColbyTresness I am facing the same issue. @mattchenderson can you please add something here?

umair8794 avatar Aug 09 '19 07:08 umair8794

The question did not specify whether its a proxy or a function, nor the programming language, but with a js function, this function.json works:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "route": "departments/{*segments}",
      "methods": [
        "get"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

Then, in the function, you can access the segment in req.params.segments. This is a string, and it can contain forward slashes (not sure about back slashes).

magyarb avatar Aug 21 '19 20:08 magyarb

The workaround suggested by engineering- try modifying the rule like /code/{*code}

Modify the client to send requests as https://.azurewebsites.net/code/fsdfsfdasfdsbk/asfdsfsfsdfdsfsa Instead of https://< functionapp>.azurewebsites.net/code=sdfsfdasfdsbk/asfdsfsfsdfdsfsa

anilpras avatar May 20 '20 17:05 anilpras

We're deliberately url-encoding the slashes in order to not affect the request path, so I'm trying to understand why the %2F is decoded before route matching.

With a function route /get-resources/{keyVaultUri} a request like /get-resources/https%3A%2F%2Fsomeurl.net works fine when debugging on a local running environment (eg. IIS-express), but will result in status code 404 on a deployed Azure Web App. Why that difference?

The * wildcard suggestion seems useful, but only if you have a single url-encoded string parameter and can control it to the end of the url. But even then, in my case (using an Azure Function V3) with the above example, I receive an argument value https:/someurl.net (so it swallowed one of the slashes). And even with a request /get-resources/https%3A%2F%2F%2F%2F%2F%2Fsomeurl.net it gets trimmed down to a single slash / 😞

Crossbow78 avatar Jul 02 '20 10:07 Crossbow78

This has to be a bug in the Azure functions runtime, as it's behaving different in debug locally and when deployed to Azure..

Anyways, I faced this issue today and figured out that it's possible to double encode the values that's sent. When doing this, the slashes in the encoded string are surviving the routing algorithm going on in the background.

Node.js example:

const encode = (id) => encodeURIComponent(encodeURIComponent(id))
const decode = (id) => decodeURIComponent(decodeURIComponent(id))

// Client side:
const id = 'TEST/ABC123'
fetch(`azure-functions-api.com/groups/${encode(id)}/members`)
  .then(console.log)
  .catch(console.error)

// Azure Functions side:
module.exports = (context, req) => {
  const { id: rawId } = req.params
  const id = decode(rawId)
 
  // do stuff..
}

MatsAnd avatar Nov 26 '20 11:11 MatsAnd

We are facing the same issue. Our http triggered functions are connected to Azure API Management and used by our customers. Recently one of our customers noticed that they could not use the identifier they wanted when using the APIs we expose.

After debugging we found that this was tied to the %2F issue others are facing.

Since the APIs we expose are used by our customers we cannot ask them to "double encode" their parameters before using the API.

Aslo, as noted before, the option of using the ${*param} bindining will not work when there are more than one parameter in question and perhaps said parameter is not the trailing parameter of the url.

As noted by @MatsAnd, this seems only to be the case when running the function in the Azure cloud and not while developing locally.

To solve this issue now, we might need to do the double encoding ourselves in the <inbound> rules of the API Management.

I have tried with forcing the parameter AZURE_FUNCTION_PROXY_BACKEND_URL_DECODE_SLASHES to false even though the documentation says that false is the default value. No success there.

This issue has been dormant since 2018 and seems to be linked to this https://github.com/Azure/azure-functions-host/issues/2249.

oc002 avatar Feb 08 '21 16:02 oc002

hey @ingenfakir , that sounds like a great idea. hadn’t thought of that since i hadn’t used Apim. I have forgotten the context i asked my question in, but could you please let me know if this fix works for you? thanks russell

russgove avatar Feb 09 '21 01:02 russgove

Does not seem possible to rewrite the uri in a generic way to support "double encoding" of /. There is a directive <find-and-replace /> but that only works for the body otherwise it could have been used as <find-and-replace from="%2F" to="%252F" />. Theres also the <rewrite-uri template="uri template" copy-unmatched-params="true | false" /> but that does not support the usecase.

I've resorted to creating a support ticket from our Tenant to Azure support. Will keep this ticket updated with the answers I receive from them.

oc002 avatar Feb 09 '21 09:02 oc002

After many exchanges back and forth between me and the support team and the product team the solution was:

For resolution, the PG team says that simply, don’t pass a / in the URL part of the HTTP address. You might setup a URL Rewrite rule to look for this and then change it before it gets to the application.

Which means that there's nothing we can do but to prohibit the usage of url-encoded / characters in our APIs or figure out a way to double encode the parameter.

We will go with the former and ask our customers to avoid encoding / characters in the URL for now.

oc002 avatar Apr 26 '21 11:04 oc002

The only option here is to perform additional encoding on the URL before you call it, then perform the corresponding decoding on the receiving end. We used Base64 for this.

IanKemp avatar May 07 '21 10:05 IanKemp

Yes @IanKemp that is true, and the issue we have is that our APIs are consumed by our customers and we don't feel like communicating to them that "For all path variables please perform two encodings since our API platform does not support single encoded path parameters".

If the consumers of the APIs were internal, this would be fine. But ours are external.

oc002 avatar May 07 '21 12:05 oc002

@drownintheloch Yeah, I was just giving a possible solution for anyone who is fortunate enough to not be publishing an external API.

The fact this has been an issue since 2018 and never got any attention is just bizarre to me, but sadly par for the course for Azure Functions. Microsoft honestly doesn't seem to care, the result is that using AF as a web API has gone from "not recommended" in my books to "strongly discouraged".

IanKemp avatar May 07 '21 13:05 IanKemp

I've lost an afternoon to this working on dev then breaking on Azure, before finding this slash strip/replace parameter mangling. Double encoding is a potential solution for me, but it will clearly be labelled with // HACK: Remove when Microsoft fixes Azure

jamesburtonqubithealth avatar May 11 '21 20:05 jamesburtonqubithealth

Same issue here. Locally everything works fine, but when deploying (over a linux container), I'm getting the bug and need to double encode :-(

laurentbel avatar Jan 31 '22 17:01 laurentbel

Has anyone observed this same behavior with a NodeJS app hosted in Azure App Services?

alphonso77 avatar Feb 21 '22 22:02 alphonso77

As a follow up - I ran across this same issue in an Azure-hosted NodeJS container. We had some routes that had parameters with encoded slashes (like: http://our-api.com/first-param/second-param/some%2Fname). The route worked fine running locally on a NodeJS Windows 11 x64 architecture. But it 404'd in the target Azure environment. I changed the last parameter to an encoded Query String parameter and it worked fine.

alphonso77 avatar Feb 22 '22 19:02 alphonso77