Como emitir solicitações HTTP(S)

Esta página descreve como emitir solicitações HTTP(S) do seu aplicativo App Engine.

O App Engine usa o serviço de busca de URL para emitir solicitações HTTP(S) de saída. Para mais detalhes sobre os limites de tamanho de solicitação e quais cabeçalhos são enviados em uma solicitação de busca de URL, consulte Solicitações de saída.

Como emitir solicitações HTTP

Para emitir uma solicitação HTTP de saída, use o método urlfetch.fetch. Para melhorar a portabilidade de código, use também as bibliotecas padrão urllib, urllib2, ou httplib para emitir solicitações HTTP. Quando você usa essas bibliotecas no App Engine, elas executam solicitações HTTP usando o serviço de busca de URL do App Engine. Você também pode usar a biblioteca requests de terceiros, desde que a configure para usar a URLFetch.

urlfetch

Os snippets a seguir demonstram como executar uma solicitação HTTP GET básica usando urlfetch. Primeiro, importe a biblioteca urlfetch do SDK do App Engine:

from google.appengine.api import urlfetch

Em seguida, use urlfetch para executar a solicitação 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')

O snippet a seguir demonstra como executar uma solicitação mais avançada, enviando dados de um formulário da Web por meio de uma solicitação HTTP POST usando urlfetch:

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

Os snippets a seguir demonstram como executar uma solicitação HTTP GET básica usando o urllib2. Primeiro, importe a biblioteca urllib2:

import urllib2

Em seguida, use urllib2 para executar a solicitação 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')

solicitações

Para usar as solicitações, será preciso instalar requests e requests-toolbelt (links em inglês) usando as instruções de disponibilização de pacotes de terceiros.

Após a instalação, use o módulo requests_toolbelt.adapters.appengine para configurar solicitações para usar 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()

Depois de configurado, use as solicitações normalmente:

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

Para mais informações sobre suporte de solicitações do Google App Engine, consulte a documentação sobre urllib3.contrib.appengine e requests_toolbelt.appengine (ambos em inglês).

Como definir um tempo limite de solicitação

É possível ajustar o prazo padrão usando a função urlfetch.set_default_fetch_deadline(). Essa função armazena o novo prazo padrão em uma variável de encadeamento local. Portanto, ela precisa ser configurada para cada solicitação, por exemplo, em um middleware personalizado.

Como emitir solicitações HTTPS

Para emitir uma solicitação HTTPS, configure o parâmetro validate_certificate como true ao chamar o método urlfetch.fetch().

Como emitir uma solicitação assíncrona

As solicitações HTTP(S) são síncronas por padrão. Para emitir uma solicitação assíncrona, o aplicativo precisa:

  1. criar um novo objeto RPC usando urlfetch.create_rpc(). Esse objeto representa sua chamada assíncrona em chamadas de método subsequentes;
  2. chamar urlfetch.make_fetch_call() para fazer a solicitação. Esse método usa como parâmetros seu objeto de RPC e o URL de destino da solicitação;
  3. chamar o método get_result() do objeto RPC. Durante a solicitação, esse método retorna o objeto de resultado em caso de êxito e cria uma exceção em caso de erro.

Os snippets a seguir demonstram como fazer uma solicitação assíncrona básica a partir de um aplicativo em Python. Primeiro, importe a biblioteca urlfetch do SDK do App Engine:

from google.appengine.api import urlfetch

Em seguida, use urlfetch para fazer a solicitação assíncrona:

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

Como definir um tempo limite de solicitação

Para configurar um tempo limite para a solicitação, configure o parâmetro deadline do método urlfetch.create_rpc() ao criar o objeto de RPC.

Como usar uma função de retorno de chamada

É possível definir uma função de retorno de chamada para seu objeto de RPC. A função será chamada quando o aplicativo chamar um método no objeto como wait(), checksuccess() ou get_result(), fazendo com que o objeto aguarde a solicitação ser concluída.

Para usar uma função de retorno de chamada ao lidar com o resultado da chamada de busca:

  1. Crie uma função auxiliar para definir o escopo de callback.
  2. Crie uma função de gerenciador para lidar com o resultado da chamada de busca.
  3. Configure o atributo callback do objeto de RPC para a função auxiliar.

O snippet a seguir demonstra como invocar uma função de retorno de chamada:

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

Como emitir solicitações para outro aplicativo do App Engine

Durante a emissão de uma solicitação para outro aplicativo do App Engine, o app precisa declarar a identidade dele adicionando o cabeçalho X-Appengine-Inbound-Appid à solicitação. Se você instruir o serviço de busca de URL para não seguir redirecionamentos, o App Engine adicionará esse cabeçalho às solicitações automaticamente.

Para instruir o serviço de busca de URL a não seguir redirecionamentos, defina o parâmetro fetch do método follow_redirects como False.

Próximas etapas

Para saber mais sobre o serviço de busca de URL, como os cabeçalhos que são enviados em uma solicitação de busca de URL, consulte Solicitações de saída (em inglês).