{"id":18086199,"url":"https://github.com/shibayan/azure-functions-http-api","last_synced_at":"2026-04-04T08:02:42.942Z","repository":{"id":40654147,"uuid":"241135429","full_name":"shibayan/azure-functions-http-api","owner":"shibayan","description":"HTTP API Extensions for Azure Functions","archived":false,"fork":false,"pushed_at":"2025-02-03T06:04:52.000Z","size":210,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T16:39:15.757Z","etag":null,"topics":["azure-functions","http-api"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shibayan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"shibayan","custom":"paypal.me/shibayan"}},"created_at":"2020-02-17T15:02:03.000Z","updated_at":"2025-03-08T16:07:38.000Z","dependencies_parsed_at":"2025-02-03T07:19:36.346Z","dependency_job_id":"304775bb-c92d-4e48-83d0-df571e86943f","html_url":"https://github.com/shibayan/azure-functions-http-api","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shibayan%2Fazure-functions-http-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shibayan%2Fazure-functions-http-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shibayan%2Fazure-functions-http-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shibayan%2Fazure-functions-http-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shibayan","download_url":"https://codeload.github.com/shibayan/azure-functions-http-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248642803,"owners_count":21138352,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure-functions","http-api"],"created_at":"2024-10-31T16:07:15.959Z","updated_at":"2026-04-04T08:02:42.933Z","avatar_url":"https://github.com/shibayan.png","language":"C#","readme":"# HTTP API Extensions for Azure Functions\n\n[![Build](https://github.com/shibayan/azure-functions-http-api/workflows/Build/badge.svg)](https://github.com/shibayan/azure-functions-http-api/actions/workflows/build.yml)\n[![License](https://badgen.net/github/license/shibayan/azure-functions-http-api)](https://github.com/shibayan/azure-functions-http-api/blob/master/LICENSE)\n\n| Package | NuGet |\n|---------|-------|\n| WebJobs.Extensions.HttpApi (In-Process) | [![NuGet](https://badgen.net/nuget/v/WebJobs.Extensions.HttpApi)](https://www.nuget.org/packages/WebJobs.Extensions.HttpApi/) [![Downloads](https://badgen.net/nuget/dt/WebJobs.Extensions.HttpApi)](https://www.nuget.org/packages/WebJobs.Extensions.HttpApi/) |\n| Functions.Worker.Extensions.HttpApi (Isolated Worker) | [![NuGet](https://badgen.net/nuget/v/Functions.Worker.Extensions.HttpApi)](https://www.nuget.org/packages/Functions.Worker.Extensions.HttpApi/) [![Downloads](https://badgen.net/nuget/dt/Functions.Worker.Extensions.HttpApi)](https://www.nuget.org/packages/Functions.Worker.Extensions.HttpApi/) |\n\nAn extension library that brings ASP.NET Core-like developer experience to Azure Functions. Inherit from `HttpFunctionBase` to get access to familiar helpers such as `Ok()`, `BadRequest()`, `File()`, model validation, URL generation, and more — in both **In-Process** and **Isolated Worker** models.\n\n## Features\n\n- **Model validation** — Validate request models with DataAnnotations using `TryValidateModel()` and return `BadRequest(ModelState)` or `ValidationProblem(ModelState)`\n- **ASP.NET Core-like helpers** — Use familiar methods such as `Ok()`, `BadRequest()`, `NotFound()`, `Unauthorized()`, `Content()`, `File()`, and access `Request` / `Response` / `User` directly\n- **URL generation** — Generate URLs to other functions with `CreatedAtFunction()` and `AcceptedAtFunction()`\n- **Static file hosting** — Serve files from `wwwroot` with automatic content-type detection\n- **Reverse proxy** — Forward requests to backend services with `Proxy()`, supporting route template substitution\n- **SPA / SSG hosting** — Host single-page applications with `LocalStaticApp()`, including fallback routing and path exclusion\n- **App Service Authentication** — Access authenticated user info via the `User` property with App Service Authentication (EasyAuth) support\n- **Better route precedence** — Improved route matching behavior over default Azure Functions routing\n\n## Installation\n\n### .NET Isolated Worker (Recommended)\n\n```\ndotnet add package Functions.Worker.Extensions.HttpApi\n```\n\n### .NET In-Process\n\n```\ndotnet add package WebJobs.Extensions.HttpApi\n```\n\n## Quick Start\n\n### Isolated Worker\n\nUse ASP.NET Core integration in `Program.cs`. The extension is registered automatically by the package.\n\n```csharp\n// Program.cs\nvar builder = FunctionsApplication.CreateBuilder(args);\n\nbuilder.ConfigureFunctionsWebApplication();\n\nbuilder.Build().Run();\n```\n\n```csharp\n// Function1.cs\npublic class Function1(IHttpContextAccessor httpContextAccessor) : HttpFunctionBase(httpContextAccessor)\n{\n    [Function(\"Function1\")]\n    public IActionResult Run(\n        [HttpTrigger(AuthorizationLevel.Function, \"get\")] HttpRequest req)\n    {\n        return Ok($\"Hello, {req.Query[\"name\"]}\");\n    }\n}\n```\n\n### In-Process\n\n```csharp\npublic class Function1(IHttpContextAccessor httpContextAccessor) : HttpFunctionBase(httpContextAccessor)\n{\n    [FunctionName(\"Function1\")]\n    public IActionResult Run(\n        [HttpTrigger(AuthorizationLevel.Function, \"get\")] HttpRequest req)\n    {\n        return Ok($\"Hello, {req.Query[\"name\"]}\");\n    }\n}\n```\n\n## Examples\n\n### Model Validation\n\nUse `TryValidateModel()` with DataAnnotations to validate incoming request bodies.\n\n```csharp\npublic class Function1(IHttpContextAccessor httpContextAccessor) : HttpFunctionBase(httpContextAccessor)\n{\n    [FunctionName(\"Function1\")]\n    public IActionResult Run(\n        [HttpTrigger(AuthorizationLevel.Function, \"post\")] SampleModel model)\n    {\n        if (!TryValidateModel(model))\n        {\n            return BadRequest(ModelState);\n        }\n\n        return Ok(model);\n    }\n}\n\npublic class SampleModel\n{\n    [Required]\n    public string Name { get; set; }\n\n    public string[] Array { get; set; }\n\n    [Range(100, 10000)]\n    public int Price { get; set; }\n}\n```\n\nYou can also return RFC 7807 Problem Details format using `ValidationProblem()`:\n\n```csharp\nif (!TryValidateModel(model))\n{\n    return ValidationProblem(ModelState);\n}\n```\n\n### Accessing Request / Response / User\n\nAccess `HttpContext`, `Request`, `Response`, and `User` properties directly, just like in ASP.NET Core controllers.\n\n```csharp\npublic class Function2(IHttpContextAccessor httpContextAccessor) : HttpFunctionBase(httpContextAccessor)\n{\n    [FunctionName(\"Function2\")]\n    public IActionResult Run(\n        [HttpTrigger(AuthorizationLevel.Function, \"get\")] HttpRequest req)\n    {\n        Response.Headers.Add(\"Cache-Control\", \"no-cache\");\n\n        return Ok($\"Now: {DateTime.Now}\");\n    }\n}\n```\n\n### URL Generation\n\nGenerate URLs to other functions using `CreatedAtFunction()` and `AcceptedAtFunction()`.\n\n```csharp\npublic class Function3(IHttpContextAccessor httpContextAccessor) : HttpFunctionBase(httpContextAccessor)\n{\n    [FunctionName(\"Function3\")]\n    public IActionResult Run(\n        [HttpTrigger(AuthorizationLevel.Function, \"get\", Route = \"route/{id}\")] HttpRequest req,\n        string id)\n    {\n        return CreatedAtFunction(\"Function3\", new { id = \"kazuakix\" }, null);\n    }\n}\n```\n\n### Static File Hosting\n\nServe files from the `wwwroot` directory with automatic content-type detection.\n\n```csharp\npublic class Function1(IHttpContextAccessor httpContextAccessor) : HttpFunctionBase(httpContextAccessor)\n{\n    [FunctionName(\"Function1\")]\n    public IActionResult Run(\n        [HttpTrigger(AuthorizationLevel.Anonymous, \"get\")] HttpRequest req)\n    {\n        return File(\"sample.html\");\n    }\n}\n```\n\n### Reverse Proxy\n\nForward incoming requests to a backend service. Route parameters are automatically substituted in the backend URI.\nYou can also inspect or modify the proxied request and response with async hooks.\n\n```csharp\npublic class ReverseProxy(IHttpContextAccessor httpContextAccessor) : HttpFunctionBase(httpContextAccessor)\n{\n    [FunctionName(nameof(ReverseProxy))]\n    public IActionResult Run(\n        [HttpTrigger(AuthorizationLevel.Anonymous, \"get\", \"post\", \"put\", \"delete\", Route = \"{*path}\")] HttpRequest req)\n    {\n        return Proxy(\n            \"https://example.com/{path}\",\n            async request =\u003e\n            {\n                request.Headers.Add(\"X-Forwarded-By\", \"azure-functions-http-api\");\n                await Task.CompletedTask;\n            },\n            async response =\u003e\n            {\n                response.Headers.Add(\"X-Proxied\", \"true\");\n                await Task.CompletedTask;\n            });\n    }\n}\n```\n\n### SPA / SSG Hosting\n\nHost single-page applications or static sites with client-side routing support. `LocalStaticApp()` serves files from the local `wwwroot` directory and applies a fallback file when the requested path does not exist.\n\nUse a catch-all route such as `{*path}` so the static app handler can resolve the requested virtual path.\n\n```csharp\npublic class StaticWebsite(IHttpContextAccessor httpContextAccessor) : HttpFunctionBase(httpContextAccessor)\n{\n    [FunctionName(nameof(StaticWebsite))]\n    public IActionResult Run(\n        [HttpTrigger(AuthorizationLevel.Anonymous, \"get\", Route = \"{*path}\")] HttpRequest req)\n    {\n        // Serve from local wwwroot with SPA fallback\n        return LocalStaticApp(fallbackPath: \"200.html\", fallbackExcludePattern: \"^/_nuxt/.*\");\n    }\n}\n```\n\n### App Service Authentication\n\nWhen App Service Authentication (EasyAuth) is enabled, access the authenticated user via the `User` property.\n\n```csharp\npublic class SecureFunction(IHttpContextAccessor httpContextAccessor) : HttpFunctionBase(httpContextAccessor)\n{\n    [Function(\"SecureFunction\")]\n    public IActionResult Run(\n        [HttpTrigger(AuthorizationLevel.Anonymous, \"get\")] HttpRequest req)\n    {\n        if (!User.Identity.IsAuthenticated)\n        {\n            return Unauthorized();\n        }\n\n        return Ok($\"Hello, {User.Identity.Name}\");\n    }\n}\n```\n\n## Available Helpers\n\n| Method | Description |\n|--------|-------------|\n| `Ok()` / `Ok(value)` | Returns 200 OK |\n| `BadRequest()` / `BadRequest(ModelState)` | Returns 400 Bad Request |\n| `Unauthorized()` | Returns 401 Unauthorized |\n| `Forbid()` | Returns 403 Forbidden |\n| `NotFound()` / `NotFound(value)` | Returns 404 Not Found |\n| `Conflict()` / `Conflict(ModelState)` | Returns 409 Conflict |\n| `NoContent()` | Returns 204 No Content |\n| `StatusCode(code)` | Returns a custom status code |\n| `Content(string, contentType)` | Returns content with a specific content type |\n| `File(path)` / `File(bytes, contentType)` / `File(stream, contentType)` | Returns a file response |\n| `CreatedAtFunction(functionName, routeValues, value)` | Returns 201 with a Location header pointing to the specified function |\n| `AcceptedAtFunction(functionName, routeValues, value)` | Returns 202 with a Location header pointing to the specified function |\n| `TryValidateModel(model)` | Validates the model using DataAnnotations |\n| `ValidationProblem(ModelState)` | Returns RFC 7807 Problem Details for validation errors |\n| `Problem(detail, instance, statusCode, title, type)` | Returns RFC 7807 Problem Details |\n| `Proxy(backendUri, beforeSend, afterSend)` | Forwards the request to a backend service with optional async hooks |\n| `LocalStaticApp(defaultFile, fallbackPath, fallbackExcludePattern)` | Serves static files from local `wwwroot` with SPA fallback |\n\n## License\n\nThis project is licensed under the [MIT License](https://github.com/shibayan/azure-functions-http-api/blob/master/LICENSE)\n","funding_links":["https://github.com/sponsors/shibayan","paypal.me/shibayan"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshibayan%2Fazure-functions-http-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshibayan%2Fazure-functions-http-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshibayan%2Fazure-functions-http-api/lists"}