Response annotations
By default the success response is derived from the method’s return type and the verb’s
statusCode, and 400/401/403 are added when they apply
(details). Use the
annotations here to override the success response or add others.
Returns
Section titled “Returns”Overrides the success response’s status, description or body schema. Also the element type of
the responses: list on verb annotations and of Responses.
@Target({TargetKind.method})class Returns { const Returns({ this.statusCode, this.description, this.contentType = 'application/json', this.bodyType, });}When to use: when the method returns a raw Response (so the generator cannot see the body
type), or when you want a different status code or description in the document. For extra,
non-success responses use ApiResponse.
| Parameter | Type | Default | Description |
|---|---|---|---|
statusCode |
int? |
null |
Success status. When null, the verb’s statusCode is used. Overrides the runtime status too when the method returns a value or void. |
description |
String? |
null |
Response description. Defaults to the reason phrase (OK, Created, …). |
contentType |
String |
'application/json' |
Currently not used; responses are documented as application/json. |
bodyType |
Type? |
null |
Schema for the body. Only used when the method returns Response; otherwise the return type is used. |
In a list (inline responses: or Responses) the first entry is the success
response and each later entry with a statusCode is added as another response. Entries after
the first without a statusCode are ignored. Standalone @Returns/@Responses annotations win
over the inline responses: list; if several are stacked, their entries are combined in order.
Example
import 'package:gisila_doc/gisila_doc.dart';
@Get('/me')@Returns(bodyType: UserResponse, description: 'The signed-in user')Future<Response> me(Request request) async { /* ... */ }
@Post( '/register', summary: 'Register a new account', body: BodyDoc(UserRegisterRequest), responses: [ Returns(statusCode: 201, bodyType: UserResponse), Returns(statusCode: 409, bodyType: ErrorResponse, description: 'Email taken'), ],)Future<Response> register(Request request) async { /* ... */ }ApiResponse
Section titled “ApiResponse”Adds one more response entry to an operation.
@Target({TargetKind.method})class ApiResponse { const ApiResponse( this.statusCode, { this.description, this.contentType = 'application/json', this.bodyType, });}When to use: to document error and alternative responses (404, 409, 422, …). Stack
as many as you need. Declaring 400, 401 or 403 yourself replaces the automatic entry for
that code.
| Parameter | Type | Default | Description |
|---|---|---|---|
statusCode |
int |
required | Status code. Positional. |
description |
String? |
null |
Defaults to the reason phrase (Not Found, Conflict, …; Status <code> for others). |
contentType |
String |
'application/json' |
Currently not used; a body is documented as application/json. |
bodyType |
Type? |
null |
Body schema. Without it the response has no content. |
Example
@Get('/{id}', summary: 'Fetch a user')@ApiResponse(404, description: 'User not found')@ApiResponse(410, description: 'User was deleted', bodyType: Tombstone)Future<User> getUser(String id, UserService users) => users.getById(id);The automatic 400/401/403 entries use gisila’s error body,
errorEnvelopeSchema. ApiResponse
takes a Dart type, not a schema map, so to document the same body on your own error responses
point bodyType at a class with the same shape (error: {status, message, code, details}).
Responses
Section titled “Responses”Declares a list of Returns entries in one annotation.
@Target({TargetKind.method})class Responses { const Responses(this.responses); final List<Returns> responses;}When to use: when the inline responses: list makes the verb annotation hard to read, or
when you want to reuse a const response list across routes. Behaves exactly like the inline
list.
Example
const crudResponses = Responses([ Returns(statusCode: 200, bodyType: Product), Returns(statusCode: 404, description: 'No such product'),]);
@Get('/{id}')@crudResponsesFuture<Response> getProduct(String id, Request request) async { /* ... */ }Intended to add an extra tag to a single operation.
@Target({TargetKind.method})class Tag { const Tag(this.name, [this.description]);}@Get('/stats', tags: ['Reporting'])Future<Stats> stats(StatsService s) => s.current();
// at startupspec.putTag('Reporting', description: 'Aggregated numbers');