Points de terminaison API Encore
Instructions
Lors de la création de points de terminaison API avec Encore.ts, suivez ces modèles :
1. Importer le module API
import { api } from "encore.dev/api";
2. Définir les interfaces de requête/réponse typées
Définissez toujours des interfaces TypeScript explicites pour les types de requête et de réponse :
interface CreateUserRequest {
email: string;
name: string;
}
interface CreateUserResponse {
id: string;
email: string;
name: string;
}
3. Créer le point de terminaison
export const createUser = api(
{ method: "POST", path: "/users", expose: true },
async (req: CreateUserRequest): Promise<CreateUserResponse> => {
// Implementation
}
);
Options API
| Option | Type | Description |
|---|---|---|
method |
string | Méthode HTTP : GET, POST, PUT, PATCH, DELETE |
path |
string | Chemin URL, supporte :param et *wildcard |
expose |
boolean | Si true, accessible de l'extérieur (défaut : false) |
auth |
boolean | Si true, nécessite une authentification |
sensitive |
boolean | Si true, masque les payloads de requête/réponse des traces |
Modèles de requête/réponse
Encore supporte quatre configurations de points de terminaison :
// Requête et réponse
export const createUser = api(
{ method: "POST", path: "/users", expose: true },
async (req: CreateRequest): Promise<CreateResponse> => { ... }
);
// Réponse uniquement (pas de corps de requête)
export const listUsers = api(
{ method: "GET", path: "/users", expose: true },
async (): Promise<ListResponse> => { ... }
);
// Requête uniquement (pas de corps de réponse)
export const deleteUser = api(
{ method: "DELETE", path: "/users/:id", expose: true },
async (req: DeleteRequest): Promise<void> => { ... }
);
// Ni requête ni réponse
export const ping = api(
{ method: "GET", path: "/ping", expose: true },
async (): Promise<void> => { ... }
);
Codes de statut HTTP personnalisés
Incluez un champ HttpStatus dans votre réponse pour retourner des codes de statut personnalisés :
import { api, HttpStatus } from "encore.dev/api";
interface CreateResponse {
id: string;
status: HttpStatus;
}
export const create = api(
{ method: "POST", path: "/items", expose: true },
async (req: CreateRequest): Promise<CreateResponse> => {
const item = await createItem(req);
return { id: item.id, status: HttpStatus.Created }; // Retourne 201
}
);
Types de paramètres
Paramètres de chemin
// Path: "/users/:id"
interface GetUserRequest {
id: string; // Extrait automatiquement de :id
}
Paramètres de requête
import { Query } from "encore.dev/api";
interface ListUsersRequest {
limit?: Query<number>;
offset?: Query<number>;
}
En-têtes
import { Header } from "encore.dev/api";
interface WebhookRequest {
signature: Header<"X-Webhook-Signature">;
payload: string;
}
Cookies
import { Cookie } from "encore.dev/api";
interface SessionRequest {
session?: Cookie<"session">;
settings?: Cookie<"user-settings">;
}
Validation de requête
Encore valide les requêtes à l'exécution en utilisant les types TypeScript. Ajoutez des contraintes pour une validation plus stricte :
import { api } from "encore.dev/api";
import { Min, Max, MinLen, MaxLen, IsEmail, IsURL } from "encore.dev/validate";
interface CreateUserRequest {
email: string & IsEmail; // Doit être une adresse e-mail valide
username: string & MinLen<3> & MaxLen<20>; // 3-20 caractères
age: number & Min<13> & Max<120>; // Entre 13 et 120
website?: string & IsURL; // Optionnel, doit être une URL si fourni
}
Combinaison de règles de validation
Utilisez & pour la logique ET (doit passer toutes les règles) et | pour la logique OU (doit passer au moins une) :
import { IsEmail, IsURL, MinLen, MaxLen } from "encore.dev/validate";
interface ContactRequest {
// Doit être une adresse e-mail valide OU une URL valide
contact: string & (IsEmail | IsURL);
// Doit faire 5-100 caractères ET être une URL valide
website: string & MinLen<5> & MaxLen<100> & IsURL;
}
Validateurs disponibles
| Validateur | S'applique à | Exemple |
|---|---|---|
Min<N> |
number | age: number & Min<18> |
Max<N> |
number | count: number & Max<100> |
MinLen<N> |
string, array | name: string & MinLen<1> |
MaxLen<N> |
string, array | tags: string[] & MaxLen<10> |
IsEmail |
string | email: string & IsEmail |
IsURL |
string | link: string & IsURL |
StartsWith<S> |
string | id: string & StartsWith<"usr_"> |
EndsWith<S> |
string | file: string & EndsWith<".json"> |
MatchesRegexp<R> |
string | code: string & MatchesRegexp<"^[A-Z]{3}$"> |
Réponse d'erreur de validation
Les requêtes invalides retournent 400 avec les détails :
{
"code": "invalid_argument",
"message": "validation failed",
"details": { "field": "email", "error": "must be a valid email" }
}
Points de terminaison bruts
Utilisez api.raw pour les webhooks ou quand vous avez besoin d'un accès direct à la requête/réponse :
export const stripeWebhook = api.raw(
{ expose: true, path: "/webhooks/stripe", method: "POST" },
async (req, res) => {
const sig = req.headers["stripe-signature"];
// Gérer la requête brute...
res.writeHead(200);
res.end();
}
);
Gestion des erreurs
Utilisez APIError pour les réponses d'erreur HTTP appropriées :
import { APIError, ErrCode } from "encore.dev/api";
// Lever avec code d'erreur
throw new APIError(ErrCode.NotFound, "user not found");
// Ou utiliser la forme abrégée
throw APIError.notFound("user not found");
throw APIError.invalidArgument("email is required");
throw APIError.unauthenticated("invalid token");
Codes d'erreur courants
| Code | Statut HTTP | Utilisation |
|---|---|---|
NotFound |
404 | La ressource n'existe pas |
InvalidArgument |
400 | Mauvaise entrée |
Unauthenticated |
401 | Authentification manquante/invalide |
PermissionDenied |
403 | Non autorisé |
AlreadyExists |
409 | Ressource en doublon |
Actifs statiques
Servez des fichiers statiques (HTML, CSS, JS, images) avec api.static :
import { api } from "encore.dev/api";
// Servir les fichiers de ./assets sous /static/*
export const assets = api.static(
{ expose: true, path: "/static/*path", dir: "./assets" }
);
// Servir à la racine (utiliser !path pour le routage de secours)
export const frontend = api.static(
{ expose: true, path: "/!path", dir: "./dist" }
);
// Page 404 personnalisée
export const app = api.static(
{ expose: true, path: "/!path", dir: "./public", notFound: "./404.html" }
);
Syntaxe du chemin
*path- Wildcard standard : correspond à tous les chemins sous le préfixe (par ex.,/static/*path)!path- Routage de secours : sert les fichiers statiques à la racine du domaine sans confliter avec les autres points de terminaison API. Utilisez ceci pour les SPA où les routes non trouvées doivent servirindex.html
Directives
- Utilisez toujours
importet nonrequire - Définissez des interfaces explicites pour la sécurité des types
- Utilisez
expose: trueuniquement pour les points de terminaison publics - Utilisez
api.rawpour les webhooks,apipour tout le reste - Levez
APIErrorau lieu de retourner des objets d'erreur - Les paramètres de chemin sont automatiquement extraits du motif de chemin
- Utilisez des contraintes de validation (
Min,MaxLen, etc.) pour les entrées utilisateur