HTTP Customization
In cases where Celest's standard HTTP conventions do not align with your requirements, you can control the HTTP API generated for your Celest Functions using the HTTP annotations.
Some HTTP elements are not currently configurable, such as the URL path. If you require this functionality, please let us know by creating an issue (opens in a new tab).
Execution Controls
The @http
and @httpError
annotations allow you to control the behavior of the HTTP endpoint, such as how the endpoint is exposed,
and how it responds in both success and error cases.
@http
To configure the method and default status code of your HTTP endpoint, use the @http
annotation.
@cloud
@http(
method: HttpMethod.put,
statusCode: HttpStatus.created,
)
Future<String> greet(String name) async {
return 'Hello, $name';
}
PUT /greet
Content-Type: application/json
{
"name": "Celest"
}
HTTP/1.1 201 Created
Content-Type: application/json
{
"response": "Hello, Celest"
}
@httpError
To control the status code returned from one or more thrown types, use the @httpError
annotation.
@cloud
@httpError(403, UnauthorizedException)
@httpError(404, BadNameException, NotFoundException)
Future<String> greet(String name) async {
if (name.isEmpty) {
throw BadNameException();
}
if (!name.startsWith('C')) {
throw NotFoundException();
}
if (name != 'Celest') {
throw UnauthorizedException();
}
return 'Hello, $name';
}
Exception types are handled in order of specificity. Specifying a type that other types inherit from will only apply the status code to subtypes which are not already covered by a more specific case.
For example, the following will return a 404 status code for both the concrete NotFoundException
type and BadNameException
(since it
is a subtype of Exception
), but not UnauthorizedException
which is covered by a more specific annotation.
@cloud
@httpError(404, NotFoundException, Exception)
@httpError(403, UnauthorizedException)
Future<String> greet(String name) async {
if (name.isEmpty) {
throw BadNameException(); // 404
}
if (!name.startsWith('C')) {
throw NotFoundException(); // 404
}
if (name != 'Celest') {
throw UnauthorizedException(); // 403
}
return 'Hello, $name';
}
Request Controls
The @httpHeader
and @httpQuery
annotations allow you to map input parameters to HTTP headers and query parameters, respectively.
Any parameters which are not targeted by these annotations are passed as the request body.
Some combinations are disallowed. For example, if the @http
annotation specifies a GET
method, then all input
parameters must be mapped, or there must be no input parameters, such that the request body is empty.
@httpHeader
To map an input parameter to an HTTP header, use the @httpHeader
annotation.
Only parameters of type String
, int
, double
, bool
, DateTime
, or a List
of these types, can be targeted by @httpHeader
.
@cloud
Future<String> greet({
@httpHeader('x-api-key') required String apiKey,
required String name,
}) async {
return 'Hello, $name';
}
In the generated client, these parameters are passed transparently as function arguments.
final result = await celest.functions.greet(apiKey: '123', name: 'Celest');
POST /greet
Content-Type: application/json
x-api-key: 123
{
"name": "Celest"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"response": "Hello, Celest"
}
The following HTTP headers are reserved and cannot be targeted by @httpHeader
:
Header Name |
---|
Connection |
Content-Length |
Expect |
Host |
Max-Forwards |
Server |
TE |
Header Name |
---|
Trailer |
Transfer-Encoding |
Upgrade |
User-Agent |
Via |
X-Forwarded-For |
@httpQuery
To map an input parameter to a query parameter, use the @httpQuery
annotation.
Only parameters of type String
, int
, double
, bool
, DateTime
, or a List
of these types, can be targeted by @httpQuery
.
@cloud
@http(method: HttpMethod.get)
Future<String> greet({
@httpQuery('name') required String name,
}) async {
return 'Hello, $name';
}
In the generated client, these parameters are passed transparently as function arguments.
final result = await celest.functions.greet(name: 'Celest');
GET /greet?name=Celest
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
{
"response": "Hello, Celest"
}