Building FunctionGraph HTTP Functions with PHP from scratch

Following chapter describes in short how to build FunctionGraph HTTP functions using PHP from scratch.

Introduction

For general details about creating HTTP functions from scratch and executing an HTTP function, see Creating a Function from Scratch and Executing the Function in the User Guide.

Function Development Overview

See also General Constraints for HTTP Functions

Step 1: Create a function

In FunctionGraph console, create a function with the following parameters:

  • Create with: Create from scratch

  • Function Type: HTTP Function

  • Region: select the region where you want to create the function

  • Function Name: http-function-scratch

leave the other parameters with default values, and click Create Function to create the function.

Step 2: Write code for the function

For HTTP functions, the code is expected to listen for HTTP requests and send responses.

You can use any PHP web framework or library to implement the function code.

The following is a sample code using the PHP built-in HTTP Web Server.

Full code for this example can be found at: samples-doc/scratch-http.

Note

This sample is for demonstration purposes only. The built-in Web Server should not be used on a public network.

In the code editor, replace the default code for file index.php with the following code, and click Deploy to save the code.

<?php

// Function to retrieve FunctionGraph environment variable values
// from the RUNTIME_USERDATA environment variable.
// $name is the key of the FunctionGraph environment variable to retrieve.
function getUserData($name) {
  $userdata = getenv('RUNTIME_USERDATA');
  if ($userdata === false) {
    return null;
  }
  $runtime_userdata = json_decode($userdata, true);
  return $runtime_userdata[$name] ?? null;
}

// Parse the request path from the URL.
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);

$headers = getallheaders();
$request_id = $headers['X-Cff-Request-Id'] ?? null;

error_log("Request ID: " . $request_id, 4);

// Handle GET requests to the root path.
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $path === '/') {
  header('Content-Type: application/json');

  $name = $_GET['name'] ?? 'World';
  if (is_array($name)) {
    $name = reset($name);
  }

  echo json_encode([
    'message' => "Hello, {$name}!",
    'user_data' => getUserData('USER_DATA'),
    'secret_user_data' => getUserData('SECRET_USER_DATA'),
  ], JSON_THROW_ON_ERROR);
  exit;
}

// Handle POST requests to the root path.
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $path === '/') {
  echo file_get_contents('php://input');
  exit;
}

// Handle requests to paths that are not found.
http_response_code(404);

// Respond with a 404 status code and appropriate message for not found paths.
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  header('Content-Type: application/json');
  echo json_encode(['message' => 'Not found!'], JSON_THROW_ON_ERROR);
} else {
  echo 'Not Found';
}

Step 3: Configure the bootstrap file

A file named bootstrap is used to start the function runtime and execute the function code.

The following is the code to be added in the bootstrap file for PHP runtime.

It starts PHP built-in Webserver and executes the index.php file.

bootstrap
cd $RUNTIME_CODE_ROOT/src
/opt/function/runtime/[PHP_RUNTIME]/rtsp/php/bin/php -S 0.0.0.0:8000 [FUNCTION_FILENAME]

where

  • [PHP_RUNTIME] is the PHP runtime to use (see Supported PHP Runtimes).

  • $RUNTIME_CODE_ROOT is the environment variable that points to the root directory of your function code (/opt/function/code).

  • [FUNCTION_FILENAME] is the name of the file that contains your function code (e.g., index.php).

In the code editor, replace the default code for file bootstrap with the following code, and click Deploy to save the code.

cd $RUNTIME_CODE_ROOT
/opt/function/runtime/php8.3/rtsp/php/bin/php -S 0.0.0.0:8000 index.php

Step 4: Configure environment variables

Click on Configuration tab and then select Environment Variables to configure the environment variables for the function (see also Configuring Environment Variables in the User Guide)

Add following environment variables:

Key

Value

Encrypted

USER_DATA

mydata

disabled

SECRET_USER_DATA

mysecret

enabled

Note

Encrypted environment variables are only accessible through the runtime environment variable RUNTIME_USERDATA. The environment variable RUNTIME_USERDATA is a JSON string that contains all configured FunctionGraph environment variables and their values.

Step 5: Create test events

Click on Test tab, and click Configure Test Event to create test events with the following parameters:

(For HTTP functions only “API Gateway (Dedicated)” event template is supported.)

Execution event: test_post

For POST / request create a test event named test_post:

{
   "body": "eyJtZXNzYWdlIjogIkhlbGxvLCBXb3JsZCEifQ==",
   "requestContext": {
     "apiId": "bc1dcffd-aa35-474d-897c-d53425a4c08e",
     "requestId": "11cdcdcf33949dc6d722640a13091c77",
     "stage": "RELEASE"
   },
   "queryStringParameters": {
     "responseType": "html"
   },
   "httpMethod": "POST",
   "pathParameters": {},
   "headers": {
     "content-type": "application/json",
     "accept-language": "q=0.5,en-US;q=0.3,en;q=0.2",
     "accept-encoding": "gzip, deflate, br",
     "x-forwarded-port": "443",
     "x-forwarded-for": "103.218.216.98",
     "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
     "upgrade-insecure-requests": "1",
     "host": "host",
     "x-forwarded-proto": "https",
     "pragma": "no-cache",
     "cache-control": "no-cache",
     "x-real-ip": "103.218.216.98",
     "user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0"
   },
   "path": "/",
   "isBase64Encoded": true
 }

Execution event: test_get

For GET / request create a test event named test_get:

{
   "body": "",
   "requestContext": {
     "apiId": "bc1dcffd-aa35-474d-897c-d53425a4c08e",
     "requestId": "11cdcdcf33949dc6d722640a13091c77",
     "stage": "RELEASE"
   },
   "queryStringParameters": {
     "responseType": "html",
     "name": "John"
   },
   "httpMethod": "GET",
   "pathParameters": {},
   "headers": {
     "accept-language": "q=0.5,en-US;q=0.3,en;q=0.2",
     "accept-encoding": "gzip, deflate, br",
     "x-forwarded-port": "443",
     "x-forwarded-for": "103.218.216.98",
     "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
     "upgrade-insecure-requests": "1",
     "host": "host",
     "x-forwarded-proto": "https",
     "pragma": "no-cache",
     "cache-control": "no-cache",
     "x-real-ip": "103.218.216.98",
     "user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0"
   },
   "path": "/",
   "isBase64Encoded": true
 }

Step 5: Test the function

Click Test to execute the function with the test events created in the previous step, and you should see the following output in the Execution Result section

Execution result: test_post

{
  "body": "eyJtZXNzYWdlIjogIkhlbGxvLCBXb3JsZCEifQ==",
  "headers": {
      "Content-Type": [
          "text/html; charset=UTF-8"
      ],
      "Date": [
          "Wed, 09 Sep 2026 10:27:22 GMT"
      ],
      "Host": [
          "host"
      ],
      "X-Powered-By": [
          "PHP/8.3.6"
      ]
  },
  "statusCode": 200,
  "isBase64Encoded": true
}

The body in the output is base64 encoded. After decoding, you should see the following content:

{"message": "Hello, World!"}

Execution result: test_get

{
    "body": "eyJtZXNzYWdlIjoiSGVsbG8sIEpvaG4hIiwidXNlcl9kYXRhIjoibXlkYXRhIiwic2VjcmV0X3VzZXJfZGF0YSI6Im15c2VjcmV0In0=",
    "headers": {
        "Content-Type": [
            "application/json"
        ],
        "Date": [
            "Fri, 18 Sep 2026 07:37:43 GMT"
        ],
        "Host": [
            "host"
        ],
        "X-Powered-By": [
            "PHP/8.3.6"
        ]
    },
    "statusCode": 200,
    "isBase64Encoded": true
}

The body in the output is base64 encoded. After decoding, you should see the following content:

{"message":"Hello, John!","user_data":"mydata","secret_user_data":"mysecret"}