Skip to content

Instantly share code, notes, and snippets.

@martijnlentink
Created December 5, 2023 09:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martijnlentink/da862d759fe989b8b0e7b6a7c4063104 to your computer and use it in GitHub Desktop.
Save martijnlentink/da862d759fe989b8b0e7b6a7c4063104 to your computer and use it in GitHub Desktop.
Get the URL of HTTP triggered Azure Function including path/query parameters. GetUrl(nameof(FunctionClass.Run))
namespace Namespace.Helpers
using Microsoft.Azure.Functions.Worker;
using Microsoft.AspNetCore.Routing.Template;
using System.Reflection;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.Extensions.ObjectPool;
using System.Text.Encodings.Web;
public class UrlFunctionsHelper
{
private static readonly Lazy<(FunctionAttribute? fnAttr, ParameterInfo[] parameters)[]> FunctionNameAttributesLazy = new (() => Assembly
.GetExecutingAssembly()
.GetTypes()
.SelectMany(x => x.GetMethods())
.Select(x => (x.GetCustomAttribute<FunctionAttribute>(), x.GetParameters()))
.Where(x => x.Item1 is not null)
.ToArray()
);
public static Uri GetUrl(string functionName, IDictionary<string, string>? routeValues = default)
{
var correspondingAttribute = FunctionNameAttributesLazy.Value
.FirstOrDefault(x => x.fnAttr?.Name == functionName);
if (correspondingAttribute.fnAttr is null)
{
throw new InvalidOperationException($"'{functionName}' is not a valid Azure Function, please make sure the {nameof(FunctionAttribute)} was set correctly");
}
#if DEBUG
const string scheme = "http";
#else
const string scheme = "https";
#endif
var hostname = Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME");
var httpTrigger = correspondingAttribute.parameters
.Select(x => x.GetCustomAttribute<HttpTriggerAttribute>())
.SingleOrDefault();
if (httpTrigger is null)
{
throw new InvalidOperationException(
$"Provided function had no parameter with attribute of type {nameof(HttpTriggerAttribute)}");
}
var preparedRoute = ParseRouteTemplate(httpTrigger?.Route ?? functionName, routeValues);
return new Uri($"{scheme}://{hostname}/api{preparedRoute}");
}
private static string? ParseRouteTemplate(string route, IDictionary<string, string>? routeValues)
{
var templateRoute = TemplateParser.Parse(route);
var pool = new DefaultObjectPoolProvider().Create(new UriBuilderContextPooledObjectPolicy());
var templateBinder = new TemplateBinder(UrlEncoder.Default, pool, templateRoute, defaults: null);
return templateBinder.BindValues(new RouteValueDictionary(routeValues));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment