Azure / azure-functions-host

The host/runtime that powers Azure Functions
https://functions.azure.com
MIT License
1.94k stars 442 forks source link

HttpTrigger's Route precedence is different from ASP.NET Core behavior #9876

Open shibayan opened 1 year ago

shibayan commented 1 year ago

It seems that when a route template is specified in HttpTrigger, the precedence is in alphabetical order, unlike the ASP.NET Core implementation.

When the following sample code is executed, it is generally expected that the "List" function will be executed when "/Products/List" is accessed, but in fact the "Details" function is always called.

public class Products
{
    [Function(nameof(Details))]
    public IActionResult Details(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "Products/{id}")] HttpRequest req,
        string id)
    {
        return new OkObjectResult("Invoke Details function");
    }

    [Function(nameof(List))]
    public IActionResult List(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "Products/List")] HttpRequest req)
    {
        return new OkObjectResult("Invoke List function");
    }
}

image

The ASP.NET Core documentation explains precedence as follows I am not comfortable with the precedence of Azure Functions.

For example, consider templates /Products/List and /Products/{id}. It would be reasonable to assume that /Products/List is a better match than /Products/{id} for the URL path /Products/List. This works because the literal segment /List is considered to have better precedence than the parameter segment /{id}.

fabiocav commented 1 year ago

Hi @shibayan , this is indeed a host behavior that has been preserved to ensure backwards compatibility. With the new HTTP model, we have a bit more flexibility and the ability to introduce better control here, but this match, today, is still performed in the host.

shibayan commented 1 year ago

@fabiocav Thank you for your response.

I find this behavior confusing to most developers, so it would be best if there is an option to switch between ASP.NET Core compatible behavior and the previous compatibility behavior.

shibayan commented 11 months ago

Any progress?

.NET In-Process had a workaround, but Isolated Worker has no workaround, so it is blocking the migration to Isolated itself.

mattchenderson commented 9 months ago

@shibayan could you please share the workaround you had for this in in-proc?

shibayan commented 9 months ago

@mattchenderson I am currently developing an extension to facilitate writing Web APIs using Azure Functions' HttpTrigger. To work around an issue, I have resorted to forcibly obtaining the array of routes internally maintained by the Azure Functions Host through reflection. Then, I sort the routes anew using a priority system compliant with ASP.NET Core, specifically employing RoutePrecedence.ComputeInbound for sorting.

https://github.com/shibayan/azure-functions-http-api/blob/master/src/Azure.WebJobs.Extensions.HttpApi/Routing/RoutePrecedenceExtensionConfigProvider.cs#L30-L40

Extension repo : https://github.com/shibayan/azure-functions-http-api

fabiocav commented 9 months ago

Discussing this today and transferring to the host, as this is a host issue.

One of the options discussed today was to introduce a configuration option that would let you manage the precedence behavior, making the ASP.NET Core (template) precedence behavior an opt-in option for now.

ynborokh commented 2 months ago

Is there any news about this issue?