Attribute Macro salvo_oapi::endpoint
source · #[endpoint]Expand description
Enhanced of handler for generate OpenAPI documention.
Macro accepts set of attributes that can be used to configure and override default values what are resolved automatically.
You can use the Rust’s own #[deprecated] attribute on functions to mark it as deprecated and it will
reflect to the generated OpenAPI spec. Only parameters has a special deprecated attribute to define them as deprecated.
#[deprecated] attribute supports adding additional details such as a reason and or since version but this is not supported in
OpenAPI. OpenAPI has only a boolean flag to determine deprecation. While it is totally okay to declare deprecated with reason
#[deprecated = "There is better way to do this"] the reason would not render in OpenAPI spec.
Doc comment at decorated function will be used for description and summary of the path.
First line of the doc comment will be used as the summary and the whole doc comment will be
used as description.
/// This is a summary of the operation
///
/// All lines of the doc comment will be included to operation description.
#[salvo_oapi::endpoint()]
fn endpoint() {}§Endpoint Attributes
-
operation_id = ...Unique operation id for the endpoint. By default this is mapped to function name. The operation_id can be any “valid expression (e.g. string literals, macro invocations, variables) so long as its result can be converted to aStringusingString::from. -
tags(...)Can be used to group operations. Operations with same tag are grouped together. By default this is derived from the handler that is given toOpenApi. If derive results empty str then default valuecrateis used instead. -
request_body = ... | request_body(...)Defining request body indicates that the request is expecting request body within the performed request. -
status_codes(...)Filter responses with these status codes, if status code is not exists in this list, the response will ignored. -
responses(...)Slice of responses the endpoint is going to possibly return to the caller. -
parameters(...)Slice of parameters that the endpoint accepts. -
security(...)List ofSecurityRequirements local to the path operation.
§Request Body Attributes
Simple format definition by request_body = ...
request_body = Type,request_body = inline(Type)orrequest_body = ref("..."). The givenTypecan be any Rust type that is JSON parseable. It can be Option, Vec or Map etc. Withinline(...)the schema will be inlined instead of a referenced which is the default forToSchematypes.ref("./external.json")can be used to reference external json file for body schema.
Advanced format definition by request_body(...)
-
content = ...Can becontent = Type,content = inline(Type)orcontent = ref("..."). The givenTypecan be any Rust type that is JSON parseable. It can be Option, Vec or Map etc. Withinline(...)the schema will be inlined instead of a referenced which is the default forToSchematypes.ref("./external.json")can be used to reference external json file for body schema. -
description = "..."Define the description for the request body object as str. -
content_type = "..."Can be used to override the default behavior of auto resolving the content type from thecontentattribute. If defined the value should be valid content type such asapplication/json. By default the content type istext/plainfor primitive Rust types,application/octet-streamfor[u8]andapplication/jsonfor struct and complex enum types. -
example = ...Can bejson!(...).json!(...)should be something thatserde_json::json!can parse as aserde_json::Value. -
examples(...)Define multiple examples for single request body. This attribute is mutually exclusive to theexampleattribute and if both are defined this will override theexample. This has same syntax asexamples(...)in Response Attributes examples(…)
Example request body definitions.
request_body(content = String, description = "Xml as string request", content_type = "text/xml"),
request_body = Pet,
request_body = Option<[Pet]>,
§Response Attributes
-
status_code = ...Is either a valid http status code integer. E.g.200or a string value representing a range such as"4XX"or"default"or a validhttp::status::StatusCode.StatusCodecan either be use path to the status code or status code constant directly. -
description = "..."Define description for the response as str. -
body = ...Optional response body object type. When left empty response does not expect to send any response body. Can bebody = Type,body = inline(Type), orbody = ref("..."). The givenTypecan be any Rust type that is JSON parseable. It can be Option, Vec or Map etc. Withinline(...)the schema will be inlined instead of a referenced which is the default forToSchematypes.ref("./external.json")can be used to reference external json file for body schema. -
content_type = "..." | content_type = [...]Can be used to override the default behavior of auto resolving the content type from thebodyattribute. If defined the value should be valid content type such asapplication/json. By default the content type istext/plainfor primitive Rust types,application/octet-streamfor[u8]andapplication/jsonfor struct and complex enum types. Content type can also be slice of content_type values if the endpoint support returning multiple response content types. E.g["application/json", "text/xml"]would indicate that endpoint can return bothjsonandxmlformats. The order of the content types define the default example show first in the Swagger UI. Swagger UI will use the firstcontent_typevalue as a default example. -
headers(...)Slice of response headers that are returned back to a caller. -
example = ...Can bejson!(...).json!(...)should be something thatserde_json::json!can parse as aserde_json::Value. -
response = ...Type what implementsToResponsetrait. This can alternatively be used to define response attributes.responseattribute cannot co-exist with other thanstatus_codeattribute. -
content((...), (...))Can be used to define multiple return types for single response status code. Supported format for single content is(content_type = response_body, example = "...", examples(...)).exampleandexamplesare optional arguments. Examples attribute behaves exactly same way as in the response and is mutually exclusive with the example attribute. -
examples(...)Define multiple examples for single response. This attribute is mutually exclusive to theexampleattribute and if both are defined this will override theexample.name = ...This is first attribute and value must be literal string.summary = ...Short description of example. Value must be literal string.description = ...Long description of example. Attribute supports markdown for rich text representation. Value must be literal string.value = ...Example value. It must bejson!(...).json!(...)should be something thatserde_json::json!can parse as aserde_json::Value.external_value = ...Define URI to literal example value. This is mutually exclusive to thevalueattribute. Value must be literal string.
Example of example definition.
("John" = (summary = "This is John", value = json!({"name": "John"})))
Minimal response format:
responses(
(status_code = 200, description = "success response"),
(status_code = 404, description = "resource missing"),
(status_code = "5XX", description = "server error"),
(status_code = StatusCode::INTERNAL_SERVER_ERROR, description = "internal server error"),
(status_code = IM_A_TEAPOT, description = "happy easter")
)
More complete Response:
responses(
(status_code = 200, description = "Success response", body = Pet, content_type = "application/json",
headers(...),
example = json!({"id": 1, "name": "bob the cat"})
)
)
Response with multiple response content types:
responses(
(status_code = 200, description = "Success response", body = Pet, content_type = ["application/json", "text/xml"])
)
Multiple response return types with content(...) attribute:
Define multiple response return types for single response status code with their own example.
responses(
(status_code = 200, content(
("application/vnd.user.v1+json" = User, example = json!(User {id: "id".to_string()})),
("application/vnd.user.v2+json" = User2, example = json!(User2 {id: 2}))
)
)
)
§Using ToResponse for reusable responses
ReusableResponse must be a type that implements ToResponse.
responses(
(status_code = 200, response = ReusableResponse)
)
ToResponse can also be inlined to the responses map.
responses(
(status_code = 200, response = inline(ReusableResponse))
)
§Responses from ToResponses
Responses for a path can be specified with one or more types that implement
ToResponses.
responses(MyResponse)
§Response Header Attributes
-
nameName of the header. E.g.x-csrf-token -
typeAdditional type of the header value. Can beTypeorinline(Type). The givenTypecan be any Rust type that is JSON parseable. It can be Option, Vec or Map etc. Withinline(...)the schema will be inlined instead of a referenced which is the default forToSchematypes. Reminder! It’s up to the user to use valid type for the response header. -
description = "..."Can be used to define optional description for the response header as str.
Header supported formats:
("x-csrf-token"),
("x-csrf-token" = String, description = "New csrf token"),
§Params Attributes
The list of attributes inside the parameters(...) attribute can take two forms: Tuples or ToParameters
Type.
§Tuples
In the tuples format, parameters are specified using the following attributes inside a list of tuples separated by commas:
-
nameMust be the first argument. Define the name for parameter. -
parameter_typeDefine possible type for the parameter. Can beTypeorinline(Type). The givenTypecan be any Rust type that is JSON parseable. It can be Option, Vec or Map etc. Withinline(...)the schema will be inlined instead of a referenced which is the default forToSchematypes. Parameter type is placed afternamewith equals sign E.g."id" = String -
inMust be placed after name or parameter_type. Define the place of the parameter. This must be one of the variants ofparameter::ParameterIn. E.g.Path, Query, Header, Cookie -
deprecatedDefine whether the parameter is deprecated or not. Can optionally be defined with explicitboolvalue asdeprecated = bool. -
description = "..."Define possible description for the parameter as str. -
style = ...Defines how parameters are serialized byParameterStyle. Default values are based oninattribute. -
explodeDefines whether newparameter=valueis created for each parameter withinobjectorarray. -
allow_reservedDefines whether reserved characters:/?#[]@!$&'()*+,;=is allowed within value. -
example = ...Can method reference orjson!(...). Given example will override any example in underlying parameter type.
§Parameter type attributes
These attributes supported when parameter_type is present. Either by manually providing one
or otherwise resolved e.g from path macro argument when yaml crate feature is
enabled.
-
format = ...May either be variant of theKnownFormatenum, or otherwise an open value as a string. By default the format is derived from the type of the property according OpenApi spec. -
write_onlyDefines property is only used in write operations POST,PUT,PATCH but not in GET -
read_onlyDefines property is only used in read operations GET but not in POST,PUT,PATCH -
nullableDefines property is nullable (note this is different to non-required). -
multiple_of = ...Can be used to define multiplier for a value. Value is considered valid division will result aninteger. Value must be strictly above0. -
maximum = ...Can be used to define inclusive upper bound to anumbervalue. -
minimum = ...Can be used to define inclusive lower bound to anumbervalue. -
exclusive_maximum = ...Can be used to define exclusive upper bound to anumbervalue. -
exclusive_minimum = ...Can be used to define exclusive lower bound to anumbervalue. -
max_length = ...Can be used to define maximum length forstringtypes. -
min_length = ...Can be used to define minimum length forstringtypes. -
pattern = ...Can be used to define valid regular expression in ECMA-262 dialect the field value must match. -
max_items = ...Can be used to define maximum items allowed forarrayfields. Value must be non-negative integer. -
min_items = ...Can be used to define minimum items allowed forarrayfields. Value must be non-negative integer.
For example:
parameters(
("id" = String, Path, deprecated, description = "Pet database id"),
("name", Path, deprecated, description = "Pet name"),
(
"value" = inline(Option<[String]>),
Query,
description = "Value description",
style = Form,
allow_reserved,
deprecated,
explode,
example = json!(["Value"])),
max_length = 10,
min_items = 1
)
)
§ToParameters Type
In the ToParameters parameters format, the parameters are specified using an identifier for a type
that implements ToParameters. See ToParameters for an
example.
parameters(MyParameters)
Note! that MyParameters can also be used in combination with the tuples
representation or other structs.
parameters(
MyParameters1,
MyParameters2,
("id" = String, Path, deprecated, description = "Pet database id"),
)
More minimal example with the defaults.
#[salvo_oapi::endpoint(
request_body = Pet,
responses(
(status_code = 200, description = "Pet stored successfully", body = Pet,
headers(
("x-cache-len", description = "Cache length")
)
),
),
parameters(
("x-csrf-token", Header, description = "Current csrf token of user"),
)
)]
fn post_pet(res: &mut Response) {
res.render(Json(Pet {
id: 4,
name: "bob the cat".to_string(),
}));
}Use of Rust’s own #[deprecated] attribute will reflect to the generated OpenAPI spec and mark this operation as deprecated.
#[endpoint(
responses(
(status_code = 200, description = "Pet found from database")
),
parameters(
("id", description = "Pet id"),
)
)]
#[deprecated]
async fn get_pet_by_id(id: PathParam<i32>, res: &mut Response) {
let json = json!({ "pet": format!("{:?}", id.into_inner())});
res.render(Json(json))
}Example with multiple return types
#[salvo_oapi::endpoint(
responses(
(status_code = 200, content(
("application/vnd.user.v1+json" = User1, example = json!({"id": "id".to_string()})),
("application/vnd.user.v2+json" = User2, example = json!({"id": 2}))
)
)
)
)]
async fn get_user() {
}Example with multiple examples on single response.
#[salvo_oapi::endpoint(
responses(
(status_code = 200, body = User,
examples(
("Demo" = (summary = "This is summary", description = "Long description",
value = json!(User{name: "Demo".to_string()}))),
("John" = (summary = "Another user", value = json!({"name": "John"})))
)
)
)
)]
async fn get_user() -> Json<User> {
Json(User {name: "John".to_string()})
}Enhanced of handler for generate OpenAPI documention, Read more.