Azure Functions HTTP Trigger
The HTTP trigger is the most commonly used trigger in Azure Functions. It turns a function into a REST API endpoint that accepts HTTP requests from browsers, mobile apps, or any service that can make HTTP calls. This topic covers every aspect of the HTTP trigger — from reading query strings to returning proper status codes and building clean REST APIs.
HTTP Trigger Architecture
┌──────────────────────────────────────────────────────────────┐ │ HTTP TRIGGER ARCHITECTURE │ │ │ │ Client (Browser / App / Postman) │ │ │ │ │ │ HTTP Request (GET / POST / PUT / DELETE) │ │ ▼ │ │ Azure API Gateway (handles routing, auth, SSL) │ │ │ │ │ ▼ │ │ Function App ──► HTTP Trigger ──► Your Function Code │ │ │ │ │ ▼ │ │ HTTP Response │ │ (status + body + headers) │ └──────────────────────────────────────────────────────────────┘
Authentication Levels (authLevel)
Every HTTP trigger has an authLevel that controls who can call the function. This is the first line of security.
| authLevel | Who Can Call It | When to Use |
|---|---|---|
| anonymous | Anyone — no key required | Public APIs, webhooks from trusted services |
| function | Callers with the function-specific API key | Default for most internal APIs |
| admin | Callers with the master API key only | Admin operations, very sensitive endpoints |
Calling a Function-Level Protected Endpoint
# Append the API key as a query parameter GET https://myapp.azurewebsites.net/api/GetOrder?code=abc123xyz&orderId=42 # Or send it as a header GET https://myapp.azurewebsites.net/api/GetOrder?orderId=42 x-functions-key: abc123xyz
Reading Request Data
The HTTP trigger passes the full incoming request as the req object. All request data is available through its properties.
| Property | What It Contains | Example |
|---|---|---|
| req.method | HTTP method used | "GET", "POST", "PUT" |
| req.url | Full URL of the request | https://…/api/GetOrder?id=5 |
| req.query | Query string parameters as an object | { id: "5", format: "json" } |
| req.params | Route parameters from URL pattern | { orderId: "42" } |
| req.headers | All HTTP headers as an object | { "content-type": "application/json" } |
| req.body | Request body (parsed JSON or string) | { name: "Amit", age: 30 } |
Example 1 – Reading Query String and Body
// function.json: httpTrigger, methods: ["get","post"], authLevel: "anonymous"
module.exports = async function (context, req) {
// Reading from query string (?category=electronics)
const category = req.query.category;
// Reading from JSON body
const productName = req.body && req.body.name;
context.log(`Category: ${category}, Product: ${productName}`);
context.res = {
status: 200,
body: { category, productName }
};
};
Example 2 – Route Parameters
Route parameters make URLs clean and readable. Instead of /api/GetOrder?id=42, use /api/orders/42.
function.json
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"authLevel": "anonymous",
"methods": ["get"],
"route": "orders/{orderId}"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
index.js
module.exports = async function (context, req) {
// orderId comes from the URL: /api/orders/42
const orderId = context.bindingData.orderId;
context.res = {
status: 200,
body: { message: `Fetching order ${orderId}` }
};
};
URL Pattern
Without route: GET /api/GetOrder?orderId=42 With route: GET /api/orders/42 ← Clean REST URL
HTTP Response Structure
The response object sent back to the caller has three parts:
context.res = {
status: 200, // HTTP status code
headers: { // Response headers (optional)
"Content-Type": "application/json"
},
body: { // Response body
message: "Success"
}
};
Common HTTP Status Codes
| Status Code | Meaning | When to Use |
|---|---|---|
| 200 | OK | Successful GET or POST that returns data |
| 201 | Created | Successful POST that creates a new resource |
| 204 | No Content | Successful DELETE with no response body |
| 400 | Bad Request | Missing required field in request |
| 401 | Unauthorized | API key missing or invalid |
| 404 | Not Found | Requested resource does not exist |
| 500 | Internal Server Error | Unexpected error in function code |
Example 3 – Building a Mini CRUD REST API
This example shows a single function that handles multiple HTTP methods to simulate a product API.
module.exports = async function (context, req) {
const method = req.method;
const productId = context.bindingData.productId;
if (method === "GET") {
context.res = {
status: 200,
body: { id: productId, name: "Laptop", price: 75000 }
};
}
else if (method === "POST") {
const newProduct = req.body;
// In real code: save to database
context.res = {
status: 201,
body: { message: "Product created", product: newProduct }
};
}
else if (method === "DELETE") {
// In real code: delete from database
context.res = {
status: 204,
body: null
};
}
else {
context.res = {
status: 405,
body: { error: "Method not allowed" }
};
}
};
CORS – Allowing Browser Requests
When a browser JavaScript app calls an Azure Function from a different domain, CORS (Cross-Origin Resource Sharing) must be configured. Without it, the browser blocks the request.
┌──────────────────────────────────────────────────────────┐ │ CORS FLOW │ │ │ │ Browser App (www.mystore.com) │ │ │ │ │ │ GET https://myapp.azurewebsites.net/api/... │ │ ▼ │ │ Browser checks: Is this origin allowed? │ │ │ │ │ ├── CORS allows it → Request goes through ✓ │ │ └── CORS blocks it → Browser error ✗ │ └──────────────────────────────────────────────────────────┘
In Azure Portal → Function App → CORS, add the allowed origins. For local development, add http://localhost:3000 (or whichever port the frontend runs on).
Returning JSON vs Plain Text
| Body Type | Code Example | Content-Type Header |
|---|---|---|
| Plain text | body: "Hello World" | text/plain |
| JSON object | body: { name: "Ravi" } | application/json (auto) |
| JSON string | body: JSON.stringify(obj) | application/json |
When the body is a JavaScript object, Azure Functions automatically serializes it to JSON and sets the correct Content-Type header.
