HTTP Cloud Function Routing
Based on the @cloudbase/functions-framework framework, you can split a large function into multiple sub-functions and route different requests to different handler functions through request paths
Why Function Routing is Neededâ
In traditional cloud function development models, each function needs to be deployed and run independently, which brings the following problems:
- Resource Waste: Each function occupies a dedicated instance and needs to keep running even with small request volumes
- Frequent Cold Starts: More functions mean more cold start instances
- Complex Deployment: Need to deploy and manage multiple functions separately
- Higher Costs: More instances lead to higher resource costs
Using function routing can solve these problems:
- Resource Sharing: Multiple functions share the same instance, fully utilizing computing resources
- Cost Reduction: Reduce instance count and cold start frequency
- Simplified Deployment: Deploy multiple functions at once with unified management
- Performance Improvement: Share resources like memory and connection pools to improve response speed
Prerequisitesâ
Using function routing requires installing the @cloudbase/functions-framework dependency:
npm install @cloudbase/functions-framework
This framework provides core capabilities such as function loading, route distribution, and request handling.
Quick Startâ
Step 1: Create Project Structureâ
Create a project directory that supports multiple functions:
my-functions/
âââ package.json # Project configuration
âââ scf_bootstrap # Bootstrap script
âââ cloudbase-functions.json # Function routing configuration (key)
âââ index.js # Default function entry
âââ user/ # user function directory
â âââ index.js
âââ order/ # order function directory
âââ index.js
Step 2: Create Function Codeâ
Default Function (index.js):
exports.main = function (event, context) {
return {
message: 'Hello from default function',
path: context.httpContext.url,
};
};
user Function (user/index.js):
exports.main = function (event, context) {
return {
message: 'User API',
path: context.httpContext.url,
method: context.httpContext.httpMethod,
};
};
order Function (order/index.js):
exports.main = function (event, context) {
return {
message: 'Order API',
path: context.httpContext.url,
};
};
Step 3: Configure Function Routingâ
Create a cloudbase-functions.json configuration file:
{
"functionsRoot": ".",
"functions": [
{
"name": "default",
"directory": "."
},
{
"name": "user",
"directory": "user",
"triggerPath": "/api/user" // triggerPath is the simplified write method of routes, which can directly specify the trigger path in the function definition
},
{
"name": "order",
"directory": "order",
"triggerPath": "/api/order"
}
],
"routes": [
{
"functionName": "echo",
"path": "/echo"
}
]
}
Step 4: Configure package.jsonâ
{
"name": "my-functions",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@cloudbase/functions-framework": "latest"
}
}
Step 5: Create Bootstrap Scriptâ
Create a scf_bootstrap file (without extension):
#!/bin/bash
node node_modules/@cloudbase/functions-framework/bin/tcb-ff.js \
--port=9000 \
--logDirname=/tmp/logs \
--interceptOutput=false \
--extendedContextKey=X-Cloudbase-Context \
--functionsConfigFile=cloudbase-functions.json
â ï¸ Important: The
scf_bootstrapfile needs to have executable permissions. On Linux/macOS systems, use thechmod +x scf_bootstrapcommand to set permissions.
Bootstrap Parameters:
| Parameter | Description | Default Value |
|---|---|---|
--port | Function listening port | 9000 |
--logDirname | Log storage directory | /tmp/logs |
--interceptOutput | Whether to intercept standard output | false |
--extendedContextKey | Extended context request header key name | X-Cloudbase-Context |
--functionsConfigFile | Function routing configuration file path | cloudbase-functions.json |
Step 6: Install Dependenciesâ
npm install
Step 7: Local Testingâ
Start the function service:
./scf_bootstrap
Test different routes:
# Test default function
curl http://localhost:9000/
# Test user function
curl http://localhost:9000/api/user
# Test order function
curl http://localhost:9000/api/order
Step 8: Deploy to Cloudâ
Deploy the function using CloudBase CLI or console, then access after deployment:
# Default function
https://your-function.run.tcloudbase.com/
# user function
https://your-function.run.tcloudbase.com/api/user
# order function
https://your-function.run.tcloudbase.com/api/order
Route Matching Rulesâ
Understanding route matching rules is crucial for correctly configuring function routing:
1. Prefix Matchingâ
Route matching uses prefix matching mode. When a request path starts with a route rule's path, it can match that route.
Example:
{
"routes": [
{
"functionName": "user",
"path": "/api/user"
}
]
}
The following request paths will all match the user function:
/api/userâ/api/user/â/api/user/profileâ/api/user/listâ
The following request paths will not match:
/api/usersâ (does not start with/api/user)/apiâ (path incomplete)
2. Longest Matchâ
When multiple route rules can match the same request path, the framework will select the longest route rule.
Example:
{
"routes": [
{
"functionName": "user",
"path": "/api/user"
},
{
"functionName": "userProfile",
"path": "/api/user/profile"
}
]
}
Routing results:
/api/userâuserfunction/api/user/listâuserfunction/api/user/profileâuserProfilefunction (longest match)/api/user/profile/detailâuserProfilefunction (longest match)
3. Trailing Slash Handlingâ
The trailing / in paths does not affect matching results; /api/user and /api/user/ are considered equivalent.
Example:
{
"routes": [
{
"functionName": "user",
"path": "/api/user"
}
]
}
The following paths will all match:
/api/userâ/api/user/â
4. Path Unit Exact Matchingâ
Route matching splits paths by / into path units, and each path unit requires exact matching.
Example:
{
"routes": [
{
"functionName": "user",
"path": "/api/user"
}
]
}
Routing results:
/api/userâ/api/usersâ (usersdoes not matchuser)/api/user123â (user123does not matchuser)
5. One Function Multiple Routesâ
A function can be configured with multiple trigger paths, accessing the same function from different URL paths.
Example:
{
"routes": [
{
"functionName": "user",
"path": "/api/user"
},
{
"functionName": "user",
"path": "/v1/user"
},
{
"functionName": "user",
"path": "/v2/user"
}
]
}
All three paths above will route to the user function.
6. One Route One Functionâ
The same path can only point to one function and cannot point to multiple functions simultaneously.
Error Example:
{
"routes": [
{
"functionName": "userA",
"path": "/api/user"
},
{
"functionName": "userB",
"path": "/api/user"
}
]
}
â ï¸ Note: The above configuration will cause route conflicts and the framework will report an error.
7. Default Routeâ
You can configure a route with path as / as the default route to handle all unmatched requests.
Example:
{
"routes": [
{
"functionName": "user",
"path": "/api/user"
},
{
"functionName": "order",
"path": "/api/order"
},
{
"functionName": "default",
"path": "/"
}
]
}
Routing results:
/api/userâuserfunction/api/orderâorderfunction/âdefaultfunction/aboutâdefaultfunction/healthâdefaultfunction
Advanced Usageâ
Using triggerPath to Simplify Configurationâ
triggerPath is a simplified version of routes, allowing you to specify the trigger path directly in the function definition.
Comparison:
Using triggerPath:
{
"functions": [
{
"name": "user",
"directory": "user",
"triggerPath": "/api/user"
}
],
"routes": []
}
Equivalent to:
{
"functions": [
{
"name": "user",
"directory": "user"
}
],
"routes": [
{
"functionName": "user",
"path": "/api/user"
}
]
}
ð¡ Tip: It's recommended to use
triggerPathfor more concise configuration. If you need one function to correspond to multiple routes, useroutesconfiguration.
Combining with Express/Koa Frameworksâ
Function routing can be combined with Express, Koa and other web frameworks, where each sub-function can be a complete web application.
Example:
// user/index.js
const express = require('express');
const app = express();
app.get('/profile', (req, res) => {
res.json({ user: 'profile' });
});
app.get('/list', (req, res) => {
res.json({ users: [] });
});
exports.main = app;
Access:
https://your-function.api.tcloudbasegateway.com/v1/functions/{function-name}/api/user/profile?webfn=truehttps://your-function.api.tcloudbasegateway.com/v1/functions/{function-name}/api/user/list?webfn=true
Mixing SSE and WebSocketâ
Different sub-functions can handle different types of requests, such as one function handling HTTP requests and another handling WebSocket connections.
Example:
.
âââ cloudbase-functions.json
âââ index.js # HTTP function
âââ ws/ # WebSocket function
âââ index.js
cloudbase-functions.json:
{
"functionsRoot": ".",
"functions": [
{
"name": "default",
"directory": "."
},
{
"name": "ws",
"directory": "ws",
"triggerPath": "/ws"
}
]
}
VSCode Editor Supportâ
After installing the @cloudbase/functions-framework dependency, you can get schema auto-completion for cloudbase-functions.json in VSCode.
Create a .vscode/settings.json file in the project root directory:
{
"json.schemas": [
{
"fileMatch": ["cloudbase-functions.json"],
"url": "./node_modules/@cloudbase/functions-framework/functions-schema.json"
}
]
}
After configuration, field and type suggestions will automatically appear when editing the cloudbase-functions.json file.
Complete Exampleâ
Project Structureâ
my-api-service/
âââ .vscode/
â âââ settings.json # VSCode configuration
âââ package.json # Project configuration
âââ scf_bootstrap # Bootstrap script
âââ cloudbase-functions.json # Function routing configuration
âââ index.js # Default function
âââ user/ # User API
â âââ index.js
âââ order/ # Order API
â âââ index.js
âââ product/ # Product API
â âââ index.js
âââ sse/ # SSE streaming response
âââ index.js
cloudbase-functions.jsonâ
{
"functionsRoot": ".",
"functions": [
{
"name": "default",
"directory": ".",
"triggerPath": "/"
},
{
"name": "user",
"directory": "user",
"triggerPath": "/api/user"
},
{
"name": "order",
"directory": "order",
"triggerPath": "/api/order"
},
{
"name": "product",
"directory": "product",
"triggerPath": "/api/product"
},
{
"name": "sse",
"directory": "sse",
"triggerPath": "/stream"
}
]
}
FAQâ
1. Route Configuration Not Taking Effectâ
Problem: Configured routing rules but still routing to the wrong function when accessing.
Solutions:
- Check if the
cloudbase-functions.jsonfile is in the correct location - Check if the
--functionsConfigFileparameter is specified in thescf_bootstrapstartup script - Check the order of routing rules to ensure longest match rules are first
- Use
console.logto outputcontext.httpContext.urlto view the actual request path
2. Function Not Foundâ
Problem: Startup error: Function xxx not found.
Solutions:
- Check if the
functions[].directorypath is correct - Check if the
functions[].sourcefile exists - Check if the function name exported by
functions[].targetis correct - Ensure
functionsRootis set correctly
3. Route Conflictâ
Problem: Startup error: Route conflict.
Solutions:
- Check if multiple route rules point to the same path
- Check if there are duplicate configurations in
triggerPathandroutes - Ensure each path corresponds to only one function
4. Default Function Not Workingâ
Problem: Configured default route with path: "/" but getting 404 when accessing.
Solutions:
- Ensure the default route configuration is at the end of the
routesarray - Check if other route rules override the default route
- Ensure the default function's
directoryandsourceconfigurations are correct
5. Hot Reload Not Working in Local Developmentâ
Problem: After modifying function code, need to restart the service for changes to take effect.
Solutions:
The @cloudbase/functions-framework framework does not currently support hot reload, requiring manual service restart:
# Stop service (Ctrl+C)
# Restart
./scf_bootstrap