您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

Azure Functions HTTP 触发器和绑定Azure Functions HTTP triggers and bindings

本文介绍如何在 Azure Functions 中使用 HTTP 触发器和输出绑定。This article explains how to work with HTTP triggers and output bindings in Azure Functions.

HTTP 触发器可进行自定义以响应 WebhookAn HTTP trigger can be customized to respond to webhooks.

此参考信息面向 Azure Functions 开发人员。This is reference information for Azure Functions developers. Azure Functions 的新手请从以下资源入手:If you're new to Azure Functions, start with the following resources:

提示

如果计划使用 HTTP 或 WebHook 绑定,请制定计划来避免因实例化 HttpClient 不当导致的端口耗尽现象。If you plan to use the HTTP or WebHook bindings, plan to avoid port exhaustion that can be caused by improper instantiation of HttpClient. 有关详细信息,请参阅如何在 Azure Functions 中管理连接For more information, see How to manage connections in Azure Functions.

本文中的代码默认使用 Functions 2.x 语法,该语法使用 .NET Core。The code in this article defaults to Functions 2.x syntax which uses .NET Core. 有关 1.x 语法的信息,请参阅 1.x functions 模板For information on the 1.x syntax, see the 1.x functions templates.

包 - Functions 1.xPackages - Functions 1.x

Microsoft.Azure.WebJobs.Extensions.Http NuGet 包 1.x 版本中提供了 HTTP 绑定。The HTTP bindings are provided in the Microsoft.Azure.WebJobs.Extensions.Http NuGet package, version 1.x. azure-webjobs-sdk-extensions GitHub 存储库中提供了此包的源代码。Source code for the package is in the azure-webjobs-sdk-extensions GitHub repository.

在所有开发环境中自动提供对该绑定的支持。Support for this binding is automatically provided in all development environments. 无需手动安装包或注册扩展。You don't have to manually install the package or register the extension.

包 - Functions 2.xPackages - Functions 2.x

Microsoft.Azure.WebJobs.Extensions.Http NuGet 包 3.x 版本中提供了 HTTP 绑定。The HTTP bindings are provided in the Microsoft.Azure.WebJobs.Extensions.Http NuGet package, version 3.x. azure-webjobs-sdk-extensions GitHub 存储库中提供了此包的源代码。Source code for the package is in the azure-webjobs-sdk-extensions GitHub repository.

在所有开发环境中自动提供对该绑定的支持。Support for this binding is automatically provided in all development environments. 无需手动安装包或注册扩展。You don't have to manually install the package or register the extension.

触发器Trigger

借助 HTTP 触发器,可以使用 HTTP 请求调用函数。The HTTP trigger lets you invoke a function with an HTTP request. 可以使用 HTTP 触发器生成无服务器 API 和响应 Webhook。You can use an HTTP trigger to build serverless APIs and respond to webhooks.

默认情况下,在 Functions 1.x 中,HTTP 触发器返回“HTTP 200 正常”和空的正文;在 Functions 2.x 中返回“HTTP 204 无内容”和空的正文。By default, an HTTP trigger returns HTTP 200 OK with an empty body in Functions 1.x, or HTTP 204 No Content with an empty body in Functions 2.x. 若要修改该响应,请配置 HTTP 输出绑定To modify the response, configure an HTTP output binding.

触发器 - 示例Trigger - example

参阅语言特定的示例:See the language-specific example:

触发器 - C# 示例Trigger - C# example

以下示例显示一个在查询字符串或 HTTP 请求正文中查找 name 参数的 C# 函数The following example shows a C# function that looks for a name parameter either in the query string or the body of the HTTP request. 请注意,返回值用于输出绑定,但不需要返回值属性。Notice that the return value is used for the output binding, but a return value attribute isn't required.

[FunctionName("HttpTriggerCSharp")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] 
    HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    name = name ?? data?.name;

    return name != null
        ? (ActionResult)new OkObjectResult($"Hello, {name}")
        : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}

触发器 - C# 脚本示例Trigger - C# script example

以下示例演示 function.json 文件中的一个触发器绑定以及使用该绑定的 C# 脚本函数The following example shows a trigger binding in a function.json file and a C# script function that uses the binding. 该函数在查询字符串或 HTTP 请求的正文中查找 name 参数。The function looks for a name parameter either in the query string or the body of the HTTP request.

function.json 文件如下所示:Here's the function.json file:

{
    "disabled": false,
    "bindings": [
        {
            "authLevel": "function",
            "name": "req",
            "type": "httpTrigger",
            "direction": "in",
            "methods": [
                "get",
                "post"
            ]
        },
        {
            "name": "$return",
            "type": "http",
            "direction": "out"
        }
    ]
}

配置部分解释了这些属性。The configuration section explains these properties.

下面是绑定到 HttpRequest 的 C# 脚本代码:Here's C# script code that binds to HttpRequest:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    name = name ?? data?.name;

    return name != null
        ? (ActionResult)new OkObjectResult($"Hello, {name}")
        : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}

可以绑定到自定义对象而不是 HttpRequestYou can bind to a custom object instead of HttpRequest. 此对象从请求正文进行创建,并分析为 JSON。This object is created from the body of the request and parsed as JSON. 同样,可以将类型传递给 HTTP 响应输出绑定,并作为响应正文随 200 状态代码一同返回。Similarly, a type can be passed to the HTTP response output binding and returned as the response body, along with a 200 status code.

using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

public static string Run(Person person, ILogger log)
{   
    return person.Name != null
        ? (ActionResult)new OkObjectResult($"Hello, {person.Name}")
        : new BadRequestObjectResult("Please pass an instance of Person.");
}

public class Person {
     public string Name {get; set;}
}

触发器 - F# 示例Trigger - F# example

以下示例演示 function.json 文件中的一个触发器绑定以及使用该绑定的 F# 函数The following example shows a trigger binding in a function.json file and an F# function that uses the binding. 该函数在查询字符串或 HTTP 请求的正文中查找 name 参数。The function looks for a name parameter either in the query string or the body of the HTTP request.

function.json 文件如下所示:Here's the function.json file:

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "name": "res",
      "type": "http",
      "direction": "out"
    }
  ],
  "disabled": false
}

配置部分解释了这些属性。The configuration section explains these properties.

F# 代码如下所示:Here's the F# code:

open System.Net
open System.Net.Http
open FSharp.Interop.Dynamic

let Run(req: HttpRequestMessage) =
    async {
        let q =
            req.GetQueryNameValuePairs()
                |> Seq.tryFind (fun kv -> kv.Key = "name")
        match q with
        | Some kv ->
            return req.CreateResponse(HttpStatusCode.OK, "Hello " + kv.Value)
        | None ->
            let! data = Async.AwaitTask(req.Content.ReadAsAsync<obj>())
            try
                return req.CreateResponse(HttpStatusCode.OK, "Hello " + data?name)
            with e ->
                return req.CreateErrorResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
    } |> Async.StartAsTask

需要一个使用 NuGet 引用 FSharp.Interop.DynamicDynamitey 程序集的 project.json 文件,如以下示例中所示:You need a project.json file that uses NuGet to reference the FSharp.Interop.Dynamic and Dynamitey assemblies, as shown in the following example:

{
  "frameworks": {
    "net46": {
      "dependencies": {
        "Dynamitey": "1.0.2",
        "FSharp.Interop.Dynamic": "3.0.0"
      }
    }
  }
}

触发器 - JavaScript 示例Trigger - JavaScript example

以下示例演示 function.json 文件中的一个触发器绑定以及使用该绑定的 JavaScript 函数The following example shows a trigger binding in a function.json file and a JavaScript function that uses the binding. 该函数在查询字符串或 HTTP 请求的正文中查找 name 参数。The function looks for a name parameter either in the query string or the body of the HTTP request.

function.json 文件如下所示:Here's the function.json file:

{
    "disabled": false,    
    "bindings": [
        {
            "authLevel": "function",
            "type": "httpTrigger",
            "direction": "in",
            "name": "req"
        },
        {
            "type": "http",
            "direction": "out",
            "name": "res"
        }
    ]
}

配置部分解释了这些属性。The configuration section explains these properties.

JavaScript 代码如下所示:Here's the JavaScript code:

module.exports = function(context, req) {
    context.log('Node.js HTTP trigger function processed a request. RequestUri=%s', req.originalUrl);

    if (req.query.name || (req.body && req.body.name)) {
        context.res = {
            // status defaults to 200 */
            body: "Hello " + (req.query.name || req.body.name)
        };
    }
    else {
        context.res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        };
    }
    context.done();
};

触发器 - Python 示例Trigger - Python example

以下示例演示 function.json 文件中的一个触发器绑定以及使用该绑定的 Python 函数The following example shows a trigger binding in a function.json file and a Python function that uses the binding. 该函数在查询字符串或 HTTP 请求的正文中查找 name 参数。The function looks for a name parameter either in the query string or the body of the HTTP request.

function.json 文件如下所示:Here's the function.json file:

{
    "scriptFile": "__init__.py",
    "disabled": false,    
    "bindings": [
        {
            "authLevel": "function",
            "type": "httpTrigger",
            "direction": "in",
            "name": "req"
        },
        {
            "type": "http",
            "direction": "out",
            "name": "res"
        }
    ]
}

配置部分解释了这些属性。The configuration section explains these properties.

下面是 Python 代码:Here's the Python code:

import logging
import azure.functions as func


def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        return func.HttpResponse(f"Hello {name}!")
    else:
        return func.HttpResponse(
            "Please pass a name on the query string or in the request body",
            status_code=400
        )

触发器 - Java 示例Trigger - Java examples

下面的示例说明 function.json 文件中的 HTTP 触发器绑定,以及使用该绑定的相应 Java 函数The following examples show the HTTP trigger binding in a function.json file and the respective Java functions that use the binding.

function.json 文件如下所示:Here's the function.json file:

{
    "disabled": false,    
    "bindings": [
        {
            "authLevel": "anonymous",
            "type": "httpTrigger",
            "direction": "in",
            "name": "req"
        },
        {
            "type": "http",
            "direction": "out",
            "name": "res"
        }
    ]
}

从查询字符串中读取参数 (Java)Read parameter from the query string (Java)

以下示例从查询字符串中读取名为 id 的参数,然后使用该参数构建返回到客户端的 JSON 文档(内容类型为 application/json)。This example reads a parameter, named id, from the query string, and uses it to build a JSON document returned to the client, with content type application/json.

    @FunctionName("TriggerStringGet")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", 
              methods = {HttpMethod.GET}, 
              authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        
        // Item list
        context.getLogger().info("GET parameters are: " + request.getQueryParameters());

        // Get named parameter
        String id = request.getQueryParameters().getOrDefault("id", "");

        // Convert and display
        if (id.isEmpty()) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
                          .body("Document not found.")
                          .build();
        } 
        else {
            // return JSON from to the client
            // Generate document
            final String name = "fake_name";
            final String jsonDocument = "{\"id\":\"" + id + "\", " + 
                                         "\"description\": \"" + name + "\"}";
            return request.createResponseBuilder(HttpStatus.OK)
                          .header("Content-Type", "application/json")
                          .body(jsonDocument)
                          .build();
        }
    }

从 POST 请求中读取正文 (Java)Read body from a POST request (Java)

以下示例将 POST 请求的正文读取为 String,然后使用该正文构建返回到客户端的 JSON 文档(内容类型为 application/json)。This example reads the body of a POST request, as a String, and uses it to build a JSON document returned to the client, with content type application/json.

    @FunctionName("TriggerStringPost")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", 
              methods = {HttpMethod.POST}, 
              authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        
        // Item list
        context.getLogger().info("Request body is: " + request.getBody().orElse(""));

        // Check request body
        if (!request.getBody().isPresent()) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
                          .body("Document not found.")
                          .build();
        } 
        else {
            // return JSON from to the client
            // Generate document
            final String body = request.getBody().get();
            final String jsonDocument = "{\"id\":\"123456\", " + 
                                         "\"description\": \"" + body + "\"}";
            return request.createResponseBuilder(HttpStatus.OK)
                          .header("Content-Type", "application/json")
                          .body(jsonDocument)
                          .build();
        }
    }

从路由中读取参数 (Java)Read parameter from a route (Java)

此示例读取名为 id 的必选参数,并从路由路径中读取可选参数 name,然后使用这两个参数构建返回到客户端的 JSON 文档(内容类型为 application/json)。This example reads a mandatory parameter, named id, and an optional parameter name from the route path, and uses them to build a JSON document returned to the client, with content type application/json. TT

    @FunctionName("TriggerStringRoute")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", 
              methods = {HttpMethod.GET}, 
              authLevel = AuthorizationLevel.ANONYMOUS,
              route = "trigger/{id}/{name=EMPTY}") // name is optional and defaults to EMPTY
            HttpRequestMessage<Optional<String>> request,
            @BindingName("id") String id,
            @BindingName("name") String name,
            final ExecutionContext context) {
        
        // Item list
        context.getLogger().info("Route parameters are: " + id);

        // Convert and display
        if (id == null) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
                          .body("Document not found.")
                          .build();
        } 
        else {
            // return JSON from to the client
            // Generate document
            final String jsonDocument = "{\"id\":\"" + id + "\", " + 
                                         "\"description\": \"" + name + "\"}";
            return request.createResponseBuilder(HttpStatus.OK)
                          .header("Content-Type", "application/json")
                          .body(jsonDocument)
                          .build();
        }
    }

从 POST 请求中读取 POJO 正文 (Java)Read POJO body from a POST request (Java)

下面是此示例中引用的 ToDoItem 类的代码:Here is the code for the ToDoItem class, referenced in this example:


public class ToDoItem {

  private String id;
  private String description;  

  public ToDoItem(String id, String description) {
    this.id = id;
    this.description = description;
  }

  public String getId() {
    return id;
  }

  public String getDescription() {
    return description;
  }
  
  @Override
  public String toString() {
    return "ToDoItem={id=" + id + ",description=" + description + "}";
  }
}

此示例读取 POST 请求的正文。This example reads the body of a POST request. 该请求正文会自动反序列化为 ToDoItem 对象,然后以内容类型 application/json 返回到客户端。The request body gets automatically de-serialized into a ToDoItem object, and is returned to the client, with content type application/json. ToDoItem 参数分配给 HttpMessageResponse.Builder 类的 body 属性时,它会由 Functions 运行时序列化。The ToDoItem parameter is serialized by the Functions runtime as it is assigned to the body property of the HttpMessageResponse.Builder class.

    @FunctionName("TriggerPojoPost")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", 
              methods = {HttpMethod.POST}, 
              authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<ToDoItem>> request,
            final ExecutionContext context) {
        
        // Item list
        context.getLogger().info("Request body is: " + request.getBody().orElse(null));

        // Check request body
        if (!request.getBody().isPresent()) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
                          .body("Document not found.")
                          .build();
        } 
        else {
            // return JSON from to the client
            // Generate document
            final ToDoItem body = request.getBody().get();
            return request.createResponseBuilder(HttpStatus.OK)
                          .header("Content-Type", "application/json")
                          .body(body)
                          .build();
        }
    }

触发器 - 特性Trigger - attributes

C# 类库中,使用 HttpTrigger 特性。In C# class libraries, use the HttpTrigger attribute.

可以在特性构造函数参数中设置授权级别和允许的 HTTP 方法,Webhook 类型和路由模板有相应的属性。You can set the authorization level and allowable HTTP methods in attribute constructor parameters, and there are properties for webhook type and route template. 有关这些设置的详细信息,请参阅触发器 - 配置For more information about these settings, see Trigger - configuration. 下面是某个方法签名中的 HttpTrigger 特性:Here's an HttpTrigger attribute in a method signature:

[FunctionName("HttpTriggerCSharp")]
public static Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req)
{
    ...
}

有关完整示例,请参阅触发器 - C# 示例For a complete example, see Trigger - C# example.

触发器 - 配置Trigger - configuration

下表解释了在 function.json 文件和 HttpTrigger 特性中设置的绑定配置属性。The following table explains the binding configuration properties that you set in the function.json file and the HttpTrigger attribute.

function.json 属性function.json property Attribute 属性Attribute property 说明Description
typetype 不适用n/a 必需 - 必须设置为 httpTriggerRequired - must be set to httpTrigger.
direction direction 不适用n/a 必需 - 必须设置为 inRequired - must be set to in.
name name 不适用n/a 必需 - 在请求或请求正文的函数代码中使用的变量名称。Required - the variable name used in function code for the request or request body.
authLevelauthLevel AuthLevel AuthLevel 确定请求中需要提供的密钥(如果有),以便调用此函数。Determines what keys, if any, need to be present on the request in order to invoke the function. 授权级别可以是以下值之一:The authorization level can be one of the following values:
  • anonymous—无需 API 密钥。anonymous—No API key is required.
  • function—特定于函数的 API 密钥是必需的。function—A function-specific API key is required. 如果未提供任何值,该值为默认值。This is the default value if none is provided.
  • admin—无需主密钥。admin—The master key is required.
有关详细信息,请参阅有关授权密钥的部分。For more information, see the section about authorization keys.
methods methods 方法 Methods HTTP 方法的数组,该函数将响应此方法。An array of the HTTP methods to which the function responds. 如果未指定,该函数将响应所有 HTTP 方法。If not specified, the function responds to all HTTP methods. 参阅自定义 HTTP 终结点See customize the http endpoint.
route route Route Route 定义路由模板,控制函数将响应的请求 URL。Defines the route template, controlling to which request URLs your function responds. 如果未提供任何值,则默认值为 <functionname>The default value if none is provided is <functionname>. 有关详细信息,请参阅自定义 HTTP 终结点For more information, see customize the http endpoint.
webHookType webHookType WebHookType WebHookType 仅支持 1.x 版运行时。 Supported only for the version 1.x runtime.

将 HTTP 触发器配置为充当指定提供程序的 webhook 接收器。Configures the HTTP trigger to act as a webhook receiver for the specified provider. 如果未设置此属性,请不要设置 methods 属性。Don't set the methods property if you set this property. Webhook 类型可以是以下值之一:The webhook type can be one of the following values:
  • genericJson—不包含特定提供程序逻辑的常规用途 webhook 终结点。genericJson—A general-purpose webhook endpoint without logic for a specific provider. 此设置会将请求限制为仅请求使用 HTTP POST 以及内容类型为 application/jsonThis setting restricts requests to only those using HTTP POST and with the application/json content type.
  • github—该函数响应 GitHub Webhookgithub—The function responds to GitHub webhooks. 不要对 GitHub Webhook 使用 authLevel 属性。Do not use the authLevel property with GitHub webhooks. 有关详细信息,请参阅本文后面的“GitHub Webhook”部分。For more information, see the GitHub webhooks section later in this article.
  • slack—该函数响应 Slack Webhookslack—The function responds to Slack webhooks. 不要对 Slack Webhook 使用 authLevel 属性。Do not use the authLevel property with Slack webhooks. 有关详细信息,请参阅本文后面的“Slack Webhook”部分。For more information, see the Slack webhooks section later in this article.

触发器 - 用法Trigger - usage

对于 C# 和 F # 函数,可以将触发器输入的类型声明为 HttpRequest 或自定义类型。For C# and F# functions, you can declare the type of your trigger input to be either HttpRequest or a custom type. 如果选择 HttpRequest,会获得对请求对象的完全访问权限。If you choose HttpRequest, you get full access to the request object. 对于自定义类型,运行时会尝试分析 JSON 请求正文,以设置对象属性。For a custom type, the runtime tries to parse the JSON request body to set the object properties.

对于 JavaScript 函数,Functions 运行时提供请求正文而不是请求对象。For JavaScript functions, the Functions runtime provides the request body instead of the request object. 有关详细信息,请参阅 JavaScript 触发器示例For more information, see the JavaScript trigger example.

自定义 HTTP 终结点Customize the HTTP endpoint

默认情况下,创建 HTTP 触发器的函数时,可通过以下格式的路由对该函数进行寻址:By default when you create a function for an HTTP trigger, the function is addressable with a route of the form:

http://<yourapp>.azurewebsites.net/api/<funcname>

在 HTTP 触发器的输入绑定中,可以使用可选 route 属性自定义此路由。You can customize this route using the optional route property on the HTTP trigger's input binding. 例如,以下 function.json 文件定义了 HTTP 触发器的 route 属性:As an example, the following function.json file defines a route property for an HTTP trigger:

{
    "bindings": [
    {
        "type": "httpTrigger",
        "name": "req",
        "direction": "in",
        "methods": [ "get" ],
        "route": "products/{category:alpha}/{id:int?}"
    },
    {
        "type": "http",
        "name": "res",
        "direction": "out"
    }
    ]
}

通过此配置,现在可以通过以下路由对该函数进行寻址,而不是通过原始路由寻址。Using this configuration, the function is now addressable with the following route instead of the original route.

http://<yourapp>.azurewebsites.net/api/products/electronics/357

这使得函数代码可以支持地址中的两个参数:“category”和“id” 。可以将任何 Web API 路由约束与参数配合使用。This allows the function code to support two parameters in the address, category and id. You can use any Web API Route Constraint with your parameters. 以下 C# 函数代码使用了这两个参数。The following C# function code makes use of both parameters.

public static Task<IActionResult> Run(HttpRequest req, string category, int? id, ILogger log)
{
    if (id == null)
    {
        return (ActionResult)new OkObjectResult($"All {category} items were requested.");
    }
    else
    {
        return (ActionResult)new OkObjectResult($"{category} item with id = {id} has been requested.");
    }
    
    // -----
    log.LogInformation($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");
}

以下是使用相同路由参数的 Node.js 函数代码。Here is Node.js function code that uses the same route parameters.

module.exports = function (context, req) {

    var category = context.bindingData.category;
    var id = context.bindingData.id;

    if (!id) {
        context.res = {
            // status defaults to 200 */
            body: "All " + category + " items were requested."
        };
    }
    else {
        context.res = {
            // status defaults to 200 */
            body: category + " item with id = " + id + " was requested."
        };
    }

    context.done();
}

默认情况下,所有函数路由的前缀均为 api 。By default, all function routes are prefixed with api. 还可以使用 host.json 文件中的 http.routePrefix 属性自定义或删除前缀。You can also customize or remove the prefix using the http.routePrefix property in your host.json file. 以下示例通过将空字符串用于 host.json 文件中的前缀删除 api 路由前缀。The following example removes the api route prefix by using an empty string for the prefix in the host.json file.

{
    "http": {
    "routePrefix": ""
    }
}

使用客户端标识Working with client identities

如果函数应用使用应用服务身份验证/授权,则可通过代码查看有关已验证身份的客户端的信息。If your function app is using App Service Authentication / Authorization, you can view information about authenticated clients from your code. 此信息以平台注入的请求标头的形式提供。This information is available as request headers injected by the platform.

还可从绑定数据中读取此信息。You can also read this information from binding data. 此功能仅可用于 Functions 2.x 运行时,This capability is only available to the Functions 2.x runtime. 而且它目前仅可用于 .NET 语言。It is also currently only available for .NET languages.

在 .NET 语言中,此信息以 ClaimsPrincipal 的形式提供。In .NET languages, this information is available as a ClaimsPrincipal. ClaimsPrincipal 作为请求上下文的一部分提供,如以下示例中所示:The ClaimsPrincipal is available as part of the request context as shown in the following example:

using System.Net;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

public static IActionResult Run(HttpRequest req, ILogger log)
{
    ClaimsPrincipal identities = req.HttpContext.User;
    // ...
    return new OkObjectResult();
}

或者,可直接将 ClaimsPrincipal 作为其他参数包含在函数签名中:Alternatively, the ClaimsPrincipal can simply be included as an additional parameter in the function signature:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Newtonsoft.Json.Linq;

public static void Run(JObject input, ClaimsPrincipal principal, ILogger log)
{
    // ...
    return;
}

授权密钥Authorization keys

Functions 允许使用密钥使其难以在开发过程中访问 HTTP 函数终结点。Functions lets you use keys to make it harder to access your HTTP function endpoints during development. 标准 HTTP 触发器可能会要求在请求中出现此类 API 密钥。A standard HTTP trigger may require such an API key be present in the request.

重要

虽然密钥可以帮助你在开发过程中对 HTTP 终结点进行模糊处理,它们不应作为一种方法来保护生产环境中的 HTTP 触发器。While keys may help obfuscate your HTTP endpoints during development, they are not intended as a way to secure an HTTP trigger in production. 若要了解详细信息,请参阅在生产环境中保护 HTTP 终结点To learn more, see Secure an HTTP endpoint in production.

备注

在 Functions 1.x 运行时中,Webhook 提供程序可以使用密钥以多种方式对请求授权,具体取决于提供程序支持何种方式。In the Functions 1.x runtime, webhook providers may use keys to authorize requests in a variety of ways, depending on what the provider supports. Webhook 和密钥对此进行了说明。This is covered in Webhooks and keys. 2.x 版运行时不包括对 Webhook 提供程序的内置支持。The version 2.x runtime does not include built-in support for webhook providers.

有两种类型的密钥:There are two types of keys:

  • 主机密钥:由 Function App 中的所有函数共享这些密钥。Host keys: These keys are shared by all functions within the function app. 这些密钥用作 API 密钥时,可以访问 Function App 中的任何函数。When used as an API key, these allow access to any function within the function app.
  • 函数密钥:这些密钥仅适用于在其下定义它们的特定函数。Function keys: These keys apply only to the specific functions under which they are defined. 这些密钥用作 API 密钥时,只允许访问该函数。When used as an API key, these only allow access to that function.

命名每个密钥方便引用,并且在函数和主机级别存在名为“default”的默认密钥。Each key is named for reference, and there is a default key (named "default") at the function and host level. 函数密钥优先于主机密钥。Function keys take precedence over host keys. 如果为两个密钥定义的名称相同,则使用函数密钥。When two keys are defined with the same name, the function key is always used.

每个函数应用也有一个特殊的主密钥 。Each function app also has a special master key. 此密钥是名为 _master 的主机密钥,提供对运行时 API 的管理访问权限。This key is a host key named _master, which provides administrative access to the runtime APIs. 无法撤消此密钥。This key cannot be revoked. 当设置 admin 授权级别,请求必须使用主密钥;任何其他密钥会导致授权失败。When you set an authorization level of admin, requests must use the master key; any other key results in authorization failure.

注意

由于函数应用中提升的权限由主密钥所授予,因此不应与第三方共享此密钥或在本机客户端应用程序中分发此密钥。Due to the elevated permissions in your function app granted by the master key, you should not share this key with third parties or distribute it in native client applications. 选择管理员授权级别时,请务必审慎行事。Use caution when choosing the admin authorization level.

获取密钥Obtaining keys

密钥作为 Function App 的一部分存储在 Azure 中,并进行了静态加密。Keys are stored as part of your function app in Azure and are encrypted at rest. 若要查看密钥,请创建新的密钥或将密钥滚动到新值,导航到 Azure 门户中的某个 HTTP 触发函数并选择“管理” 。To view your keys, create new ones, or roll keys to new values, navigate to one of your HTTP-triggered functions in the Azure portal and select Manage.

在门户中管理函数密钥。

没有任何受支持的 API 可用于以编程方式获取函数密钥。There is no supported API for programmatically obtaining function keys.

API 密钥的授权API key authorization

大多数 HTTP 触发器模板都需要在请求中获取 API 密钥。Most HTTP trigger templates require an API key in the request. 因此 HTTP 请求通常如以下 URL 所示:So your HTTP request normally looks like the following URL:

https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?code=<API_KEY>

该密钥可以包含在名为 code 的查询字符串变量中(如上所示)。The key can be included in a query string variable named code, as above. 也可以包含在 x-functions-key HTTP 头中。It can also be included in an x-functions-key HTTP header. 密钥的值可以为任意为函数定义的函数密钥,也可以为任意主机密钥。The value of the key can be any function key defined for the function, or any host key.

可以允许匿名请求,它不需要密钥。You can allow anonymous requests, which do not require keys. 可能还需要使用主密钥。You can also require that the master key be used. 可使用绑定 JSON 中的 authLevel 属性更改默认授权级别。You change the default authorization level by using the authLevel property in the binding JSON. 有关详细信息,请参阅触发器 - 配置For more information, see Trigger - configuration.

备注

本地运行函数时,将禁用授权,而不考虑指定的身份验证级别设置。When running functions locally, authorization is disabled regardless of the specified authentication level setting. 发布到 Azure 后,将强制执行触发器中的 authLevel 设置。After publishing to Azure, the authLevel setting in your trigger is enforced.

在生产环境中保护 HTTP 终结点Secure an HTTP endpoint in production

若要全面保护生产环境中的函数终结点,应考虑实现以下函数应用级别的安全选项之一:To fully secure your function endpoints in production, you should consider implementing one of the following function app-level security options:

  • 打开函数应用的“应用服务身份验证/授权”。Turn on App Service Authentication / Authorization for your function app. 应用服务平台允许使用 Azure Active Directory (AAD) 和多个第三方标识提供者对客户端进行身份验证。The App Service platform lets use Azure Active Directory (AAD) and several third-party identity providers to authenticate clients. 可以使用此函数来实现函数的自定义授权规则,并且可以从函数代码处理用户信息。You can use this to implement custom authorization rules for your functions, and you can work with user information from your function code. 若要了解详细信息,请参阅 Azure 应用服务中的身份验证和授权以及使用客户端标识To learn more, see Authentication and authorization in Azure App Service and Working with client identities.

  • 使用 Azure API 管理 (APIM) 对请求进行身份验证。Use Azure API Management (APIM) to authenticate requests. APIM 为传入请求提供了各种 API 安全选项。APIM provides a variety of API security options for incoming requests. 若要了解详细信息,请参阅 API 管理身份验证策略To learn more, see API Management authentication policies. 有了 APIM,可以配置函数应用以接受仅来自 APIM 实例 IP 地址的请求。With APIM in place, you can configure your function app to accept requests only from the IP address of your APIM instance. 若要了解详细信息,请参阅 IP 地址限制To learn more, see IP address restrictions.

  • 将函数应用部署到 Azure 应用服务环境 (ASE)。Deploy your function app to an Azure App Service Environment (ASE). ASE 提供要在其中运行函数的专用托管环境。ASE provides a dedicated hosting environment in which to run your functions. ASE 允许配置单个前端网关,可以使用它对所有传入请求进行身份验证。ASE lets you configure a single front-end gateway that you can use to authenticate all incoming requests. 有关详细信息,请参阅为应用服务环境配置 Web 应用程序防火墙 (WAF)For more information, see Configuring a Web Application Firewall (WAF) for App Service Environment.

在使用这些函数应用级别的安全方法之一时,应将 HTTP 触发函数身份验证级别设置为 anonymousWhen using one of these function app-level security methods, you should set the HTTP-triggered function authentication level to anonymous.

WebhookWebhooks

备注

Webhook 模式仅适用于 1.x 版 Functions 运行时。Webhook mode is only available for version 1.x of the Functions runtime. 进行此更改是为了提高 2.x 版中 HTTP 触发器的性能。This change was made to improve the performance of HTTP triggers in version 2.x.

在 1.x 版中,Webhook 模板为 Webhook 有效负载提供了额外的验证。In version 1.x, webhook templates provide additional validation for webhook payloads. 在 2.x 版中,基本 HTTP 触发器仍正常工作,且是针对 Webhook 的推荐方法。In version 2.x, the base HTTP trigger still works and is the recommended approach for webhooks.

GitHub WebhookGitHub webhooks

要响应 GitHub webhook,首先请创建包含 HTTP 触发器的函数,并将 webHookType 属性设置为 githubTo respond to GitHub webhooks, first create your function with an HTTP Trigger, and set the webHookType property to github. 然后将其 URL 和 API 密钥复制到 GitHub 存储库的“添加 Webhook”页。 Then copy its URL and API key into the Add webhook page of your GitHub repository.

Slack WebhookSlack webhooks

Slack webhook 为用户生成令牌,而非让用户指定它,所以必须使用 Slack 中的令牌配置特定于函数的密钥。The Slack webhook generates a token for you instead of letting you specify it, so you must configure a function-specific key with the token from Slack. 请参阅授权密钥See Authorization keys.

Webhook 和密钥Webhooks and keys

Webhook 授权由属于 HTTP 触发器的 webhook 接收器组件处理,其机制因 webhook 类型而异。Webhook authorization is handled by the webhook receiver component, part of the HTTP trigger, and the mechanism varies based on the webhook type. 每种机制都依赖于一个密钥。Each mechanism does rely on a key. 默认情况下,使用名为“default”的函数密钥。By default, the function key named "default" is used. 要使用其他密钥,请将 webhook 提供程序配置为使用以下方式之一的请求发送密钥名称:To use a different key, configure the webhook provider to send the key name with the request in one of the following ways:

  • 查询字符串:提供程序通过 clientid 查询字符串参数(例如,https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?clientid=<KEY_NAME>)传递密钥名称。Query string: The provider passes the key name in the clientid query string parameter, such as https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?clientid=<KEY_NAME>.
  • 请求标头:提供程序通过 x-functions-clientid 标头传递密钥名称。Request header: The provider passes the key name in the x-functions-clientid header.

触发器 - 限制Trigger - limits

HTTP 请求长度限制为 100 MB(104,857,600 字节),并且 URL 长度限制为 4 KB(4,096 字节)。The HTTP request length is limited to 100 MB (104,857,600 bytes), and the URL length is limited to 4 KB (4,096 bytes). 这些限制由运行时的 Web.config 文件httpRuntime 元素指定。These limits are specified by the httpRuntime element of the runtime's Web.config file.

如果使用 HTTP 触发器的函数未在大约 2.5 分钟内完成,网关将超时并返回 HTTP 502 错误。If a function that uses the HTTP trigger doesn't complete within about 2.5 minutes, the gateway will time out and return an HTTP 502 error. 该函数将继续运行,但将无法返回 HTTP 响应。The function will continue running but will be unable to return an HTTP response. 对于长时间运行的函数,我们建议你遵循异步模式,并返回可以 ping 通请求状态的位置。For long-running functions, we recommend that you follow async patterns and return a location where you can ping the status of the request. 有关函数可以运行多长时间的信息,请参阅缩放和托管 - 消耗计划For information about how long a function can run, see Scale and hosting - Consumption plan.

触发器 - host.json 属性Trigger - host.json properties

host.json 文件包含控制 HTTP 触发器行为的设置。The host.json file contains settings that control HTTP trigger behavior.

{
    "http": {
        "routePrefix": "api",
        "maxOutstandingRequests": 200,
        "maxConcurrentRequests": 100,
        "dynamicThrottlesEnabled": true
    }
}
属性Property 默认Default 描述Description
routePrefixroutePrefix apiapi 应用到所有路由的路由前缀。The route prefix that applies to all routes. 使用空字符串可删除默认前缀。Use an empty string to remove the default prefix.
maxOutstandingRequestsmaxOutstandingRequests 200*200* 在任意给定时间搁置的未完成请求数上限。The maximum number of outstanding requests that are held at any given time. 此限制包括已排队但尚未开始执行的请求,以及正在执行的所有请求。This limit includes requests that are queued but have not started executing, as well as any in progress executions. 超出此限制的任何传入请求将被拒绝,并返回 429“太忙”响应。Any incoming requests over this limit are rejected with a 429 "Too Busy" response. 允许调用方使用基于时间的重试策略,还可帮助控制最大请求延迟。That allows callers to employ time-based retry strategies, and also helps you to control maximum request latencies. 此设置仅控制脚本宿主执行路径中发生的排队。This only controls queuing that occurs within the script host execution path. 其他队列(例如 ASP.NET 请求队列)仍有效,不受此设置的影响。Other queues such as the ASP.NET request queue will still be in effect and unaffected by this setting. *版本 1.x 的默认值是无限制的 (-1)。*The default for version 1.x is unbounded (-1). 消耗计划中版本 2.x 的默认值为 200。The default for version 2.x in a consumption plan is 200. 专用计划中版本 2.x 的默认值是无限制的 (-1)。The default for version 2.x in a dedicated plan is unbounded (-1).
maxConcurrentRequestsmaxConcurrentRequests 100*100* 要并行执行的 http 函数数目上限。The maximum number of http functions that will be executed in parallel. 这样,可以控制并发性,从而帮助管理资源利用率。This allows you to control concurrency, which can help manage resource utilization. 例如,某个 http 函数可能使用了大量系统资源(内存/CPU/插槽),从而在并发性过高时导致问题。For example, you might have an http function that uses a lot of system resources (memory/cpu/sockets) such that it causes issues when concurrency is too high. 或者,某个函数向第三方服务发出出站请求,则可能需要限制这些调用的速率。Or you might have a function that makes outbound requests to a third party service, and those calls need to be rate limited. 在这种情况下,应用限制可能有帮助。In these cases, applying a throttle here can help. *版本 1.x 的默认值是无限制的 (-1)。*The default for version 1.x is unbounded (-1). 消耗计划中版本 2.x 的默认值为 100。The default for version 2.x in a consumption plan is 100. 专用计划中版本 2.x 的默认值是无限制的 (-1)。The default for version 2.x in a dedicated plan is unbounded (-1).
dynamicThrottlesEnableddynamicThrottlesEnabled true*true* 启用时,将为此设置将导致请求处理管道,以定期检查系统性能计数器类似连接/线程/进程/内存/CPU 等,并通过内置的高阈值 (80%),如果有任何这些计数器请求拒绝与 429“太忙”响应,直至恢复到正常水平的计数器。When enabled, this setting causes the request processing pipeline to periodically check system performance counters like connections/threads/processes/memory/cpu/etc. and if any of those counters are over a built-in high threshold (80%), requests will be rejected with a 429 "Too Busy" response until the counter(s) return to normal levels. *版本 1.x 的默认值是 false。*The default for version 1.x is false. 消耗计划中版本 2.x 的默认值为 true。The default for version 2.x in a consumption plan is true. 专用计划中版本 2.x 的默认值为 false。The default for version 2.x in a dedicated plan is false.

输出Output

通过 HTTP 输出绑定响应 HTTP 请求发送者。Use the HTTP output binding to respond to the HTTP request sender. 此绑定需要使用 HTTP 触发器,利用此绑定,可以自定义与触发器请求相关联的响应。This binding requires an HTTP trigger and allows you to customize the response associated with the trigger's request. 如果未提供 HTTP 输出绑定,在 Functions 1.x 中,HTTP 触发器返回“HTTP 200 正常”和空的正文;在 Functions 2.x 中返回“HTTP 204 无内容”和空的正文。If an HTTP output binding is not provided, an HTTP trigger returns HTTP 200 OK with an empty body in Functions 1.x, or HTTP 204 No Content with an empty body in Functions 2.x.

输出 - 配置Output - configuration

下表解释了在 function.json 文件中设置的绑定配置属性。The following table explains the binding configuration properties that you set in the function.json file. 在 C# 类库中,没有与这些 function.json 属性对应的属性。For C# class libraries, there are no attribute properties that correspond to these function.json properties.

属性Property 说明Description
typetype 必须设置为 httpMust be set to http.
directiondirection 必须设置为 outMust be set to out.
name name 在响应的函数代码中使用的变量名称,或者 $return 以使用返回值。The variable name used in function code for the response, or $return to use the return value.

输出 - 用法Output - usage

若要发送 HTTP 响应,请使用语言标准响应模式。To send an HTTP response, use the language-standard response patterns. 在 C# 或 C# 脚本中,使函数返回类型为 IActionResultTask<IActionResult>In C# or C# script, make the function return type IActionResult or Task<IActionResult>. 在 C# 中,不需要返回值属性。In C#, a return value attribute isn't required.

有关示例响应,请参阅触发器示例For example responses, see the trigger example.

后续步骤Next steps

详细了解 Azure Functions 触发器和绑定Learn more about Azure functions triggers and bindings