Controllers are the core building blocks of the Interface API. They group route handlers under a shared base path and provide a structured way to organize HTTP endpoints.
The Controller function creates a controller class bound to a root location path.
import { Controller } from "@antelopejs/interface-api";
class MyController extends Controller("/api") {
// Route handlers go here
}Controllers support hierarchical nesting through the extend method. Each sub-controller inherits its parent's path prefix.
import { Controller } from "@antelopejs/interface-api";
// Handles routes at /api
class ApiController extends Controller("/api") {
// API methods
}
// Handles routes at /api/users
class UsersController extends ApiController.extend("users") {
// User-specific methods
}The PartialController function creates a controller that shares the same location as an existing controller. This is useful when you want to split routes across multiple files while sharing the same controller context and computed properties.
import { Controller, PartialController, Get } from "@antelopejs/interface-api";
// Original controller
class UsersController extends Controller("/users") {
@Get()
async listUsers() {
return { users: [] };
}
}
// Partial controller at the same /users path
class UsersAdminController extends PartialController(UsersController) {
@Get("admin")
async listAdminUsers() {
return { admins: [] };
}
}Each HTTP request creates a new controller instance. The GetControllerInstance function retrieves a controller instance for the current request context, which is useful for reusing functionality across controllers.
import {
GetControllerInstance,
Controller,
Get,
RequestContext,
Context,
} from "@antelopejs/interface-api";
class UserController extends Controller("/users") {
async fetchUser(id: string) {
// Shared logic
return { id, name: "Example User" };
}
}
class OrderController extends Controller("/orders") {
@Get(":id")
async getOrder(@Context() context: RequestContext) {
// Reuse UserController logic within the current request
const userCtrl = await GetControllerInstance(UserController, context);
const user = await userCtrl.fetchUser("user-123");
return { order: { id: "order-1", user } };
}
}The function ensures that computed properties and injected parameters are properly initialized before returning the instance.
Controllers contain methods decorated with HTTP method decorators that define route handlers.
import { Controller, Get, Post, Delete, HTTPResult } from "@antelopejs/interface-api";
class UsersController extends Controller("/users") {
@Get()
async listUsers() {
return { users: ["user1", "user2"] };
}
@Get(":id")
async getUser() {
return { id: "user123", name: "Sample User" };
}
@Post()
async createUser() {
return new HTTPResult(201, { id: "new-user-id", name: "New User" });
}
@Delete(":id")
async deleteUser() {
return new HTTPResult(204);
}
}The API supports different handler modes that control when and how a method executes.
Prefix handlers run before the main handler. They are ideal for authentication, validation, and request preprocessing. If a prefix handler returns a value, that value becomes the response and the main handler is skipped.
import { Controller, Get, Prefix, HTTPResult } from "@antelopejs/interface-api";
class UsersController extends Controller("/users") {
@Prefix("get", ":id")
async validateUserExists() {
const userExists = true; // Check database
if (!userExists) {
return new HTTPResult(404, { error: "User not found" });
}
// Returning nothing allows execution to continue to the main handler
}
@Get(":id")
async getUser() {
return { id: "user123", name: "Sample User" };
}
}Postfix handlers run after the main handler completes. They are useful for response modification, logging, and cleanup.
Warning: If a postfix handler returns a value, all subsequent postfix handlers are skipped.
import { Controller, Get, Postfix, Result, HTTPResult } from "@antelopejs/interface-api";
class UsersController extends Controller("/users") {
@Get(":id")
async getUser() {
return { id: "user123", name: "Sample User" };
}
@Postfix("get", ":id")
async logUserAccess(@Result() result: HTTPResult) {
result.addHeader("X-Accessed-At", new Date().toISOString());
}
}Monitor handlers run after request processing completes, regardless of success or failure. Their return value is ignored. Use them for logging, metrics, or other observation tasks.
import { Controller, Get, Monitor, Context, RequestContext } from "@antelopejs/interface-api";
class UsersController extends Controller("/users") {
@Get(":id")
async getUser() {
return { id: "user123", name: "Sample User" };
}
@Monitor("get", ":id")
async logRequest(@Context() ctx: RequestContext) {
const status = ctx.response.getStatus();
const message = ctx.error ? String(ctx.error) : "ok";
console.log(`GET /users/:id -> ${status} (${message})`);
}
}WebSocket handlers manage persistent connections using the @WebsocketHandler decorator.
import { Controller, WebsocketHandler, Connection } from "@antelopejs/interface-api";
class ChatController extends Controller("/chat") {
@WebsocketHandler()
async handleChat(@Connection() connection: any) {
connection.on("message", (data: string) => {
connection.send("Echo: " + data);
});
connection.on("close", () => {
console.log("Connection closed");
});
}
}Handlers can be assigned priorities to control execution order. This is especially useful when multiple prefix or postfix handlers match the same route.
import { Controller, Prefix, HandlerPriority, HTTPResult } from "@antelopejs/interface-api";
class SecuredController extends Controller("/api") {
@Prefix("get", "*", HandlerPriority.HIGHEST)
async checkAuthentication() {
const isAuthenticated = true;
if (!isAuthenticated) {
return new HTTPResult(401, { error: "Unauthorized" });
}
}
@Prefix("get", "*", HandlerPriority.HIGH)
async checkAuthorization() {
const isAuthorized = true;
if (!isAuthorized) {
return new HTTPResult(403, { error: "Forbidden" });
}
}
}The available priority levels are:
| Priority | Value | Description |
|---|---|---|
HandlerPriority.HIGHEST |
0 | Executes first |
HandlerPriority.HIGH |
1 | High priority |
HandlerPriority.NORMAL |
2 | Default priority |
HandlerPriority.LOW |
3 | Low priority |
HandlerPriority.LOWEST |
4 | Executes last |
The Listen function starts listening on all configured servers.
import { Listen } from "@antelopejs/interface-api";
await Listen();