本文介紹自訂運行時中函數調用的方式、使用限制及程式碼範例。
背景資訊
自訂運行時支援託管使用者的HTTP Server,並將函數調用的請求轉換為HTTP請求發送到HTTP Server,將HTTP Server的響應轉換為函數調用的響應返回給Client。過程示意如下:
函數調用的方式有兩種,分別為:
-
HTTP調用(推薦):使用HTTP方式調用,例如使用HTTP觸發器或者自訂網域名來調用。
-
API調用:通過InvokeFunction API進行調用,例如使用SDK調用函數或者通過事件來源觸發函數。
調用方式的不同,使用者的HTTP Server的請求和響應的格式也會不同。
使用限制
HTTP Request限制
Request Headers不支援以x-fc-開頭的自訂欄位和以下自訂欄位:
connection
keep-alive
如果Request超過以下限制,會返回
400狀態代碼和InvalidArgument錯誤碼。Headers大小:Headers中的所有Key和Value的總大小不得超過8 KB。
Path大小:包括所有的Query Params,Path的總大小不得超過4 KB。
Body大小:同步調用請求的Body的總大小不得超過32 MB,非同步呼叫請求的Body的總大小不得超過128 KB。
HTTP Response限制
Response Headers不支援以x-fc-開頭的自訂欄位和以下自訂欄位:
connection
content-length
date
keep-alive
server
content-disposition:attachment
說明從安全形度考慮,使用Function Compute預設的aliyuncs.com網域名稱,服務端會在Response Headers中強制添加content-disposition: attachment欄位,此欄位會使得返回結果在瀏覽器中以附件的方式下載。如果需要解除該限制,需配置自訂網域名。
如果Response超過以下限制,會返回
502狀態代碼和BadResponse錯誤碼。Headers大小:Headers中的所有Key和Value的總大小不得超過8 KB。
其他使用說明
您可以通過綁定自訂網域名,為函數映射不同的HTTP訪問路徑。詳細資料,請參見配置自訂網域名。
HTTP調用(推薦)
對於HTTP方式的調用,Function Compute採用透傳模式,即將Client的HTTP請求透傳到使用者的HTTP Server,並且將HTTP Server的響應透傳給Client。一些系統保留的欄位將不會透傳,具體請參考使用限制。
要求標頭(HTTP Request Header)
使用HTTP觸發器或者自訂網域名調用函數時,Function Compute支援使用配置要求標頭控制請求的行為,具體如下表所示。
| 名稱 | 類型 | 是否必選 | 樣本 | 描述 |
| X-Fc-Invocation-Type | String | 否 | Sync | 調用方式,具體資訊請參見調用方式。取值說明如下: - Sync:同步調用。 - Async:非同步呼叫。 |
| X-Fc-Log-Type | String | 否 | Tail | 請求返回日誌。取值說明如下: - Tail:返回當前請求產生的最後4 KB日誌。 - None:預設值,不返回請求日誌。 |
回應標頭(HTTP Response Header)
使用HTTP觸發器或自訂網域名調用函數時,響應中會包含Function Compute預設添加的一些回應標頭,具體如下表所示。
| 名稱 | 描述 | 樣本值 |
| X-Fc-Request-Id | 函數調用的請求ID。 | dab25e58-9356-4e3f-97d6-f044c4**** |
API調用
對於使用InvokeFunction API的調用,Function Compute會將InvokeFunction請求轉換成HTTP請求,傳遞給使用者的HTTP Server,轉換的規則如下:
InvokeFunction的event參數被轉換成HTTP請求的訊息體。
path為/invoke。method為POST。Content-Type訊息頭為application/octe-stream。
Function Compute會將使用者HTTP Server的響應轉換為InvokeFunction的響應返回給用戶端,轉換的規則如下:
HTTP響應體轉換成InvokeFunction的響應體。
在轉換過程中會丟失HTTP回應標頭和狀態代碼資訊。
Invoke API 請求的轉換樣本
| Invoke請求 | HTTP Request (HTTP Server收到的請求) |
Invoke API 請求內容:"hello world" | > POST /invoke HTTP/1.1 > Host: 21.0.X.X > Content-Length: 11 > Content-Type: application/octet-stream hello world |
Invoke API 響應的輸出樣本
| HTTP Response | Invoke響應 |
< HTTP/1.1 200 OK < Date: Mon, 10 Jul 2025 10:37:15 GMT < Content-Type: application/octet-stream < Content-Length: 11 < Connection: keep-alive hello world | hello world |
< HTTP/1.1 400 Bad Request < Date: Mon, 10 Jul 2025 10:37:15 GMT < Content-Type: application/octet-stream < Content-Length: 28 < Connection: keep-alive {"errorMessage":"exception"} | {"errorMessage":"exception"} |
Function Compute響應碼和回應標頭
Custom Runtime本質是您實現的HTTP Server,因此每一次函數調用都是一次HTTP請求,即每次響應都有響應碼和回應標頭。
響應碼
StatusCode200:成功狀態。404:失敗狀態。
回應標頭
x-fc-status200:成功狀態。404:失敗狀態。
通過Headers中的x-fc-status響應,向Function Compute彙報本地函數是否執行成功。
不設定
x-fc-status:Function Compute預設本次調用是成功執行的,但是您的函數可能有異常,沒有向Function Compute彙報,Function Compute會認為這次函數執行沒有報錯,在商務邏輯上可能沒有影響,但是在監控可觀測性上會有影響。如以下代碼所示:print("FC Invoke Start RequestId: " + rid) data = request.stream.read() print("Path: " + path) print("Data: " + str(data)) # 類比異常:觸發一個執行階段錯誤 raise Exception("mock exception") print("FC Invoke End RequestId: " + rid) return "Hello, World!" if __name__ == '__main__': app.run(host='0.0.0.0', port=9000)設定
x-fc-status:當您的函數存在異常,通過x-fc-status響應向Function Compute彙報本次函數執行失敗,並將錯誤堆棧資訊列印到日誌中。如下所示:設定x-fc-status回應標頭為404後,Function Compute將本次調用識別為執行失敗,錯誤類型為InvocationError,返回結果為mock exception。app.py 範例程式碼:@app.route('/', defaults={'path': ''}) @app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE']) def hello_world(path): rid = request.headers.get(REQUEST_ID_HEADER) print("FC Invoke Start RequestId: " + rid) try: raise Exception("mock exception") except Exception as e: print("FC Invoke End RequestId: " + rid + ", Error: Unhandled Exception") print(str(e)) return str(e), 404, [{"x-fc-status", "404"}]
在返回的HTTP響應中,建議您同時設定StatusCode和x-fc-status。
程式碼範例
當函數配置觸發器時,您可以使用任意語言實現HTTP Server。本文以Python為例,程式碼範例如下。
該範例程式碼依賴Python環境和Flask庫,建議建立函數方式選擇Web 函數,運行環境選擇Python 3.10。
import os from flask import Flask from flask import request REQUEST_ID_HEADER = 'x-fc-request-id' app = Flask(__name__) @app.route('/', defaults={'path': ''}) @app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE']) def hello_world(path): rid = request.headers.get(REQUEST_ID_HEADER) data = request.stream.read() print("Path: " + path) print("Data: " + str(data)) return "Hello, World!", 200, [('Function-Name', os.getenv('FC_FUNCTION_NAME'))] if __name__ == '__main__': app.run(host='0.0.0.0', port=9000)樣本解析如下:
@app.route('/', defaults={'path': ''}):預設路由,對應根路徑。@app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE']):帶有路徑參數的動態路由,可以處理GET、POST、PUT、DELETE請求。路徑參數的值將被傳遞給hello_world函數作為參數path。rid = request.headers.get(REQUEST_ID_HEADER):擷取要求標頭中的x-fc-request-id欄位的值。data = request.stream.read():讀取請求的內容,並將其賦值給變數data。return "Hello, World!", 200, [('Function-Name', os.getenv('FC_FUNCTION_NAME'))]:返回一個包含"Hello, World!"的響應體,並設定狀態代碼為200及一個包含Function-Name頭部的元組。