发出 HTTP(S) 请求

地区 ID

REGION_ID 是 Google 根据您在创建应用时选择的区域分配的缩写代码。此代码不对应于国家/地区或省,尽管某些区域 ID 可能类似于常用国家/地区代码和省代码。对于 2020 年 2 月以后创建的应用,REGION_ID.r 包含在 App Engine 网址中。对于在此日期之前创建的现有应用,网址中的区域 ID 是可选的。

详细了解区域 ID

本页介绍如何从 App Engine 应用发出 HTTP(S) 请求。

默认情况下,App Engine 使用 URL Fetch 服务来发出出站 HTTP(S) 请求。

如需详细了解请求大小限制以及 URL Fetch 请求中发送的标头,请参阅出站请求

如果您已设置无服务器 VPC 访问通道或使用 Sockets API,则需要阻止 URL Fetch 处理请求。URL Fetch 会导致发送到您的 VPC 网络或 Sockets API 的请求失败。停用 URL Fetch 后,标准 Python 库将处理 HTTP 请求。如果您需要 URL Fetch 为特定请求提供的功能,则可以直接将 urlfetch 库用于这些特定请求。

发出 HTTP 请求

如需发出出站 HTTP 请求,请使用 urlfetch.fetch 方法。为了提高代码的可移植性,您还可以使用 Python 标准库 urlliburllib2httplib 发出 HTTP 请求。在 App Engine 中使用这些库时,它们使用 App Engine 的 URL Fetch 服务执行 HTTP 请求。您还可以使用第三方 requests 库,只要将其配置为使用URLFetch 即可。

urlfetch

以下代码段演示了如何使用 urlfetch 执行基本 HTTP GET 请求。首先,从 App Engine SDK 中导入 urlfetch 库:

from google.appengine.api import urlfetch

接下来,使用 urlfetch 执行 GET 请求:

url = 'http://www.google.com/humans.txt'
try:
    result = urlfetch.fetch(url)
    if result.status_code == 200:
        self.response.write(result.content)
    else:
        self.response.status_code = result.status_code
except urlfetch.Error:
    logging.exception('Caught exception fetching url')

以下代码段演示了如何执行更高级的请求,使用 urlfetch 通过 HTTP POST 请求从网络表单提交数据:

try:
    form_data = urllib.urlencode(UrlPostHandler.form_fields)
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    result = urlfetch.fetch(
        url='http://localhost:8080/submit_form',
        payload=form_data,
        method=urlfetch.POST,
        headers=headers)
    self.response.write(result.content)
except urlfetch.Error:
    logging.exception('Caught exception fetching url')

urllib2

以下代码段演示了如何使用 urllib2 执行基本 HTTP GET 请求。首先,导入 urllib2 库:

import urllib2

接下来,使用 urllib2 执行 GET 请求:

url = 'http://www.google.com/humans.txt'
try:
    result = urllib2.urlopen(url)
    self.response.write(result.read())
except urllib2.URLError:
    logging.exception('Caught exception fetching url')

requests

如需使用请求,您需要按照 vendoring 说明安装 requestsrequests-toolbelt

安装后,使用 requests_toolbelt.adapters.appengine 模块将请求配置为使用 URLFetch:

import requests
import requests_toolbelt.adapters.appengine

# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt.adapters.appengine.monkeypatch()

配置完成后,您可以正常使用请求:

url = 'http://www.google.com/humans.txt'
response = requests.get(url)
response.raise_for_status()
return response.text

如需详细了解请求对 Google App Engine 的支持,请参阅 urllib3.contrib.appenginerequests_toolbelt.appengine 相关文档

设置请求超时

您可以使用 urlfetch.set_default_fetch_deadline() 函数调整默认的截止时间。该函数将新的默认截止时间存储在线程局部变量中,因此需针对每个请求对其进行设置,例如在自定义中间件中。

发出 HTTPS 请求

如需发出 HTTPS 请求,请在调用 urlfetch.fetch() 方法时将 validate_certificate 参数设置为 true

发出异步请求

默认情况下,HTTP(S) 请求为同步请求。要发出异步请求,您的应用必须完成以下步骤:

  1. 使用 urlfetch.create_rpc() 创建新的 RPC 对象。在后续方法调用中,该对象表示异步调用。
  2. 调用 urlfetch.make_fetch_call() 发出请求。此方法将 RPC 对象和请求目标的网址作为参数。
  3. 调用 RPC 对象的 get_result() 方法。如果请求成功,该方法将返回结果对象;如果请求期间发生错误,则会引发异常。

以下代码段演示了如何从 Python 应用发出基本异步请求。首先,从 App Engine SDK 中导入 urlfetch 库:

from google.appengine.api import urlfetch

接下来,使用 urlfetch 发出异步请求:

rpc = urlfetch.create_rpc()
urlfetch.make_fetch_call(rpc, 'http://www.google.com/')

# ... do other things ...
try:
    result = rpc.get_result()
    if result.status_code == 200:
        text = result.content
        self.response.write(text)
    else:
        self.response.status_int = result.status_code
        self.response.write('URL returned status code {}'.format(
            result.status_code))
except urlfetch.DownloadError:
    self.response.status_int = 500
    self.response.write('Error fetching URL')

设置请求超时

如需为请求设置超时,请在创建 RPC 对象时设置 urlfetch.create_rpc() 方法的 deadline 参数。

使用回调函数

您可以为 RPC 对象定义回调函数。当您的应用对对象调用方法(例如 wait()checksuccess()get_result())时,系统会调用该函数,从而使对象等待请求完成。

如需使用回调函数处理提取调用的结果,请执行以下步骤:

  1. 创建用于定义回调范围的辅助函数。
  2. 创建用于处理提取调用结果的处理程序函数。
  3. 将 RPC 对象的 callback 特性设置为辅助函数。

以下代码段演示了如何调用回调函数:

def handle_result(rpc):
    result = rpc.get_result()
    self.response.write(result.content)
    logging.info('Handling RPC in callback: result {}'.format(result))

urls = ['http://www.google.com',
        'http://www.github.com',
        'http://www.travis-ci.org']
rpcs = []
for url in urls:
    rpc = urlfetch.create_rpc()
    rpc.callback = functools.partial(handle_result, rpc)
    urlfetch.make_fetch_call(rpc, url)
    rpcs.append(rpc)

# ... do other things ...

# Finish all RPCs, and let callbacks process the results.

for rpc in rpcs:
    rpc.wait()

logging.info('Done waiting for RPCs')

向其他 App Engine 应用发出请求

向其他 App Engine 应用发出请求时,您的 App Engine 应用必须通过将标头 X-Appengine-Inbound-Appid 添加到请求中来声明其身份。如果您指示 URL Fetch 服务不遵循重定向,则 App Engine 会自动将此标头添加到请求中。

如需指示 URL Fetch 服务不遵循重定向,请将 fetch 方法的 follow_redirects 参数设置为 False

后续步骤

参阅出站请求了解 URL Fetch 服务,例如在 URL Fetch 请求中发送的标头。