LogoRevali

HTTP Methods

Method annotations that turn controller methods into endpoints, and the route path syntax

A method annotation (@Get, @Post, ...) turns a controller method into an endpoint for that HTTP method. Its optional path argument is appended to the controller path.

Minimal example#

routes/controllers/status_controller.dart
import 'package:revali_router/revali_router.dart';

@Controller('status')
class StatusController {
  const StatusController();

  @Get()
  String status() => 'ok';

  @Get('version')
  String version() => '1.2.0';
}
curl http://localhost:8080/api/status
# {"data":"ok"}

curl http://localhost:8080/api/status/version
# {"data":"1.2.0"}

Method annotations#

AnnotationHTTP methodDocs
@Get([path])GET
@Post([path])POST
@Put([path])PUT
@Patch([path])PATCH
@Delete([path])DELETE
@Head([path]) HEAD HEAD requests
@SSE([path]) GET, response kept open and streamed Server-Sent Events
@WebSocket(path) WebSocket (a GET upgrade request) WebSockets
  • One method annotation per method. A second one fails the build.
  • The method name is never part of the URL.
  • HEAD and OPTIONS are answered automatically for every route; you rarely need @Head. See HEAD and OPTIONS.

Path syntax#

SegmentMeaningExample pathMatches
name Literal segment version /api/status/version
:name One dynamic segment, bound with @Param() :id /api/users/42
*name All remaining segments, bound with @Param() List<String> name files/*path /api/files/a/b.txt
  • Do not start or end a path with / (@Get('version'), not @Get('/version')); the router rejects it at startup. Nested paths use inner slashes: @Get('a/b').
  • Allowed characters: letters, digits, -, _, ., plus : and * at the start of a segment.
  • Controller paths can contain parameters too: @Controller('shops/:shopId') makes shopId available to every endpoint in the controller.
  • A path parameter is always required. A request missing the segment matches no route and gets 404.

Path parameters#

@Controller('shops/:shopId')
class ProductsController {
  const ProductsController();

  @Get('products/:productId')
  Map<String, String> product(
    @Param() String shopId,
    @Param() String productId,
  ) {
    return {'shopId': shopId, 'productId': productId};
  }
}
curl http://localhost:8080/api/shops/abc/products/xyz
# {"data":{"shopId":"abc","productId":"xyz"}}

Path parameter values are Strings. To get another type, transform the value with a pipe. Binding details are on the Binding page.

Custom HTTP methods#

Extend Method to serve a verb Revali does not ship an annotation for:

import 'package:revali_router/revali_router.dart';

final class Purge extends Method {
  const Purge([String? path]) : super('PURGE', path: path);
}

@Controller('cache')
class CacheController {
  const CacheController();

  @Purge()
  String purge() => 'purged';
}
curl -X PURGE http://localhost:8080/api/cache
# {"data":"purged"}

Next: Binding · Response