您可以使用HTTP请求处理程序更方便地处理HTTP请求。当调用函数时,函数计算使用您提供的执行方法来处理HTTP请求。本文介绍Python HTTP请求处理程序的结构和特点。
使用说明
使用HTTP请求处理程序前,请确保为HTTP函数配置HTTP触发器。具体信息,请参见配置HTTP触发器并使用HTTP触发。
HTTP Handler签名
Python HTTP Handler的签名遵循WSGI(Python Web Server Gateway Interface)规范。
一个简单的HTTP Handler签名定义如下。
def handler(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b'<h1>Hello, world!</h1>']
HTTP Handler签名的示例解析如下:
handler
:符合WSGI标准的HTTP请求处理函数,可以传入以下两个参数。environ
:用于存放所有HTTP请求的信息。start_response
:发送HTTP响应的函数。
start_response('200 OK', [('Content-Type', 'text/html')])
:函数响应。包含两个参数:第一个参数是HTTP状态码;第二个参数是一组Python list对象组成的HTTP Headers,每个Header是一个Python tuple对象,包含两个Python str。return [b'<h1>Hello, world!</h1>']
:返回信息。此返回值将作为HTTP响应的Body返回给客户端。
示例:实现Flask应用
示例代码
当实现了符合WSGI协议的HTTP Handler后,基于Flask和Django等流行的Web框架的应用能够非常快速地移植到函数计算上。如下代码展示如何在函数计算的Python Runtime中运行Flask框架的hello world
应用。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Web App with Python Flask!'
def handler(environ, start_response):
return app(environ, start_response)
代码示例解释如下:
第一部分:Flask应用的代码。从
from flask import Flask
开始,至return 'Web App with Python Flask!'
结束。第二部分:
handler
函数。只需要将handler
函数实现为return app(environ, start_response)
,即可将Flask或Django等Web框架应用运行在函数计算的Python Runtime中。
前提条件
操作步骤
请求结构体(environ)
用于存放HTTP请求的信息。其结构为Python字典结构。常见字段如下,更多关于请求结构体的说明,请参见environ说明。
参数 | 类型 | 解释说明 |
REQUEST_METHOD | String | HTTP请求方法,例如GET、POST等。 |
HTTP_Variables | String | HTTP请求头。 |
CONTENT_TYPE | String | HTTP请求体(Body)类型。 |
CONTENT_LENGTH | String | HTTP请求体(Body)长度。 |
REMOTE_ADDR | String | 客户端IP地址。 |
wsgi.input | BytesIO | HTTP请求体(Body)。 |
fc.request_uri | String | 客户端请求的URL,由函数计算定义。 |
fc.context | FCContext | 上下文,由函数计算定义。 |
请求结构体(environ)中的参数HTTP_Variables是按照WSGI规范对请求头中的key
做了处理的HTTP请求头,处理方式为key="HTTP_"+k.upper().replace("-","_")
。例如,某个请求头是'x-Custom-key':'value',在请求结构体(environ)中会表现为environ['HTTP_X_CUSTOM_KEY']='value'
。
获取HTTP Handler请求结构体的示例代码如下。
# Method 1: User provide the function. FC call the function to process request and send back response.
HELLO_WORLD = b"Hello world!\n"
def handler(environ, start_response):
context = environ['fc.context']
request_uri = environ['fc.request_uri']
for k, v in environ.items():
if k.startswith("HTTP_"):
# process custom request headers
pass
# get request_body
try:
request_body_size = int(environ.get('CONTENT_LENGTH', 0))
except (ValueError):
request_body_size = 0
request_body = environ['wsgi.input'].read(request_body_size)
# get request_method
request_method = environ['REQUEST_METHOD']
# get path info
path_info = environ['PATH_INFO']
# get server_protocol
server_protocol = environ['SERVER_PROTOCOL']
# get content_type
try:
content_type = environ['CONTENT_TYPE']
except (KeyError):
content_type = " "
# get query_string
try:
query_string = environ['QUERY_STRING']
except (KeyError):
query_string = " "
print ('request_body: {}'.format(request_body))
print ('method: {}\n path: {}\n query_string: {}\n server_protocol: {}\n'.format(request_method, path_info, query_string, server_protocol))
# do something here
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
# return value must be iterable
return [HELLO_WORLD]
响应结构体
HTTP Handler响应结构体包含响应状态、响应头和响应体。您需要先调用start_response()
,将响应状态status
和响应头headers
的内容返回给服务端,才能返回响应体。响应体要求为可迭代对象。
start_response
是一个可调用结构(Callable),结构示例如下。关于start_response
的更多信息,请参见the-start-response-callable。
# Provided by FC runtime.
# status: a string like '200 OK' or '403 FORBIDDEN'
# return: must be a write(body_data) callable
def start_response(status, response_headers, exc_info=None):
...
参数说明如下。
参数 | 类型 | 解释说明 |
status | String | HTTP响应状态码。 |
response_headers | List | HTTP响应头。 |
exc_info | List | 用于将当前的异常信息以元组的形式返回。函数计算目前未使用。 |
限制说明
请求限制
如果超过以下限制,会返回400状态码和InvalidArgument错误码。
字段
限制说明
HTTP状态码
错误码
headers
请求头中的所有键和值的总大小不能超过8 KB。
400
InvalidArgument
path
请求路径以及所有查询参数的总大小不能超过4 KB。
body
同步调用请求的Body的总大小不能超过32 MB,异步调用请求的Body的总大小不能超过128 KB。
响应限制
如果超过以下限制,会返回502状态码和BadResponse错误码。
字段
限制说明
HTTP状态码
错误码
headers
响应头中的所有键和值对的大小不能超过8 KB。
502
BadResponse