Coder Social home page Coder Social logo

azurefunctionsisolatedroutepriority's Introduction

HTTP route resolution priority for Isolated Azure Functions

Provides correct and deterministic HTTP route resolution priority for Azure Functions running in Isolated mode.

Potentially ambiguous routes like these will resolve properly when called with a url that could match either one.

/api/{userId}
/api/ping

Usage

Add the Element.Azure.Functions.Worker.Extensions.RoutePriority Nuget package to your Isolated Azure Functions project.

NOTE: Due to how the Azure Functions metadata generator works, you must actually use the extension in a function declaration. To meet that requirement, you must add the [RoutePriority] input binding attribute to any one of your HttpTrigger functions (does not need to be all of them):

[Function("Ping")]
public HttpResponseData Ping([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "ping")] HttpRequestData req, [RoutePriority] object ignore)
{
    // ... your code ...
}

How does it work?

See my original blog post for full details of the problem and how the extension works internally. In the in-process model, the solution from that blog post works great.

However, in the the isolated functions model, the functions host and your functions code run as two separate processes. The functions host recieves the incoming request then communicates with your worker process via gRPC. But the only way to get access to the IWebJobsRouter is to do it from the host.

Unfortunately, the code you write in your function app only runs in the worker process and there is no way to 'reach into' the host to modify its behavior.

Except, there is. And it is via Binding Extensions.

Binding extensions are ways to add your own custom trigger types, input bindings, and output bindings. In order to allow them to work, they also have to run in the host. So this solution creates a custom extension that allows code (in this case, code to reorder the route priority order) to run on the host.

One limitation of extensions is that they are only geared towards bindings. As such, your function app code must make use of at least one binding from your extension or else the function extension metadata generator will strip out the extension information from the generated host code. That is why the [RoutePriority] input binding attribute needs to be applied somewhere in a function in your function app - it doesnt do anything, other than prevent the rest of the extension code from being complied out.

The actual mechanisms of how extensions work is:

  • you add a reference to a worker extension library (in this case: Element.Azure.Functions.Worker.Extensions.RoutePriority available via Nuget)
  • that worker extension library has an [ExtensionInformation] attribute that points to a different Nuget package that contains the actual logic which will be injected into the host (in this case: Element.Azure.WebJobs.Extensions.RoutePriority, which is also available on Nuget but should not be referenced directly from your function app)
  • when you compile your function app, the function metadata generator scans your code for binding extensions, creates a temporary .csproj file, and outputs the necessary .dlls and and emits an extensions.json file with metadata about your extension and the entry points

You don't need to know any of that in order to take advantage of this package, but it might be interesting to know what is going on under the hood.

References

Credit goes to Maarten Balliauw for documenting how to write custom extensions for isolated functions. It was invaluable in understanding how things worked internally.

The source code for the functions metadata generator (where you can see how items are stripped out if not used) is also interesting reading.

The source code for the Microsoft-provided extensions was also a great reference, as was the Dapr extension source code.

azurefunctionsisolatedroutepriority's People

Contributors

briandunnington avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.