Function Compute supports using API Gateway as an event source. You can configure Function Compute as the backend service for APIs. When a request is received by the API Gateway instance configured to use Function Compute as its backend service, API Gateway triggers the associated function to execute. Once the function completes its execution, Function Compute sends the result back to API Gateway.
Background
API Gateway triggers work similarly to HTTP triggers and can be used to build web applications. Unlike HTTP triggers, API Gateway triggers allow you to perform advanced operations, such as setting IP whitelists or blacklists.
API Gateway can be configured to use both event functions and web functions as its backend service. Once Function Compute is integrated with API Gateway, these functions can be securely exposed to clients through APIs. This setup allows for effective management of various concerns, including authentication, traffic control, and data conversion.
Create an event function and integrate it with API Gateway
Step 1: Create an event function
Create an event function in the Function Compute console. For more information, see Create an event function.
Step 2: Create an API with Function Compute as its backend service
You must create a backend service in API Gateway and configure a URL for the backend service to point to your Function Compute service.
Log on to the API Gateway console. In the left-side navigation pane, choose Manage APIs > Backend Services. In the top navigation bar, select a region. Then, click Create Backend Service in the upper-right corner, configure the parameters as shown in the following figure, and click Confirm:
On the Backend Services page, click the backend service you just created. On the Backend Service Definition page, click the Production tab. In the Basic Information section, click Create. Choose the event function you created in Step 1 and click Publish.
Create an API group.
We recommend that you create an API group in the same region as your function. If the API is in a different region, it will need to access your Function Compute services over the Internet, which will incur traffic costs. For stringent data security and network latency requirements, ensure that the API group is created in the same region as your function.
Create and publish an API.
Configure the required parameters as outlined below. You can leave the rest at their default settings.
Parameter
Configuration instruction
Parameter
Configuration instruction
Security Authentication
Select No Authentication.
Configuration Mode
Choose Use Existing Backend Service.
Backend Service Type
Choose Function Compute.
Version
Choose Function Compute V3.0.
Function Type
Choose Event Function.
Backend Service
Choose the backend service you just created that points to the event function.
Step 3: Write the function code
Log on to the Function Compute console. In the left-side navigation pane, click Functions.
In the top navigation bar, select a region. On the Functions page, click the function that you want to manage.
On the Code tab of the Function Details page, write code in the code editor and click Deploy.
The sample code for different languages is as follows:
Node.jsPythonPHPJavamodule.exports.handler = function(event, context, callback) { var event = JSON.parse(event); var content = { path: event.path, method: event.method, headers: event.headers, queryParameters: event.queryParameters, pathParameters: event.pathParameters, body: event.body // You can write your own logic here. } var response = { isBase64Encoded: false, statusCode: '200', headers: { 'x-custom-header': 'header value' }, body: content }; callback(null, response) };
# -*- coding: utf-8 -*- import json def handler(event, context): event = json.loads(event) content = { 'path': event['path'], 'method': event['httpMethod'], 'headers': event['headers'], 'queryParameters': event['queryParameters'], 'pathParameters': event['pathParameters'], 'body': event['body'] } # You can write your own logic here. rep = { "isBase64Encoded": "false", "statusCode": "200", "headers": { "x-custom-header": "no" }, "body": content } return json.dumps(rep)
<?php function handler($event, $context) { $event = json_decode($event, $assoc = true); $content = [ 'path' => $event['path'], 'method' => $event['httpMethod'], 'headers' => $event['headers'], 'queryParameters' => $event['queryParameters'], 'pathParameters' => $event['pathParameters'], 'body' => $event['body'], ]; $rep = [ "isBase64Encoded" => "false", "statusCode" => "200", "headers" => [ "x-custom-header" => "no", ], "body" => $content, ]; return json_encode($rep); }
When you program in Java for Function Compute, you must implement a class that uses a predefined handler method. There are two predefined handler methods. For more information about the Java runtime, see Compile and deploy code packages.
(Recommended) Use the PojoRequestHandler<I, O> handler.
import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.PojoRequestHandler; import java.util.HashMap; import java.util.Map; public class ApiTriggerDemo implements PojoRequestHandler<ApiRequest, ApiResponse> { public ApiResponse handleRequest(ApiRequest request, Context context) { // Obtain the API request information. context.getLogger().info(request.toString()); String path = request.getPath(); String httpMethod = request.getHttpMethod(); String body = request.getBody(); context.getLogger().info("path:" + path); context.getLogger().info("httpMethod:" + httpMethod); context.getLogger().info("body:" + body); // You can write your own logic here. // API response example. Map headers = new HashMap(); boolean isBase64Encoded = false; int statusCode = 200; String returnBody = ""; return new ApiResponse(headers,isBase64Encoded,statusCode,returnBody); } }
The following sample defines two
POJO
classes:ApiRequest
andApiResponse
.The
set()
andget()
methods of thePOJO
classes must be specified.import java.util.Map; public class ApiRequest { private String path; private String httpMethod; private Map headers; private Map queryParameters; private Map pathParameters; private String body; private boolean isBase64Encoded; @Override public String toString() { return "Request{" + "path='" + path + '\'' + ", httpMethod='" + httpMethod + '\'' + ", headers=" + headers + ", queryParameters=" + queryParameters + ", pathParameters=" + pathParameters + ", body='" + body + '\'' + ", isBase64Encoded=" + isBase64Encoded + '}'; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getHttpMethod() { return httpMethod; } public void setHttpMethod(String httpMethod) { this.httpMethod = httpMethod; } public Map getHeaders() { return headers; } public void setHeaders(Map headers) { this.headers = headers; } public Map getQueryParameters() { return queryParameters; } public void setQueryParameters(Map queryParameters) { this.queryParameters = queryParameters; } public Map getPathParameters() { return pathParameters; } public void setPathParameters(Map pathParameters) { this.pathParameters = pathParameters; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public boolean getIsBase64Encoded() { return this.isBase64Encoded; } public void setIsBase64Encoded(boolean base64Encoded) { this.isBase64Encoded = base64Encoded; } }
import java.util.Map; public class ApiResponse { private Map headers; private boolean isBase64Encoded; private int statusCode; private String body; public ApiResponse(Map headers, boolean isBase64Encoded, int statusCode, String body) { this.headers = headers; this.isBase64Encoded = isBase64Encoded; this.statusCode = statusCode; this.body = body; } public Map getHeaders() { return headers; } public void setHeaders(Map headers) { this.headers = headers; } public boolean getIsBase64Encoded() { return isBase64Encoded; } public void setIsBase64Encoded(boolean base64Encoded) { this.isBase64Encoded = base64Encoded; } public int getStatusCode() { return statusCode; } public void setStatusCode(int statusCode) { this.statusCode = statusCode; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } }
The following code shows an example of the pom.xml file.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>apiTrigger</groupId> <artifactId>apiTrigger</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>com.aliyun.fc.runtime</groupId> <artifactId>fc-java-core</artifactId> <version>1.0.0</version> </dependency> </dependencies> </project>
Use the StreamRequestHandler handler.
To use this handler, you must convert
InputStream
to thePOJO
class. The following sample code describes how to use this handler.The configuration of the pom.xml file is the same as when using the PojoRequestHandler<I, O> handler.
import com.aliyun.fc.runtime.Context; import com.aliyun.fc.runtime.StreamRequestHandler; import com.aliyun.fc.runtime.Context; import com.google.gson.Gson; import java.io.*; import java.util.Base64; import java.util.HashMap; import java.util.Map; public class ApiTriggerDemo2 implements StreamRequestHandler { public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) { try { // Convert InputStream into a string. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); StringBuffer stringBuffer = new StringBuffer(); String string = ""; while ((string = bufferedReader.readLine()) != null) { stringBuffer.append(string); } String input = stringBuffer.toString(); context.getLogger().info("inputStream: " + input); Request req = new Gson().fromJson(input, Request.class); context.getLogger().info("input req: "); context.getLogger().info(req.toString()); String bodyReq = req.getBody(); Base64.Decoder decoder = Base64.getDecoder(); context.getLogger().info("body: " + new String(decoder.decode(bodyReq))); // You can write your own logic here. // The returned result. Map headers = new HashMap(); headers.put("x-custom-header", " "); boolean isBase64Encoded = false; int statusCode = 200; Map body = new HashMap(); Response resp = new Response(headers, isBase64Encoded, statusCode, body); String respJson = new Gson().toJson(resp); context.getLogger().info("outputStream: " + respJson); outputStream.write(respJson.getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { try { outputStream.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } class Request { private String path; private String httpMethod; private Map headers; private Map queryParameters; private Map pathParameters; private String body; private boolean isBase64Encoded; @Override public String toString() { return "Request{" + "path='" + path + '\'' + ", httpMethod='" + httpMethod + '\'' + ", headers=" + headers + ", queryParameters=" + queryParameters + ", pathParameters=" + pathParameters + ", body='" + body + '\'' + ", isBase64Encoded=" + isBase64Encoded + '}'; } public String getBody() { return body; } } // Function Compute returns responses to API Gateway in the following JSON format. class Response { private Map headers; private boolean isBase64Encoded; private int statusCode; private Map body; public Response(Map headers, boolean isBase64Encoded, int statusCode, Map body) { this.headers = headers; this.isBase64Encoded = isBase64Encoded; this.statusCode = statusCode; this.body = body; } } }
Step 4: Configure the input parameter of the function
When API Gateway triggers a function, it passes information in the form of an event object into the function. You can use the information to debug your function.
On the Code tab of the function details page, click the
icon next Test Function and select Configure Test Parameters from the drop-down list.
In the Configure Test Parameters panel, click the Create New Test Event or Modify Existing Test Event tab, enter the event name and event content, and click OK.
An example of the event object is as follows:
{ "path":"api request path", "httpMethod":"request method name", "headers":{all headers,including system headers}, "queryParameters":{query parameters}, "pathParameters":{path parameters}, "body":"string of request payload", "isBase64Encoded":"true|false, indicate if the body is Base64-encode" }
The following table describes the parameters in an event object.
Parameter
Type
Description
Parameter
Type
Description
path
String
The API request path.
httpMethod
String
The request method. Valid values: GET, POST, PUT, and DELETE.
headers
Object
The request header information. It encompasses all request headers, including both system headers and custom headers.
queryParameters
Object
The query parameters. They are usually in the form of key-value pairs that appear after the question mark in the URL.
pathParameters
Object
The path parameters. They are usually part of the URL and are used to identify specific resources.
body
String
The request body.
isBase64Encoded
Boolean
Specifies whether the request body is in Base64 encoding.
If the value of
isBase64Encoded
istrue
, the body content that API Gateway sends to Function Compute is Base64-encoded. Function Compute decodes the body content from Base64 format before processing the content.If the value of
isBase64Encoded
isfalse
, API Gateway did not perform Base64 encoding on the body content, and Function Compute can directly obtain the body content.
Click Test Function.
Step 5: View the result
After the function is executed, you can view the result on the Code tab.
Function Compute sends the execution result to API Gateway for parsing in the following JSON format. The following code snippet shows an example of the returned result:
{
"isBase64Encoded":true|false,
"statusCode":httpStatusCode,
"headers":{response headers},
"body":"..."
}
Format requirements when an event function is integrated with API Gateway
After API Gateway receives a request for an API operation with Function Compute as the backend service, API Gateway converts the request parameters to key-value pairs in the map format and sends the request to Function Compute. Function Compute handles the request and returns a response in a specific output format to API Gateway. The response includes information such as the status code, header, and body, as shown in the following figure. API Gateway maps the information in the response that is returned by Function Compute to the status code, headers, and body of an API response, and returns the API response to the client.
Create a web function and integrate it with API Gateway
Step 1: Create a web function
Create a web function in the Function Compute console. For more information, see Step 1: Create a web function.
An HTTP trigger is automatically created for the web function you just created. Copy the internal endpoint for subsequent use.
Step 2: Create a backend service
You must create a backend service in API Gateway and configure a URL for the backend service to point to your Function Compute service.
Log on to the API Gateway console. In the left-side navigation pane, choose Manage APIs > Backend Services. In the top navigation bar, select a region. Then, click Create Backend Service in the upper-right corner, configure the parameters as shown in the following figure, and click Confirm:
On the Backend Services page, click the backend service you just created. On the Backend Service Definition page, click the Production tab. In the Basic Information section, click Create. Paste the internal endpoint you copied in Step 1 and click Publish.
Step 3: Create and publish an API
In this step, you create an API that allows external applications to call internal web functions in specific ways. API groups are used to organize and manage multiple related APIs, facilitating the implementation of unified security policies and traffic control measures.
Log on to the API Gateway console. In the left-side navigation pane, choose Manage APIs > API Groups. On the API Groups page, click Create Group.
In the Create Group dialog box, select an instance from the Instances drop-down list, set the Group Name parameter to
FC-Group
and the BasePath parameter to/
, and click Confirm.We recommend that you create an API group in the same region as your function. If the API is in a different region, it will need to access your Function Compute services over the Internet, which will incur traffic costs. For stringent data security and network latency requirements, ensure that the API group is created in the same region as your function.
On the API Groups page, find the API group that you created, click Manage APIs in the Actions column, and then click Create API. Configure the following parameters and click Next.
In the Define API Request step, set the Request Path parameter to
/
, use the default values for other parameters, and then click Next.In the Define Backend Service step, configure the following parameters and click Next:
In the Define Response step, keep the default settings and click Create. In the Note dialog box that appears, click Publish.
In the Publish API dialog box, configure the following parameters and click Publish.
Step 4: Create an application and authorize it to call the API
The application represents the identity that is used to authenticate when making requests to the API service. In this example, Alibaba Cloud App was selected for the Security Authentication parameter in Step 3: Create and publish an API. Therefore, after the API is published, you must create an application and authorize it to call the API.
Log on to the API Gateway console. In the left-side navigation pane, choose Call APIs > Apps.
On the Apps page, click Create App in the upper-right corner. In the Create App dialog box, set App Name to
fcApp
and click Confirm.On the Apps page, click the
fcApp
application you just created. On the App Details page, you can see that two authentication methods are available:AppKey
andAppCode
. TheAppKey
method includes a pair ofAppKey
andAppSecret
, which works similarly to a pair of username and password. When you call the API, you must pass theAppKey
as a parameter. TheAppSecret
is used to calculate signatures. API Gateway verifies the AppKey-AppSecret pair to authenticate your identity.In the left-side navigation pane, choose Manage APIs > APIs. On the APIs page, find the API you just created and click
> Authorize in the Actions column.
In the Authorize dialog box, set the Stage parameter to Production. Enter
fcApp
in the search bar of the Choose Apps for Authorization section. In the search results, select the fcApp application, click Add in the Actions column, and then click Confirm. A message appears to inform you that the application is authorized to call the API.
Step 5: Verify the result
The following section describes how to use the AppCode-based authentication method to call a published API in your business system. This example uses Curl commands to make the API calls.
Log on to the API Gateway console. In the left-side navigation pane, choose Call APIs > Apps. On the Apps page, click the authorized application and obtain its AppCode on the page that appears. Then, use the following sample code to call the API:
curl -i -X GET "http://fd6f8e2b7bf44ab181a56****-cn-hangzhou.alicloudapi.com" -H "Authorization:APPCODE 7d2b7e4945ce44028ab00***"
FAQ
Error code 502 is returned when function execution is triggered by API Gateway, but the function log shows that the function is successfully executed. How do I resolve this issue?
API Gateway requires Function Compute to return responses in a specific format. If the response is not in the expected format, API Gateway considers the backend service unavailable. For more information about the format requirements of the integration between API Gateway and Function Compute, see Formats of event for different triggers and Step 5: View the result.
How do I set the content type of the returned response?
As shown in the following figure, you can specify the content type of a response in the Define Response step when you create the API. For more information, see Use API Gateway to trigger a web function in Function Compute 3.0.
Error code 503 is returned when I use API Gateway to invoke a function that was previously invoked but has not been invoked for a period of time. How do I resolve this issue?
If a function has not been invoked for some time, a new execution environment must be prepared upon its next invocation, resulting in a cold start delay. This can cause a timeout in API Gateway before the invocation completes, leading API Gateway to treat the backend service as unavailable. To resolve this issue, increase the API Gateway timeout period.
Why is the body parameter of the requests passed from API Gateway to Function Compute Base64-encoded?
The body of requests is Base64-encoded to prevent content transmission errors or loss, except for bodies transmitted in form format by API Gateway, which are not Base64-encoded. When using form format, you must select Input Parameter Mapping in API Gateway. We recommend that you check whether the value of isBase64 is true or false. If the value of isBase64 is true, Function Compute decodes the body content from Base64 format before processing the content. For more information about the event format that is passed to Function Compute by API Gateway, see Formats of event for different triggers.