HTTP(S) リクエストの発行

リージョン ID

REGION_ID は、アプリの作成時に選択したリージョンに基づいて Google が割り当てる省略形のコードです。一部のリージョン ID は、一般的に使用されている国や州のコードと類似しているように見える場合がありますが、このコードは国または州に対応するものではありません。2020 年 2 月以降に作成されたアプリの場合、REGION_ID.r は App Engine の URL に含まれています。この日付より前に作成されたアプリの場合、URL のリージョン ID は省略可能です。

詳しくは、リージョン ID をご覧ください。

このページでは、App Engine アプリから HTTP(S) リクエストを発行する方法について説明します。

デフォルトでは、App Engine は URL 取得サービスを使用してアウトバウンド HTTP(S) リクエストを発行します。

リクエスト サイズの上限と URL 取得リクエストで送信されるヘッダーの詳細については、アウトバウンド リクエストをご覧ください。

サーバーレス VPC アクセスを設定している場合、または Sockets API を使用している場合は、URL 取得でのリクエストの処理を停止する必要があります。URL 取得を使用すると、VPC ネットワークまたは Sockets API へのリクエストは失敗します。URL 取得を無効にすると、標準の Python ライブラリで HTTP リクエストが処理されます。特定のリクエストに対して URL 取得で提供される機能が必要な場合は、そのリクエストに urlfetch ライブラリを直接使用できます。

HTTP リクエストの発行

送信 HTTP リクエストを発行するには、urlfetch.fetch メソッドを使用します。コードの移植性を高めるために、Python 標準ライブラリ urlliburllib2httplib を使用して HTTP リクエストを発行することもできます。これらのライブラリを App Engine で使用すると、App Engine の URL 取得サービスを使用して HTTP リクエストが実行されます。URLFetch を使用するように構成すると、サードパーティの requests ライブラリを使用することもできます。

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')

リクエスト

リクエストを使用するには、ベンダリング手順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() 関数を使って変更できます。この関数は、スレッド ローカルの変数に新しいデフォルトの期限を保存します。たとえば、カスタム ミドルウェアでは、この変数をリクエストごとに設定する必要があります。

リダイレクトの無効化

URL 取得を使用している場合、基本の URL 取得サービスはデフォルトで最大 5 回のリダイレクトを行います。これらのリダイレクトでは、認証ヘッダーなどの機密情報がリダイレクト先に転送される可能性があります。アプリで HTTP リダイレクトが不要な場合は、リダイレクトを無効にすることをおすすめします。

リダイレクトを実行しないように URL 取得サービスに指示するには、fetch メソッドの follow_redirects パラメータを False に設定します。

HTTPS リクエストの発行

HTTPS リクエストを発行するには、urlfetch.fetch() メソッドを呼び出すときに validate_certificate パラメータを true に設定します。

非同期リクエストの発行

HTTP(S) リクエストはデフォルトで同期されます。非同期リクエストを発行するには、アプリケーションで次の処理を行う必要があります。

  1. urlfetch.create_rpc() を使用して新しい RPC オブジェクトを作成します。このオブジェクトは、後続のメソッド呼び出しでの非同期呼び出しを表します。
  2. urlfetch.make_fetch_call() を呼び出して、リクエストを送信します。このメソッドは、RPC オブジェクトとリクエストのターゲット URL をパラメータとして取得します。
  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 を追加して、その ID を表明する必要があります。URL 取得サービスにリダイレクトを実行しないよう指示する場合、App Engine はこのヘッダーをリクエストに自動的に追加します。

リダイレクトの無効化に関するガイダンスについては、リダイレクトの無効化を参照してください。

次のステップ

送信リクエスト内の URL 取得リクエストで送信されるヘッダーなど、URL 取得サービスについて学習する。