HTTP handlers let you process HTTP requests directly in Python using the Python Web Server Gateway Interface (WSGI) specification. When a request arrives, Function Compute calls the handler you specify, passing request data through environ and a response callback through start_response.
An HTTP trigger must be configured for your function before it can receive HTTP requests. See Configure an HTTP trigger that invokes a function with HTTP requests.
Handler signature
Every HTTP handler follows the WSGI signature:
def handler(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b'<h1>Hello, world!</h1>']| Parameter | Type | Description |
|---|---|---|
environ | dict | A Python dictionary containing all HTTP request data. See Request fields (environ) for the full field list. |
start_response | callable | A function provided by the FC runtime. Call it to set the response status and headers before returning the response body. |
The return value must be an iterable. return [b'<h1>Hello, world!</h1>'] returns a list with a single bytes object, which the runtime sends to the client as the HTTP response body.
For the full WSGI spec, see PEP 3333.
Migrate a Flask app to Function Compute
Because HTTP handlers follow the WSGI specification, Flask and Django applications require only a single adapter function to run in Function Compute.
The example below runs a Flask hello world app in the Python 3 runtime:
# Flask application — define routes as usual
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Web App with Python Flask!'
# FC handler — forwards every request to the Flask WSGI app
def handler(environ, start_response):
return app(environ, start_response)The example has two parts:
Flask application (lines 1–7): Standard Flask code. No changes needed.
FC handler (lines 9–11): A minimal adapter that passes
environandstart_responsedirectly to the Flask app. This single line is all that's required to run any WSGI-compatible framework in Function Compute.
Deploy the Flask app
Before you begin, create a service.
Log on to the Function Compute console. In the left-side navigation pane, click Services & Functions.
In the top navigation bar, select a region. On the Services page, click the desired service.
On the Functions page, click Create Function. Create an HTTP function with the Python 3 runtime. For details, see Create a function.
On the Function Details page, click the Code tab and paste the sample code into the editor. Then choose Terminal > New Terminal and run the following command in the TERMINAL panel to install Flask in the current directory:
pip install flask -t .Click Deploy.
Click Test Function and check the response. If
Web App with Python Flask!appears, the function is running correctly.
Request fields (environ)
environ is a Python dictionary containing all HTTP request data. The table below lists the fields most commonly used in Function Compute handlers. For the complete field list, see environ variables.
| Field | Type | Description |
|---|---|---|
REQUEST_METHOD | String | HTTP request method, such as GET or POST. |
HTTP_* | String | Client-supplied request headers. Each header key is normalized to HTTP_ + the uppercased, hyphen-to-underscore key. For example, x-Custom-key: value becomes environ['HTTP_X_CUSTOM_KEY'] = 'value'. |
CONTENT_TYPE | String | Media type of the request body. |
CONTENT_LENGTH | String | Length of the request body in bytes. |
REMOTE_ADDR | String | Client IP address. |
wsgi.input | BytesIO | Request body. |
fc.request_uri | String | Full request URL, as defined by Function Compute. |
fc.context | FCContext | Function invocation context, as defined by Function Compute. |
The following example reads common fields from environ:
HELLO_WORLD = b"Hello world!\n"
def handler(environ, start_response):
# FC-specific context and request URI
context = environ['fc.context']
request_uri = environ['fc.request_uri']
# Iterate over custom request headers (all start with HTTP_)
for k, v in environ.items():
if k.startswith("HTTP_"):
pass # process custom headers here
# Read 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)
# Read other common fields
request_method = environ['REQUEST_METHOD']
path_info = environ['PATH_INFO']
server_protocol = environ['SERVER_PROTOCOL']
try:
content_type = environ['CONTENT_TYPE']
except KeyError:
content_type = " "
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))
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return [HELLO_WORLD] # return value must be iterableResponse struct (start_response)
Call start_response to set the response status and headers before returning the response body. The FC runtime provides this callable with the following signature:
# 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):
...For the full spec, see The start_response() callable.
| Parameter | Type | Description |
|---|---|---|
status | String | HTTP response status, such as '200 OK' or '403 FORBIDDEN'. |
response_headers | List | HTTP response headers. Each header is a tuple of two strings: (header_name, header_value). |
exc_info | List | Exception information in tuple format for error responses. Not used in Function Compute. |
The response body returned by the handler must be an iterable object.
Limits
Request limits
Requests exceeding the following limits are rejected with HTTP status 400 and error InvalidArgument.
| Field | Limit |
|---|---|
headers | Total size of all keys and values ≤ 8 KB |
path | Total size of the request path and query parameters ≤ 4 KB |
body (synchronous invocation) | ≤ 32 MB |
body (asynchronous invocation) | ≤ 128 KB |
Response limits
Responses exceeding the following limits result in HTTP status 502 and error BadResponse.
| Field | Limit |
|---|---|
headers | Total size of all keys and values ≤ 8 KB |