使用旧版代理

重要

Azure Functions 代理是 Azure Functions 运行时 1.x 到 3.x 版的旧功能。 版本 4.x 中对代理支持的支持将回归,这样你可以成功将函数应用升级到最新的运行时版本。 你应该尽快将你的函数应用与 Azure API 管理集成。 API 管理使你能够利用一组更完整的功能来定义、保护、管理基于 Functions 的 API 并从中获利。 有关详细信息,请参阅 API 管理集成。 有关版本 4.x 中代理待重返的信息,请监视应用服务公告页

为了帮助更轻松地从现有代理实现迁移,本文提供了指向等效的 API 管理内容(如果可用)的链接。

本文介绍了如何配置和使用 Azure Functions 代理。 使用此功能可在 Function App 上指定由其他资源实现的终结点。 可以使用这些代理将大型 API 拆分到多个 Function App 中(与在微服务体系结构中一样),同时对客户端仍然呈现为单个 API 接口。

标准版 Functions 针对代理执行收费。 有关详细信息,请参阅 Azure Functions 定价

在 Functions v4.x 中重新启用代理

将函数应用迁移到 Functions 运行时版本 4.x 后,需要专门重新启用代理。 仍应尽快切换到将函数应用与 Azure API 管理集成的方式,而不是仅仅依赖于代理。

重新启用代理需要通过以下方式之一在 AzureWebJobsFeatureFlags 应用程序设置中设置标志:

  • 如果 AzureWebJobsFeatureFlags 设置尚不存在,请将该设置添加到值为 EnableProxies 的函数应用。

  • 如果该设置已存在,请将 ,EnableProxies 添加到现有值的末尾。

AzureWebJobsFeatureFlags 是用于启用预览和其他临时功能的标志的逗号分隔数组。 若要详细了解如何创建和修改应用程序设置,请参阅使用应用程序设置

注意

即使使用 EnableProxies 标志重新启用,也无法在 Azure 门户中使用代理。 相反,你必须直接为函数应用使用 proxies.json 文件。 有关详细信息,请参阅高级配置

创建代理

重要

有关使用 API 管理的等效内容,请参阅使用 Azure API 管理从 HTTP 终结点公开无服务器 API

代理在函数应用根目录的 proxies.json 文件中进行定义。 本部分中的步骤向你展示如何使用 Azure 门户在函数应用中创建此文件。 并非所有语言和操作系统组合都支持门户中编辑。 如果无法在门户中修改函数应用文件,则可以改为从本地项目文件夹的根目录创建和部署等效的 proxies.json 文件。 若要详细了解门户编辑支持,请参阅语言支持详细信息

  1. 打开 Azure 门户,并转到 Function App。
  2. 在左侧窗格中,选择“代理”,然后选择“+ 添加”。
  3. 为代理提供一个名称。
  4. 通过指定路由模板HTTP 方法配置在此 Function App 上公开的终结点。 这些参数的行为取决于 HTTP 触发器的规则。
  5. 将“后端 URL”设置为另一个终结点。 此终结点可以是其他 Function App 中的函数,也可以是任何其他 API。 该值不需要是静态值,并且可以引用应用程序设置原始客户端请求中的参数
  6. 选择“创建”

代理现在已作为新终结点存在于 Function App 上。 从客户端的角度来看,它与 Functions 中的 HttpTrigger 相同。 可以通过复制代理 URL 并使用最喜欢的 HTTP 客户端对其进行测试来试验新代理。

修改请求和响应

重要

使用 API 管理,可以使用策略通过配置来更改 API 行为。 策略是针对 API 请求或响应按顺序运行的一系列语句。 有关 API 管理策略的详细信息,请参阅 Azure API 管理中的策略

使用代理,可以修改针对后端发出的请求以及从后端返回的响应。 这些转换可以使用使用变量中定义的变量。

修改后端请求

默认情况下,后端请求初始化为原始请求的副本。 除了设置后端 URL 以外,还可以对 HTTP 方法、标头和查询字符串参数进行更改。 修改的值可以引用应用程序设置原始客户端请求中的参数

可在门户中通过展开代理详细信息页的“请求替代”部分修改后端请求。

修改响应

默认情况下,客户端响应初始化为后端响应的副本。 可对响应的状态代码、原因短语、标头和正文进行更改。 修改的值可以引用应用程序设置原始客户端请求中的参数后端响应中的参数

可在门户中通过展开代理详细信息页的“响应替代”部分修改后端响应。

使用变量

代理的配置不需要是静态的。 可将它调整为使用原始客户端请求、后端响应或应用程序设置中的变量。

引用本地函数

可以使用 localhost 直接引用同一函数应用内的函数,而无需往返代理请求。

"backendUri": "https://localhost/api/httptriggerC#1" 将引用路由 /api/httptriggerC#1 中的本地 HTTP 触发函数

注意

如果函数使用“函数”、“管理员”或“sys” 授权级别,将需要根据原始函数 URL 提供代码和 clientId。 在这种情况下,引用将如下所示:"backendUri": "https://localhost/api/httptriggerC#1?code=<keyvalue>&clientId=<keyname>" 我们建议将这些密钥存储在应用程序设置中,并在代理中引用这些密钥。 这样可以避免在源代码中存储机密。

引用请求参数

可将请求参数用作后端 URL 属性的输入,或者在修改请求和响应的过程中使用请求参数。 一些参数可以从基本代理配置中指定的路由模板绑定,而其他一些参数可以来自传入请求的属性。

路由模板参数

可按名称引用路由模板中使用的参数。 需将参数名称括在大括号 ({}) 中。

例如,如果代理具有诸如 /pets/{petId} 的路由模板,则后端 URL 可以包括 {petId} 的值,就像在 https://<AnotherApp>.chinacloudsites.cn/api/pets/{petId} 中那样。 如果路由模板以通配符结尾,例如 /api/{*restOfPath},则值 {restOfPath} 将是传入请求中的其余路径段的字符串表示形式。

其他请求参数

除了路由模板参数以外,还可以在配置值中使用以下值:

  • {request.method} :对原始请求使用的 HTTP 方法。
  • {request.headers.<HeaderName>}:可从原始请求中读取的标头。 请将 <HeaderName> 替换为要读取的标头的名称。 如果该标头未包含在请求中,则该值为空字符串。
  • {request.querystring.<ParameterName>}:可从原始请求中读取的查询字符串参数。 请将 <ParameterName> 替换为要读取的参数的名称。 如果该参数未包含在请求中,则该值为空字符串。

引用后端响应参数

在修改返回给客户端的响应过程中,可以使用响应参数。 可以在配置值中使用以下值:

  • {backend.response.statusCode} :在后端响应中返回的 HTTP 状态代码。
  • {backend.response.statusReason} :在后端响应中返回的 HTTP 原因短语。
  • {backend.response.headers.<HeaderName>}:可从后端响应中读取的标头。 请将 <HeaderName> 替换为要读取的标头的名称。 如果该标头未包含在响应中,则该值为空字符串。

引用应用程序设置

还可以通过将设置名称括在百分号 (%) 之间来引用针对 Function App 定义的应用程序设置

例如,后端 URL https://%ORDER_PROCESSING_HOST%/api/orders 会将“%ORDER_PROCESSING_HOST%”替换为 ORDER_PROCESSING_HOST 设置的值。

提示

当有多个部署或测试环境时,请为后端主机使用应用程序设置。 这样可以确保始终与该环境的正确后端进行通信。

对代理进行故障排除

通过将标志 "debug":true 添加到 proxies.json 中的任何代理,将启用调试日志记录。 日志存储在 D:\home\LogFiles\Application\Proxies\DetailedTrace 中,可通过高级工具 (kudu) 访问。 任何 HTTP 响应也将包含 Proxy-Trace-Location 标头,其中包含用于访问日志文件的 URL。

可以通过添加设置为 trueProxy-Trace-Enabled 标头来从客户端调试代理。 这还会将跟踪结果记录到文件系统,并以响应中标头的形式返回跟踪 URL。

阻止代理跟踪

出于安全原因,你可能不想允许任何人调用服务生成跟踪。 没有登录凭据这些人将无法访问跟踪内容,但生成跟踪会占用资源并公开你正在使用函数代理。

通过将 "debug":false 添加到 proxies.json 中的任何特定代理可完全禁用跟踪。

高级配置

配置的代理存储在一个 proxies.json 文件中,此文件位于函数应用目录的根目录中。 使用 Functions 支持的任意部署方法时,可以手动编辑此文件并将其部署为应用的一部分。

提示

如果尚未设置一种部署方法,也可以在门户中使用 proxies.json 文件。 转到到 Function App,选择“平台功能”,并选择“应用服务编辑器”。 这样,便可以看到 Function App 的整个文件结构并进行更改。

Proxies.json 是由一个代理对象定义的,包括已命名的代理及其定义。 (可选)可以引用用于代码完成的 JSON 架构(如果编辑器支持这样做)。 示例文件可能如下例所示:

{
    "$schema": "http://json.schemastore.org/proxies",
    "proxies": {
        "proxy1": {
            "matchCondition": {
                "methods": [ "GET" ],
                "route": "/api/{test}"
            },
            "backendUri": "https://<AnotherApp>.chinacloudsites.cn/api/<FunctionName>"
        }
    }
}

每个代理都有一个友好名称,例如上例中的 proxy1。 对应的代理定义对象是由以下属性定义的:

  • matchCondition:必需 - 一个对象,用于定义触发此代理执行的请求。 它包含两个与 HTTP 触发器共享的属性:
    • methods:代理响应的 HTTP 方法的数组。 如果未指定此属性,代理将响应路由上的所有 HTTP 方法。
    • route:必需 - 定义路由模板,控制代理将响应哪些请求 URL。 与在 HTTP 触发器中不同,此处没有默认值。
  • backendUri:应当通过代理将请求发送到的后端资源的 URL。 此值可以引用应用程序设置和原始客户端请求中的参数。 如果未包括此属性,则 Azure Functions 以 HTTP 200 OK 进行响应。
  • requestOverrides:定义对后端请求执行的转换的对象。 请参阅定义 requestOverrides 对象
  • responseOverrides:定义对客户端响应执行的转换的对象。 请参阅定义 responseOverrides 对象

注意

Azure Functions 代理中的 route 属性不接受 Function App 主机配置的 routePrefix 属性。 如果希望包括一个如 /api 等前缀,必须将其包括在 route 属性中

禁用单个代理

可以通过将 "disabled": true 添加到 proxies.json 文件中的代理来禁用单个代理。 这将导致满足 matchCondition 的任何请求返回 404。

{
    "$schema": "http://json.schemastore.org/proxies",
    "proxies": {
        "Root": {
            "disabled":true,
            "matchCondition": {
                "route": "/example"
            },
            "backendUri": "https://<AnotherApp>.chinacloudsites.cn/api/<FunctionName>"
        }
    }
}

应用程序设置

代理行为可以通过多个应用程序设置进行控制。 Functions App 设置参考中概述了所有这些设置

保留字符(字符串格式设置)

代理使用“\”作为转义符从 JSON 文件中读取所有字符串。 代理还会解释大括号。 请参阅下面的完整示例集。

字符 转义字符 示例
{ 或 } {{ 或 }} {{ example }} -->{ example }
\ \\ example.com\\text.html -->example.com\text.html
" \" \"example\" -->"example"

定义 requestOverrides 对象

requestOverrides 对象定义调用后端资源时对请求所做的更改。 该对象由以下属性定义:

  • backend.request.method:用于调用后端的 HTTP 方法。
  • backend.request.querystring.<ParameterName>:可为后端调用设置的查询字符串参数。 请将 <ParameterName> 替换为要设置的参数的名称。 如果提供了空字符串,参数仍然包含在后端请求中。
  • backend.request.headers.<HeaderName>:可为后端调用设置的标头。 请将 <HeaderName> 替换为要设置的标头的名称。 如果提供了空字符串,参数仍然包含在后端请求中。

值可以引用应用程序设置和原始客户端请求中的参数。

示例配置可能如下所示:

{
    "$schema": "http://json.schemastore.org/proxies",
    "proxies": {
        "proxy1": {
            "matchCondition": {
                "methods": [ "GET" ],
                "route": "/api/{test}"
            },
            "backendUri": "https://<AnotherApp>.chinacloudsites.cn/api/<FunctionName>",
            "requestOverrides": {
                "backend.request.headers.Accept": "application/xml",
                "backend.request.headers.x-functions-key": "%ANOTHERAPP_API_KEY%"
            }
        }
    }
}

定义 responseOverrides 对象

requestOverrides 对象定义对传回客户端的响应所做的更改。 该对象由以下属性定义:

  • response.statusCode:要返回给客户端的 HTTP 状态代码。
  • response.statusReason:要返回给客户端的 HTTP 原因短语。
  • response.body:要返回给客户端的正文的字符串表示形式。
  • response.headers.<HeaderName>:可为返回给客户端的响应设置的标头。 请将 <HeaderName> 替换为要设置的标头的名称。 如果提供空字符串,该标头不会包含在响应中。

值可以引用应用程序设置、原始客户端请求中的参数和后端响应中的参数。

示例配置可能如下所示:

{
    "$schema": "http://json.schemastore.org/proxies",
    "proxies": {
        "proxy1": {
            "matchCondition": {
                "methods": [ "GET" ],
                "route": "/api/{test}"
            },
            "responseOverrides": {
                "response.body": "Hello, {test}",
                "response.headers.Content-Type": "text/plain"
            }
        }
    }
}

注意

在此示例中,响应正文是直接设置的,因此不需要 backendUri 属性。 此示例演示如何使用 Azure Functions 代理来模拟 API。