Chopper handles paths passed to HTTP verb annotations' path parameter based on the path's content.
If the path value is a relative path, it will be concatenated to the URL composed of the baseUrl of the ChopperClient and the baseUrl of the enclosing service class (provided as a parameter of the @ChopperApi annotation).
Here are a few examples of the described behavior:
-
ChopperClientbase URL: https://example.com/
Path: profile
Result: https://example.com/profile -
ChopperClientbase URL: https://example.com/
Service base URL: profile
Path: /image
Result: https://example.com/profile/image -
ChopperClientbase URL: https://example.com/
Service base URL: profile
Path: image
Result: https://example.com/profile/image
Chopper detects and handles missing slash (
/) characters on URL segment borders, but does not handle duplicate slashes.
If the service's baseUrl concatenated with the request's path results in a full URL, the ChopperClient's baseUrl is ignored.
ChopperClientbase URL: https://example.com/
Service base URL: https://api.github.com/
Path: user
Result: https://api.github.com/user
A path containing a full URL replaces the base URLs of both the ChopperClient and the service class entirely for a request.
-
ChopperClientbase URL: https://example.com/
Path: https://api.github.com/user
Result: https://api.github.com/user -
ChopperClientbase URL: https://example.com/
Service base URL: profile
Path: https://api.github.com/user
Result: https://api.github.com/user
Dynamic path parameters can be defined in the URL with replacement blocks. A replacement block is an alphanumeric substring of the path surrounded by { and }. In the following example {id} is a replacement block.
@Get(path: "/{id}")Use the @Path() annotation to bind a parameter to a replacement block. This way the parameter's name must match a replacement block's string.
@Get(path: "/{id}")
Future<Response> getItemById(@Path() String id);As an alternative, you can set the @Path annotation's name parameter to match a replacement block's string while using a different parameter name, like in the following example:
@Get(path: "/{id}")
Future<Response> getItemById(@Path("id") int itemId);Chopper uses String interpolation to replace replacement blocks with the provided values in the request URLs.
Dynamic query parameters can be added to the URL by adding parameters to a request method annotated with the @Query annotation. Default values are supported.
Future<Response> search(
@Query() String name, {
@Query("count") int numberOfResults = 42,
});If the parameter of the @Query annotation is not set, Chopper will use the actual name of the annotated parameter as the key for the query parameter in the URL.
If you prefer to pass a Map of query parameters, you can do so with the @QueryMap annotation.
Future<Response> search(@QueryMap() Map<String, dynamic> query);Use the @Body annotation on a request method parameter to specify data that will be sent as the request's body.
@Post(path: "todo/create")
Future<Response> postData(@Body() String data);{% hint style="warning" %}
Chopper does not automatically convert Objects to Mapthen JSON.
You have to pass a Converter instance to a ChopperClient for JSON conversion to happen. See built_value_converter for an example Converter implementation.
{% endhint %}
Request headers can be set by providing a Map<String, String> object to the headers parameter each of the HTTP verb annotations have.
@Get(path: "/", headers: {"foo": "bar"})
Future<Response> fetch();The @Header annotation can be used on method parameters to set headers dynamically for each request call.
@Get(path: "/")
Future<Response> fetch(@Header("foo") String bar);Setting request headers dynamically is also supported by Interceptors and Converters.
As Chopper invokes Interceptors and Converter(s) after creating a Request, Interceptors and Converters can override headers set with the
headersparameter or@Headerannotations.
If no Converter is specified for a request (neither on a ChopperClient nor with the @FactoryConverter annotation) and the request body is of type Map<String, String>, the body will be sent as form URL encoded data.
This is the default behavior of the http package.
You can also use FormUrlEncodedConverter that will add the correct content-type and convert a Map into Map<String, String> for requests.
final chopper = ChopperClient(
converter: FormUrlEncodedConverter(),
);To do only a single type of request with form encoding in a service, use the provided FormUrlEncodedConverter's requestFactory method with the @FactoryConverter annotation.
@Post(
path: "form",
headers: {contentTypeKey: formEncodedHeaders},
)
@FactoryConverter(
request: FormUrlEncodedConverter.requestFactory,
)
Future<Response> postForm(@Body() Map<String, String> fields);To specify fields individually, use the @Field annotation on method parameters. If the field's name is not provided, the parameter's name is used as the field's name.
@Post(path: "form")
@FactoryConverter(
request: FormUrlEncodedConverter.requestFactory,
)
Future<Response> post(@Field() String foo, @Field("b") int bar);