REST API Routing
App routes lets you create secure public (REST) API endpoints to serverless JavaScript functions in your application.
Example REST API route
The example app routes below creates two REST API endpoint routes that triggers a serverless function. This simple example function echo
does nothing useful, other than echoing back the request data to the client as JSON.
import app from 'codehooks-js'
// Codehooks API routes
app.post('/myroute', echo);
app.get('/myroute/:var1/:var2', echo);
// Serverless function
function echo(req, res) {
res.json(req);
}
// bind to Codehooks runtime
export default app.init();
After deploying the REST API with the coho deploy
CLI command we can run a quick test from the command line using curl
.
You can use Postman together with Codehooks for testing your APIs.
curl https://myproject-abcd.api.codehooks.io/dev/myroute/123/321
-H 'x-apikey: 6e111ea6-6b3a-412d-8f6b-061c816c67c9'
The example shows that our function echoes back the input as a structured (and very handy) JSON object.
{
"hostname": "myproject-abcd.api.codehooks.io",
"headers": {
"host": "myproject-abcd.api.codehooks.io",
"user-agent": "curl/7.77.0",
"accept": "*/*",
"x-apikey": "6e111ea6-6b3a-412d-8f6b-061c816c67c8"
},
"query": {},
"path": "/dev/myroute/123/321",
"apiPath": "/myroute/123/321",
"originalUrl": "/dev/myroute/123/321",
"params": {
"var1": "123",
"var2": "321"
},
"body": {},
"method": "GET"
}
After deployment the specified routes will be available as HTTPS endpoints.
REST API endpoint URL spec
A REST API app route is available at an HTTPS endpoint based on the HTTP verb, tenant ID, datastore name and API route specification.
┌─── Project Id, e.g. booking-2b39
│ ┌─── Project space name (environment) , e.g. prod
│ │ ┌─── API route, e.g. /cars/:model/:make
│ │ │ ┌─── Parameters, e.g. color=black
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
https://<PROJECT>.api.codehooks.io/<SPACE>/<API-ROUTE>[?QUERY]
Example URL: /cars/:model/:make
https://booking-2b39.api.codehooks.io/prod/cars/Tesla/model-x?color=black&campaign=A
REST API route matching
Any request agaist a space REST API, e.g. /dev/*
, are matched against the deployed and declared app route functions.
String path
Route declaration must match exact to trigger function.
// matches: https://apollo-ff00.api.codehooks.io/dev/admin
app.get("/admin", myFunc)
Path parameters
Route declaration can match variable named segments of route to trigger function.
// matches: https://apollo-ff00.api.codehooks.io/dev/admin/abc-123
app.get('/admin/:messageId', myFunc)
Wildcard
Route declaration can match wildcard segments of route to trigger function.
// matches: https://apollo-ff00.api.codehooks.io/dev/user/abc-123/inbox
// matches: https://apollo-ff00.api.codehooks.io/dev/user/turbo-xyz/inbox
app.get('/user/*/inbox', myFunc)
Regular expression
Route declaration matches a regular expression to trigger function.
// matches: https://apollo-ff00.api.codehooks.io/dev/foo/bar
// matches: https://apollo-ff00.api.codehooks.io/dev/user/bar/foo/y/x
app.get(/^\/(foo|bar)/, myFunc)
The REST API request object
The request object contains these following properties for a client (HTTPS) request.
Overview
request.headers
Get the HTTP header values as key-value pairs.
console.log(req.headers['user-agent']); // -> PostmanRuntime/7.29.0
request.query
Get the URL query parameters as key-value pairs.
// route: /product
// url : /dev/product?price=10
console.log(req.query.price); // -> 10
request.params
Get the URL route variables as key-value pairs.
// route: /order/:orderID/:type
// url : /dev/order/12345/small
console.log(req.params.orderID, req.params.type); // -> 12345, small
request.body
Get the request body.
console.log(req.body); // -> {"foo": "bar"}
request.path
Get the URL full path.
// route: /order/:orderID
// url : /dev/order/12345
console.log(req.path); // -> /dev/order/12345
request.apipath
Get the URL api path.
// route: /order/:orderID
// url : /dev/order/12345
console.log(req.apipath); // -> /order/12345
request.originalUrl
Get the URL full path and query parameter string.
// route: /order/:orderID
// url : /dev/product?size=small
console.log(req.originalUrl); // -> /dev/product?size=small
request.method
Get the HTTP request verb.
// url: /dev/product
console.log(req.method); // -> GET
request.hostname
Get the project URL domain name.
// url: https://myproject-ff00.api.codehooks.io/dev/product
console.log(req.hostname); // -> myproject-ff00.api.codehooks.io
request.pipe(Stream)
Process a request data stream by piping it to another stream. Useful to process other data formats than JSON, e.g. binary or raw data content types - content-type: application/octet-stream
.
const mystream = new PassThrough();
// process mystream
req.pipe(mystream);
request.on(event, data)
Process a request data stream by listening to the request data emitter. Useful to process other data formats than JSON, e.g. binary or raw data content types - content-type: application/octet-stream
.
req.on('data', (buf) => {
console.log(buf.length) // process buf data
})
req.on('end', (bytes) => {
console.log('Got binary data', bytes)
res.end('Got binary ' + bytes)
})
The REST API response object
The response object sends data back to the client and finalizes the request.
Overview
response.set(header, value)
Set a response header value.
Parameters
header
string, read more about HTTP header valuesvalue
string
Code example
// REST route
app.get('/myroute', myFunc)
function myFunc(req, res) {
res.set('Content-Type', 'text/html; charset=UTF-8'); // set a response header
res.end('<h1>Hello world!</h1>'); // send html back to client
}
response.headers(Object)
Set multiple response header values.
Parameters
Object
JSON, read more about HTTP header values
Code example
// REST route
app.get('/myroute', myFunc)
function myFunc(req, res) {
res.headers({
'Content-Type': 'text/html; charset=UTF-8',
'X-myheader': '123456890'
});
res.send('<h1>Hello world!</h1>'); // send html back to client
}
response.status(HttpStatusCode)
Return a HTTP response status code for a client request.
Parameters
HttpStatusCode
integer, read more about HTTP status codes
Code example
// REST route
app.get('/myroute', myFunc)
function myFunc(req, res) {
res.status(401); // Unauthorized
res.end();
}
response.json(Object)
Return a JSON response for a client request.
Ends the client request and terminates the Codehook execution.
Parameters
Object
JSON
Code example
// REST route
app.get('/myroute', myFunc)
function myFunc(req, res) {
res.json({"message": "Hello"});
}
response.write(data, [encoding])
Stream data back to the client as text or binary data buffers.
NB! content-type
must be set before any write
operations.
Parameters
data
string or any data that the Content-Type allowsencoding
optional string useres.write(mybuf, 'buffer')
to write binary data back to client
Code example
// REST route
app.get('/myroute', myFunc)
function myFunc(req, res) {
res.set('content-type', 'text/plain');
res.write('Hello');
res.write('world!')
res.write('\n');
res.end();
}
response.send(data)
End response for a client request.
Ends client request and terminates the Codehook execution immediately.
If not called, the Codehook will not return and finally time out.
Parameters
data
string
Code example
// REST route
app.get('/myroute', myFunc)
function myFunc(req, res) {
res.send("Thanks for visiting!");
res.end();
}
response.redirect(statusCode, URL)
Redirect a client request.
Parameters
statusCode
number 301 or 302URL
string A valid relative or absolute URL
Code example
// REST route
app.get('/myroute', myFunc)
function myFunc(req, res) {
res.redirect(301, 'https://example.com')
}
response.end()
End response for a client request.
Ends client request and terminates the Codehook execution immediately.
If not called, the Codehook will not return and finally time out.
Parameters
- none
Code example
// REST route
app.get('/myroute', myFunc)
function myFunc(req, res) {
res.send("Thanks for visiting!");
res.end();
}
response.writable
Get the Writable object that can be used in node.js Stream operations.
mystream.pipe(res.writable)
Middleware functions
You can create middleware logic by chaining functions in an array or globally with the app.use
function.
Each function have a next
method parameter that is used to "chain" the next function or to terminate the chain. The example below shows how a middleware function is called before the main function. The middelware function typically check some state or logic before proceeding to the next.
import app from 'codehooks-js'
// Global middleware on all routes
app.use((req, res, next) => {
console.log("I'm global");
res.next();
})
// Global middleware on route matches
app.use('/my*', (req, res, next) => {
console.log("I'm global match for /my*");
res.next();
})
// Example route with middleware
app.post('/myroute', middleWare, myFunc);
// REST route
app.get('/myroute', myFunc)
function myFunc(req, res) {
// All is OK, got here finally
res.end();
}
function middleWare(req, res, next) {
let OK = true;
// do something here
if (OK) {
next();
} else {
res.status(401); // Unauthorized
res.end();
}
}
export default app.init();
Wildcard routes
Wildcards lets you match all methods
and all routes
that are not matched by previous routes
.
See example code below.
import app from 'codehooks-js'
app.get('/myroute': getFunc);
app.put('/myroute/:id': putFunc);
// wildcard route
app.all('/*': (req, res) => {
res.end("I catch all methods, on all routes not matched before");
}
)
export default app.init();