Response response;
var dio =Dio();
response =await dio.get('/test?id=12&name=wendu');
print(response.data.toString());
// Optionally the request above could also be done as
response =await dio.get('/test', queryParameters: {'id':12, 'name':'wendu'});
print(response.data.toString());
You can create instance of Dio with an optional BaseOptions object:
var dio =Dio(); // with default Options// Set default configs
dio.options.baseUrl ='https://www.xx.com/api';
dio.options.connectTimeout =5000; //5s
dio.options.receiveTimeout =3000;
// or new Dio with a BaseOptions instance.var options =BaseOptions(
baseUrl:'https://www.xx.com/api',
connectTimeout:5000,
receiveTimeout:3000,
);
Dio dio =Dio(options);
For convenience aliases have been provided for all supported request methods.
Future get(…)
Future post(…)
Future put(…)
Future delete(…)
Future head(…)
Future put(…)
Future path(…)
Future download(…)
Future fetch(RequestOptions) new*
Request Options
The Options class describes the http request information and configuration. Each Dio instance has a base config for all requests maked by itself, and we can override the base config with [Options] when make a single request. The [BaseOptions] declaration as follows:
/// Request base url, it can contain sub path, like: 'https://www.google.com/api/'.
String baseUrl;
/// Http request headers.
Map headers;
/// Timeout in milliseconds for opening url.
int connectTimeout;
/// Whenever more than [receiveTimeout] (in milliseconds) passes between two events from response stream,
/// [Dio] will throw the [DioError] with [DioErrorType.RECEIVE_TIMEOUT].
/// Note: This is not the receiving time limitation.
int receiveTimeout;
/// Request data, can be any type.
T data;
/// If the `path` starts with ‘http(s)’, the `baseURL` will be ignored, otherwise,
/// it will be combined and then resolved with the baseUrl.
String path=”;
/// The request Content-Type. The default value is ‘application/json; charset=utf-8’.
/// If you want to encode request body with ‘application/x-www-form-urlencoded’,
/// you can set [Headers.formUrlEncodedContentType], and [Dio]
/// will automatically encode the request body.
String contentType;
/// [responseType] indicates the type of data that the server will respond with
/// options which defined in [ResponseType] are `JSON`, `STREAM`, `PLAIN`.
///
/// The default value is `JSON`, dio will parse response string to json object automatically
/// when the content-type of response is ‘application/json’.
///
/// If you want to receive response data with binary bytes, for example,
/// downloading a image, use `STREAM`.
///
/// If you want to receive the response data with String, use `PLAIN`.
ResponseType responseType;
/// `validateStatus` defines whether the request is successful for a given
/// HTTP response status code. If `validateStatus` returns `true` ,
/// the request will be perceived as successful; otherwise, considered as failed.
ValidateStatus validateStatus;
/// Custom field that you can retrieve it later in [Interceptor]、[Transformer] and the [Response] object.
Map extra;
/// Common query parameters
Map<String, dynamic /*String|Iterable*/ > queryParameters;
/// [collectionFormat] indicates the format of collection data in request
/// options which defined in [CollectionFormat] are `csv`, `ssv`, `tsv`, `pipes`, `multi`,`multiCompatible`.
/// The default value is `multiCompatible`
late CollectionFormat collectionFormat;
}
“>
{
/// Http method.String method;
/// Request base url, it can contain sub path, like: 'https://www.google.com/api/'.String baseUrl;
/// Http request headers.Map<String, dynamic> headers;
/// Timeout in milliseconds for opening url.int connectTimeout;
/// Whenever more than [receiveTimeout] (in milliseconds) passes between two events from response stream, /// [Dio] will throw the [DioError] with [DioErrorType.RECEIVE_TIMEOUT]. /// Note: This is not the receiving time limitation.int receiveTimeout;
/// Request data, can be any type.T data;
/// If the `path` starts with 'http(s)', the `baseURL` will be ignored, otherwise, /// it will be combined and then resolved with the baseUrl.String path='';
/// The request Content-Type. The default value is 'application/json; charset=utf-8'. /// If you want to encode request body with 'application/x-www-form-urlencoded', /// you can set [Headers.formUrlEncodedContentType], and [Dio] /// will automatically encode the request body.String contentType;
/// [responseType] indicates the type of data that the server will respond with /// options which defined in [ResponseType] are `JSON`, `STREAM`, `PLAIN`. /// /// The default value is `JSON`, dio will parse response string to json object automatically /// when the content-type of response is 'application/json'. /// /// If you want to receive response data with binary bytes, for example, /// downloading a image, use `STREAM`. /// /// If you want to receive the response data with String, use `PLAIN`.ResponseType responseType;
/// `validateStatus` defines whether the request is successful for a given /// HTTP response status code. If `validateStatus` returns `true` , /// the request will be perceived as successful; otherwise, considered as failed.ValidateStatus validateStatus;
/// Custom field that you can retrieve it later in [Interceptor]、[Transformer] and the [Response] object.Map<String, dynamic> extra;
/// Common query parametersMap<String, dynamic/*String|Iterable<String>*/> queryParameters;
/// [collectionFormat] indicates the format of collection data in request /// options which defined in [CollectionFormat] are `csv`, `ssv`, `tsv`, `pipes`, `multi`,`multiCompatible`. /// The default value is `multiCompatible`lateCollectionFormat collectionFormat;
}
The response for a request contains the following information.
<div class="highlight highlight-source-dart position-relative" data-snippet-clipboard-copy-content="{
/// Response body. may have been transformed, please refer to [ResponseType].
T? data;
/// Response headers.
Headers headers;
/// The corresponding request info.
RequestOptions requestOptions;
/// Http status code.
int? statusCode;
String? statusMessage;
/// Whether redirect
bool? isRedirect;
/// redirect info
List redirects ;
/// Returns the final real request uri (maybe redirect).
Uri realUri;
/// Custom field that you can retrieve it later in `then`.
Map extra;
}
“>
{
/// Response body. may have been transformed, please refer to [ResponseType].T? data;
/// Response headers.Headers headers;
/// The corresponding request info.RequestOptions requestOptions;
/// Http status code.int? statusCode;
String? statusMessage;
/// Whether redirect bool? isRedirect;
/// redirect info List<RedirectInfo> redirects ;
/// Returns the final real request uri (maybe redirect). Uri realUri;
/// Custom field that you can retrieve it later in `then`.Map<String, dynamic> extra;
}
When request is succeed, you will receive the response as follows:
For each dio instance, We can add one or more interceptors, by which we can intercept requests 、 responses and errors before they are handled by then or catchError.
dio.interceptors.add(InterceptorsWrapper(
onRequest:(options, handler){
// Do something before request is sentreturn handler.next(options); //continue// If you want to resolve the request with some custom data,// you can resolve a `Response` object eg: `handler.resolve(response)`.// If you want to reject the request with a error message,// you can reject a `DioError` object eg: `handler.reject(dioError)`
},
onResponse:(response,handler) {
// Do something with response datareturn handler.next(response); // continue// If you want to reject the request with a error message,// you can reject a `DioError` object eg: `handler.reject(dioError)`
},
onError: (DioError e, handler) {
// Do something with response errorreturn handler.next(e);//continue// If you want to resolve the request with some custom data,// you can resolve a `Response` object eg: `handler.resolve(response)`.
}
));
In all interceptors, you can interfere with their execution flow. If you want to resolve the request/response with some custom data,you can call handler.resolve(Response). If you want to reject the request/response with a error message, you can call handler.reject(dioError) .
You can lock/unlock the interceptors by calling their lock()/unlock method. Once the request/response interceptor is locked, the incoming request/response will be added to a queue before they enter the interceptor, they will not be continued until the interceptor is unlocked.
dio.interceptors.requestLock.unlock());
}
));
“>
tokenDio =Dio(); //Create a new instance to request the token.
tokenDio.options = dio.options.copyWith();
dio.interceptors.add(InterceptorsWrapper(
onRequest:(Options options, handler){
// If no token, request token firstly and lock this interceptor// to prevent other request enter this interceptor.
dio.interceptors.requestLock.lock();
// We use a new Dio(to avoid dead lock) instance to request token.
tokenDio.get('/token').then((response){
//Set the token to headers
options.headers['token'] = response.data['data']['token'];
handler.next(options); //continue
}).catchError((error, stackTrace) {
handler.reject(error, true);
}).whenComplete(() => dio.interceptors.requestLock.unlock());
}
));
You can clean the waiting queue by calling clear();
aliases
When the request interceptor is locked, the incoming request will pause, this is equivalent to we locked the current dio instance, Therefore, Dio provied the two aliases for the lock/unlock of request interceptors.
Because of security reasons, we need all the requests to set up a csrfToken in the header, if csrfToken does not exist, we need to request a csrfToken first, and then perform the network request, because the request csrfToken progress is asynchronous, so we need to execute this async request in request interceptor. The code is as follows:
dio.unlock()); // unlock the dio
} else {
options.headers[‘csrfToken’] = csrfToken;
handler.next(options);
}
}
));
“>
When a error occurs, Dio will wrap the Error/Exception to a DioError:
try {
//404await dio.get('https://wendux.github.io/xsddddd');
} onDioErrorcatch (e) {
// The request was made and the server responded with a status code// that falls out of the range of 2xx and is also not 304.if (e.response) {
print(e.response.data)
print(e.response.headers)
print(e.response.requestOptions)
} else {
// Something happened in setting up or sending the request that triggered an Errorprint(e.requestOptions)
print(e.message)
}
}
DioError scheme
{
/// Response info, it may be `null` if the request can't reach to /// the http server, for example, occurring a dns error, network is not available.Response? response;
/// Request info.RequestOptions? requestOptions;
/// Error descriptions.String message;
DioErrorType type;
/// The original error/exception object; It's usually not null when `type` /// is DioErrorType.DEFAULTdynamic? error;
}
DioErrorType
enumDioErrorType {
/// It occurs when url is opened timeout.
connectTimeout,
/// It occurs when url is sent timeout.
sendTimeout,
///It occurs when receiving timeout.
receiveTimeout,
/// When the server response, but with a incorrect status, such as 404, 503...
response,
/// When the request is cancelled, dio will throw a error with this type.
cancel,
/// Default error type, Some other Error. In this case, you can /// use the DioError.error if it is not null.
other,
}
Using application/x-www-form-urlencoded format
By default, Dio serializes request data(except String type) to JSON. To send data in the application/x-www-form-urlencoded format instead, you can :
//Instance level
dio.options.contentType=Headers.formUrlEncodedContentType;
//or works once
dio.post(
'/info',
data: {'id':5},
options:Options(contentType:Headers.formUrlEncodedContentType),
);
Sending FormData
You can also send FormData with Dio, which will send data in the multipart/form-data, and it supports uploading files.
The upload key eventually becomes ‘files[]’,This is because many back-end services add a middle bracket to key when they get an array of files. If you don’t want “[]”,you should create FormData as follows(Don’t use FormData.fromMap):
Transformer allows changes to the request/response data before it is sent/received to/from the server. This is only applicable for request methods ‘PUT’, ‘POST’, and ‘PATCH’. Dio has already implemented a DefaultTransformer, and as the default Transformer. If you want to customize the transformation of request/response data, you can provide a Transformer by your self, and replace the DefaultTransformer by setting the dio.transformer.
In flutter
If you use dio in flutter development, you’d better to decode json in background with [compute] function.
HttpClientAdapter is a bridge between Dio and HttpClient.
Dio implements standard and friendly API for developer.
HttpClient: It is the real object that makes Http requests.
We can use any HttpClient not just dart:io:HttpClient to make the Http request. And all we need is providing a HttpClientAdapter. The default HttpClientAdapter for Dio is DefaultHttpClientAdapter.
DefaultHttpClientAdapter provide a callback to set proxy to dart:io:HttpClient, for example:
import'package:dio_http/dio_http.dart';
import'package:dio_http/adapter.dart';
...
(dio.httpClientAdapter asDefaultHttpClientAdapter).onHttpClientCreate = (client) {
// config the http client
client.findProxy = (uri) {
//proxy all request to localhost:8888return'PROXY localhost:8888';
};
// you can also create a new HttpClient to dio// return HttpClient();
};
Another way is creating a SecurityContext when create the HttpClient:
(dio.httpClientAdapter asDefaultHttpClientAdapter).onHttpClientCreate = (client) {
SecurityContext sc =SecurityContext();
//file is the path of certificate
sc.setTrustedCertificates(file);
HttpClient httpClient =HttpClient(context: sc);
return httpClient;
};
In this way, the format of certificate must be PEM or PKCS12.
Http2 support
dio_http2_adapter package is a Dio HttpClientAdapter which support Http/2.0 .
Cancellation
You can cancel a request using a cancel token. One token can be shared with multiple requests. When a token’s cancel method invoked, all requests with this token will be cancelled.
CancelToken token =CancelToken();
dio.get(url, cancelToken: token)
.catchError((DioError err){
if (CancelToken.isCancel(err)) {
print('Request canceled! '+ err.message)
}else{
// handle error.
}
});
// cancel the requests with "cancelled" message.
token.cancel('cancelled');
Dio is a abstract class with factory constructor,so we don’t extend Dio class directy. For this purpose, we can extend DioForNative or DioForBrowser instead, for example:
import'package:dio_http/dio_http.dart';
import'package:dio_http/native_imp.dart'; //If in browser, import 'package:dio_http/browser_imp.dart'classHttpextendsDioForNative {
Http([BaseOptions options]):super(options){
// do something
}
}
We can also implement our Dio client:
classMyDiowithDioMixinimplementsDio{
// ...
}
Features and bugs
Please file feature requests and bugs at the issue tracker.