This topic describes how to define a function in the Function Compute console. The code in this topic is for your reference only. You must define your business code as needed.

Event format

When Function Compute serves as a backend service of API Gateway, API Gateway passes the request parameters as events to Function Compute in a predefined structure. Function Compute obtains the parameters in the following way, and then processes the obtained parameters:

{
    "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"
}           
Note
  • If the value of isBase64Encoded is true, the body content that API Gateway sends to Function Compute is Base64-encoded. To trigger the corresponding function, Function Compute needs to perform Base64 decoding on the body content first.
  • If the value of isBase64Encoded is false, the body content that API Gateway set to Function Compute is not Base64-encoded. Function Compute can directly get the body content.

Define function code

  1. Log on to the Function Compute console.
  2. In the top navigation bar, select your region.
  3. In the left-side navigation pane, click Service/Function.
  4. Find the target function in the target service and click the name of the function.
  5. Click the Code tab and write code in the code editor.
    The following sample code shows code in different languages:
    • Node.js
      module.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 deal with your own logic here.  
         }
         var response = {
              isBase64Encoded: false,
              statusCode: '200',
              headers: {
                'x-custom-header': 'header value'
              },
              body: content
            }; 
         callback(null, response)
      };                               
    • Python
      # -*- 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 deal with your own logic here. 
          rep = {
              "isBase64Encoded": "false",
              "statusCode": "200",
              "headers": {
                  "x-custom-header": "no"
              },
              "body": content
          }
          return json.dumps(rep)                                
    • PHP
      <? 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);
      }                               
    • Java

      When you program in Java, you must implement a class that uses a predefined handler method for Function Compute. Two predefined handler methods are available. For more information about the Java runtime environment of Function Compute, see Java runtime environment.

      • (Recommended) Use 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) {
                // Get ApiRequest info
                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);
        
                // Deal with your own logic here
        
                // ApiResponse example
                Map headers = new HashMap();
                boolean isBase64Encoded = false;
                int statusCode = 200;
                String returnBody = "";
                return new ApiResponse(headers,isBase64Encoded,statusCode,returnBody);
            }
        }                                        
        • The following sample defines the two POJO classes: ApiRequest and ApiResponse.
          Note The set() and get() methods of the POJO 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 StreamRequestHandler handler

        To use this handler, you need to convert InputStream to the corresponding POJO class. The following sample describes how to use this handler.

        The pom.xml file must be configured the same as that of 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 to 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)));
        
                    // Deal with your own logic here
        
                    // construct response
                    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;
                }
            }
        
            // FC need to return the response 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;
                }
            }
        }                                        

Format of responses from Function Compute

Function Compute sends the execution result of the corresponding function to API Gateway in the JSON format, as shown in the following code snippet. API Gateway will parse the response that Function Compute returns.

{
    "isBase64Encoded":true|false,
    "statusCode":httpStatusCode,
    "headers":{response headers},
    "body":"..."
}       
Note isBase64Encoded specifies the encoding format of the content that Function Compute returns to API Gateway.
  • If the body content of the response is binary data, Function Compute needs to perform Base64 encoding on the body content. In this case, set isBase64Encoded to true.
  • If Function Compute does not need to perform Base64 encoding on the body content of the response, set isBase64Encoded to false.

API Gateway performs Base64 decoding on the body content for which isBase64Encoded is set to true, and then returns the decoded content to the client.

If Function Compute returns a response that is not in the required format, API Gateway returns an error "503 Service Unavailable" to the client.