Viewing version 5.4.3+1. Open the latest package page.

dio

5.4.3+1

A powerful HTTP networking package, supports Interceptors, Aborting and canceling a request, Custom adapters, Transformers, etc.

Download archive

Readme

dio

Pub Dev

Language: English | 简体中文

A powerful HTTP networking package for Dart/Flutter, supports Global configuration, Interceptors, FormData, Request cancellation, File uploading/downloading, Timeout, Custom adapters, Transformers, etc.

Don't forget to add #dio topic to your published dio related packages! See more: https://dart.dev/tools/pub/pubspec#topics

Get started

Install

Add the dio package to your pubspec dependencies.

Before you upgrade: Breaking changes might happen in major and minor versions of packages. See the Migration Guide for the complete breaking changes list.

Super simple to use

import 'package:dio/dio.dart';

final dio = Dio();

void getHttp() async {
  final response = await dio.get('https://dart.dev');
  print(response);
}

Awesome dio

🎉 A curated list of awesome things related to dio.

Plugins

Plugins

Welcome to submit third-party plugins and related libraries in here.

Examples

Performing a GET request:

import 'package:dio/dio.dart';

final dio = Dio();

void request() async {
  Response response;
  response = await dio.get('/test?id=12&name=dio');
  print(response.data.toString());
  // The below request is the same as above.
  response = await dio.get(
    '/test',
    queryParameters: {'id': 12, 'name': 'dio'},
  );
  print(response.data.toString());
}

Performing a POST request:

response = await dio.post('/test', data: {'id': 12, 'name': 'dio'});

Performing multiple concurrent requests:

response = await Future.wait([dio.post('/info'), dio.get('/token')]);

Downloading a file:

response = await dio.download(
  'https://pub.dev/',
  (await getTemporaryDirectory()).path + 'pub.html',
);

Get response stream:

final rs = await dio.get(
  url,
  options: Options(responseType: ResponseType.stream), // Set the response type to `stream`.
);
print(rs.data.stream); // Response stream.

Get response with bytes:

final rs = await Dio().get<List<int>>(
  url,
  options: Options(responseType: ResponseType.bytes), // Set the response type to `bytes`.
);
print(rs.data); // Type: List<int>.

Sending a FormData:

final formData = FormData.fromMap({
  'name': 'dio',
  'date': DateTime.now().toIso8601String(),
});
final response = await dio.post('/info', data: formData);

Uploading multiple files to server by FormData:

final formData = FormData.fromMap({
  'name': 'dio',
  'date': DateTime.now().toIso8601String(),
  'file': await MultipartFile.fromFile('./text.txt', filename: 'upload.txt'),
  'files': [
    await MultipartFile.fromFile('./text1.txt', filename: 'text1.txt'),
    await MultipartFile.fromFile('./text2.txt', filename: 'text2.txt'),
  ]
});
final response = await dio.post('/info', data: formData);

Listening the uploading progress:

final response = await dio.post(
  'https://www.dtworkroom.com/doris/1/2.0.0/test',
  data: {'aa': 'bb' * 22},
  onSendProgress: (int sent, int total) {
    print('$sent $total');
  },
);

Post binary data with Stream:

// Binary data
final postData = <int>[0, 1, 2];
await dio.post(
  url,
  data: Stream.fromIterable(postData.map((e) => [e])), // Creates a Stream<List<int>>.
  options: Options(
    headers: {
      Headers.contentLengthHeader: postData.length, // Set the content-length.
    },
  ),
);

Note: content-length must be set if you want to subscribe to the sending progress.

See all examples code here.

Dio APIs

Creating an instance and set default configs.

It is recommended to use a singleton of Dio in projects, which can manage configurations like headers, base urls, and timeouts consistently. Here is an example that use a singleton in Flutter.

You can create instance of Dio with an optional BaseOptions object:

final dio = Dio(); // With default `Options`.

void configureDio() {
  // Set default configs
  dio.options.baseUrl = 'https://api.pub.dev';
  dio.options.connectTimeout = Duration(seconds: 5);
  dio.options.receiveTimeout = Duration(seconds: 3);

  // Or create `Dio` with a `BaseOptions` instance.
  final options = BaseOptions(
    baseUrl: 'https://api.pub.dev',
    connectTimeout: Duration(seconds: 5),
    receiveTimeout: Duration(seconds: 3),
  );
  final anotherDio = Dio(options);
}

The core API in Dio instance is:

Future<Response<T>> request<T>(
  String path, {
  Object? data,
  Map<String, dynamic>? queryParameters,
  CancelToken? cancelToken,
  Options? options,
  ProgressCallback? onSendProgress,
  ProgressCallback? onReceiveProgress,
});
final response = await dio.request(
  '/test',
  data: {'id': 12, 'name': 'dio'},
  options: Options(method: 'GET'),
);

Request Options

The Options class describes the HTTP request information and configuration. Each Dio instance has a base config for all requests made by itself, and we can override the base config with Options when make a single request. The Options declaration as follows:

/// The HTTP request method.
String method;

/// Timeout when sending data.
///
/// Throws the [DioException] with
/// [DioExceptionType.sendTimeout] type when timed out.
///
/// `null` or `Duration.zero` means no timeout limit.
Duration? sendTimeout;

/// Timeout when receiving data.
///
/// The timeout represents:
///  - a timeout before the connection is established
///    and the first received response bytes.
///  - the duration during data transfer of each byte event,
///    rather than the total duration of the receiving.
///
/// Throws the [DioException] with
/// [DioExceptionType.receiveTimeout] type when timed out.
///
/// `null` or `Duration.zero` means no timeout limit.
Duration? receiveTimeout;

/// Custom field that you can retrieve it later in [Interceptor],
/// [Transformer] and the [Response.requestOptions] object.
Map<String, dynamic>? extra;

/// HTTP request headers.
///
/// The keys of the header are case-insensitive,
/// e.g.: `content-type` and `Content-Type` will be treated as the same key.
Map<String, dynamic>? headers;

/// Whether the case of header keys should be preserved.
///
/// Defaults to false.
///
/// This option WILL NOT take effect on these circumstances:
/// - XHR ([HttpRequest]) does not support handling this explicitly.
/// - The HTTP/2 standard only supports lowercase header keys.
bool? preserveHeaderCase;

/// The type of data that [Dio] handles with options.
///
/// The default value is [ResponseType.json].
/// [Dio] will parse response string to JSON object automatically
/// when the content-type of response is [Headers.jsonContentType].
///
/// See also:
///  - `plain` if you want to receive the data as `String`.
///  - `bytes` if you want to receive the data as the complete bytes.
///  - `stream` if you want to receive the data as streamed binary bytes.
ResponseType? responseType;

/// The request content-type.
///
/// The default `content-type` for requests will be implied by the
/// [ImplyContentTypeInterceptor] according to the type of the request payload.
/// The interceptor can be removed by
/// [Interceptors.removeImplyContentTypeInterceptor].
String? contentType;

/// Defines whether the request is considered to be successful
/// with the given status code.
/// The request will be treated as succeed if the callback returns true.
ValidateStatus? validateStatus;

/// Whether to retrieve the data if status code indicates a failed request.
///
/// Defaults to true.
bool? receiveDataWhenStatusError;

/// See [HttpClientRequest.followRedirects].
///
/// Defaults to true.
bool? followRedirects;

/// The maximum number of redirects when [followRedirects] is `true`.
/// [RedirectException] will be thrown if redirects exceeded the limit.
///
/// Defaults to 5.
int? maxRedirects;

/// See [HttpClientRequest.persistentConnection].
///
/// Defaults to true.
bool? persistentConnection;

/// The default request encoder is [Utf8Encoder], you can set custom
/// encoder by this option.
RequestEncoder? requestEncoder;

/// The default response decoder is [Utf8Decoder], you can set custom
/// decoder by this option, it will be used in [Transformer].
ResponseDecoder? responseDecoder;

/// Indicates the format of collection data in request query parameters and
/// `x-www-url-encoded` body data.
///
/// Defaults to [ListFormat.multi].
ListFormat? listFormat;

There is a complete example here.

Response

The response for a request contains the following information.

/// Response body. may have been transformed, please refer to [ResponseType].
T? data;

/// The corresponding request info.
RequestOptions requestOptions;

/// HTTP status code.
int? statusCode;

/// Returns the reason phrase associated with the status code.
/// The reason phrase must be set before the body is written
/// to. Setting the reason phrase after writing to the body.
String? statusMessage;

/// Whether this response is a redirect.
/// ** Attention **: Whether this field is available depends on whether the
/// implementation of the adapter supports it or not.
bool isRedirect;

/// The series of redirects this connection has been through. The list will be
/// empty if no redirects were followed. [redirects] will be updated both
/// in the case of an automatic and a manual redirect.
///
/// ** Attention **: Whether this field is available depends on whether the
/// implementation of the adapter supports it or not.
List<RedirectRecord> redirects;

/// Custom fields that only for the [Response].
Map<String, dynamic> extra;

/// Response headers.
Headers headers;

When request is succeed, you will receive the response as follows:

final response = await dio.get('https://pub.dev');
print(response.data);
print(response.headers);
print(response.requestOptions);
print(response.statusCode);

Be aware, the Response.extra is different from RequestOptions.extra, they are not related to each other.

Interceptors

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: (RequestOptions options, RequestInterceptorHandler handler) {
      // Do something before request is sent.
      // If you want to resolve the request with custom data,
      // you can resolve a `Response` using `handler.resolve(response)`.
      // If you want to reject the request with a error message,
      // you can reject with a `DioException` using `handler.reject(dioError)`.
      return handler.next(options);
    },
    onResponse: (Response response, ResponseInterceptorHandler handler) {
      // Do something with response data.
      // If you want to reject the request with a error message,
      // you can reject a `DioException` object using `handler.reject(dioError)`.
      return handler.next(response);
    },
    onError: (DioException error, ErrorInterceptorHandler handler) {
      // Do something with response error.
      // If you want to resolve the request with some custom data,
      // you can resolve a `Response` object using `handler.resolve(response)`.
      return handler.next(error);
    },
  ),
);

Simple interceptor example:

import 'package:dio/dio.dart';
class CustomInterceptors extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    print('REQUEST[${options.method}] => PATH: ${options.path}');
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    print('RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}');
    super.onResponse(response, handler);
  }

  @override
  Future onError(DioException err, ErrorInterceptorHandler handler) async {
    print('ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}');
    super.onError(err, handler);
  }
}

Resolve and reject the request

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) .

dio.interceptors.add(
  InterceptorsWrapper(
    onRequest: (options, handler) {
      return handler.resolve(
        Response(requestOptions: options, data: 'fake data'),
      );
    },
  ),
);
final response = await dio.get('/test');
print(response.data); // 'fake data'

QueuedInterceptor

Interceptor can be executed concurrently, that is, all the requests enter the interceptor at once, rather than executing sequentially. However, in some cases we expect that requests enter the interceptor sequentially like #590. Therefore, we need to provide a mechanism for sequential access (step by step) to interceptors and QueuedInterceptor can solve this problem.

Example

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.

For the complete code see here.

LogInterceptor

You can apply the LogInterceptor to log requests and responses automatically.

Note: LogInterceptor should always be the last interceptor added, otherwise modifications by following interceptors will not be logged.

Dart

dio.interceptors.add(LogInterceptor(responseBody: false)); // Do not output responses body.

Note: When using the default logPrint function, logs will only be printed in DEBUG mode (when the assertion is enabled).

Alternatively dart:developer's log can also be used to log messages (available in Flutter too).

Flutter

When using Flutter, Flutters own debugPrint function should be used.

This ensures, that debug messages are also available via flutter logs.

Note: debugPrint does not mean print logs under the DEBUG mode, it's a throttled function which helps to print full logs without truncation. Do not use it under any production environment unless you're intended to.

dio.interceptors.add(
  LogInterceptor(
    logPrint: (o) => debugPrint(o.toString()),
  ),
);

Custom Interceptor

You can customize interceptor by extending the Interceptor/QueuedInterceptor class. There is an example that implementing a simple cache policy: custom cache interceptor.

Handling Errors

When an error occurs, Dio will wrap the Error/Exception to a DioException:

try {
  // 404
  await dio.get('https://api.pub.dev/not-exist');
} on DioException catch (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 != null) {
    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 Error
    print(e.requestOptions)
    print(e.message)
  }
}

DioException

/// The request info for the request that throws exception.
RequestOptions requestOptions;

/// 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;

/// The type of the current [DioException].
DioExceptionType type;

/// The original error/exception object;
/// It's usually not null when `type` is [DioExceptionType.unknown].
Object? error;

/// The stacktrace of the original error/exception object;
/// It's usually not null when `type` is [DioExceptionType.unknown].
StackTrace? stackTrace;

/// The error message that throws a [DioException].
String? message;

DioExceptionType

See the source code.

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:

// Instance level
dio.options.contentType = Headers.formUrlEncodedContentType;
// or only 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.

final formData = FormData.fromMap({
  'name': 'dio',
  'date': DateTime.now().toIso8601String(),
  'file': await MultipartFile.fromFile('./text.txt', filename: 'upload.txt'),
});
final response = await dio.post('/info', data: formData);

You can also specify your desired boundary name which will be used to construct boundaries of every FormData with additional prefix and suffix.

final formDataWithBoundaryName = FormData(
  boundaryName: 'my-boundary-name',
);

FormData is supported with the POST method typically.

There is a complete example here.

Multiple files upload

There are two ways to add multiple files to FormData, the only difference is that upload keys are different for array types。

final formData = FormData.fromMap({
  'files': [
    MultipartFile.fromFileSync('path/to/upload1.txt', filename: 'upload1.txt'),
    MultipartFile.fromFileSync('path/to/upload2.txt', filename: 'upload2.txt'),
  ],
});

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 a list literal, you should create FormData as follows (Don't use FormData.fromMap):

final formData = FormData();
formData.files.addAll([
  MapEntry(
   'files',
    MultipartFile.fromFileSync('./example/upload.txt',filename: 'upload.txt'),
  ),
  MapEntry(
    'files',
    MultipartFile.fromFileSync('./example/upload.txt',filename: 'upload.txt'),
  ),
]);

Reuse FormDatas and MultipartFiles

You should make a new FormData or MultipartFile every time in repeated requests. A typical wrong behavior is setting the FormData as a variable and using it in every request. It can be easy for the Cannot finalize exceptions to occur. To avoid that, write your requests like the below code:

Future<void> _repeatedlyRequest() async {
  Future<FormData> createFormData() async {
    return FormData.fromMap({
      'name': 'dio',
      'date': DateTime.now().toIso8601String(),
      'file': await MultipartFile.fromFile('./text.txt',filename: 'upload.txt'),
    });
  }
  
  await dio.post('some-url', data: await createFormData());
}

Transformer

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 as default. 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.

Transformer.transformRequest only takes effect when request with PUT/POST/PATCH, they're methods that can contain the request body. Transformer.transformResponse however, can be applied to all types of responses.

In Flutter

If you're using Dio in Flutter development, it's better to decode JSON in isolates with the compute function.

/// Must be top-level function
Map<String, dynamic> _parseAndDecode(String response) {
  return jsonDecode(response) as Map<String, dynamic>;
}

Future<Map<String, dynamic>> parseJson(String text) {
  return compute(_parseAndDecode, text);
}

void main() {
  // Custom `jsonDecodeCallback`.
  dio.transformer = DefaultTransformer()..jsonDecodeCallback = parseJson;
  runApp(MyApp());
}

Other example

There is an example for customizing Transformer.

HttpClientAdapter

HttpClientAdapter is a bridge between Dio and HttpClient.

Dio implements standard and friendly APIs for developer. HttpClient is the real object that makes Http requests.

We can use any HttpClient not just dart:io:HttpClient to make HTTP requests. And all we need is providing a HttpClientAdapter. The default HttpClientAdapter for Dio is IOHttpClientAdapter on native platforms, and BrowserHttpClientAdapter on the Web platform. They can be initiated by calling the HttpClientAdapter().

dio.httpClientAdapter = HttpClientAdapter();

If you want to use platform adapters explicitly:

  • For the Web platform:
    import 'package:dio/browser.dart';
    // ...
    dio.httpClientAdapter = BrowserHttpClientAdapter();
    
  • For native platforms:
    import 'package:dio/io.dart';
    // ...
    dio.httpClientAdapter = IOHttpClientAdapter();
    

Here is a simple example to custom adapter.

Using proxy

IOHttpClientAdapter provide a callback to set proxy to dart:io:HttpClient, for example:

import 'package:dio/io.dart';

void initAdapter() {
  dio.httpClientAdapter = IOHttpClientAdapter(
    createHttpClient: () {
      final client = HttpClient();
      // Config the client.
      client.findProxy = (uri) {
        // Forward all request to proxy "localhost:8888".
        // Be aware, the proxy should went through you running device,
        // not the host platform.
        return 'PROXY localhost:8888';
      };
      // You can also create a new HttpClient for Dio instead of returning,
      // but a client must being returned here.
      return client;
    },
  );
}

There is a complete example here.

Web does not support to set proxy.

HTTPS certificate verification

HTTPS certificate verification (or public key pinning) refers to the process of ensuring that the certificates protecting the TLS connection to the server are the ones you expect them to be. The intention is to reduce the chance of a man-in-the-middle attack. The theory is covered by OWASP.

Server Response Certificate

Unlike other methods, this one works with the certificate of the server itself.

void initAdapter() {
  const String fingerprint = 'ee5ce1dfa7a53657c545c62b65802e4272878dabd65c0aadcf85783ebb0b4d5c';
  dio.httpClientAdapter = IOHttpClientAdapter(
    createHttpClient: () {
      // Don't trust any certificate just because their root cert is trusted.
      final HttpClient client = HttpClient(context: SecurityContext(withTrustedRoots: false));
      // You can test the intermediate / root cert here. We just ignore it.
      client.badCertificateCallback = (cert, host, port) => true;
      return client;
    },
    validateCertificate: (cert, host, port) {
      // Check that the cert fingerprint matches the one we expect.
      // We definitely require _some_ certificate.
      if (cert == null) {
        return false;
      }
      // Validate it any way you want. Here we only check that
      // the fingerprint matches the OpenSSL SHA256.
      return fingerprint == sha256.convert(cert.der).toString();
    },
  );
}

You can use openssl to read the SHA256 value of a certificate:

openssl s_client -servername pinning-test.badssl.com -connect pinning-test.badssl.com:443 < /dev/null 2>/dev/null \
  | openssl x509 -noout -fingerprint -sha256

# SHA256 Fingerprint=EE:5C:E1:DF:A7:A5:36:57:C5:45:C6:2B:65:80:2E:42:72:87:8D:AB:D6:5C:0A:AD:CF:85:78:3E:BB:0B:4D:5C
# (remove the formatting, keep only lower case hex characters to match the `sha256` above)

Certificate Authority Verification

These methods work well when your server has a self-signed certificate, but they don't work for certificates issued by a 3rd party like AWS or Let's Encrypt.

There are two ways to verify the root of the https certificate chain provided by the server. Suppose the certificate format is PEM, the code like:

void initAdapter() {
  String PEM = 'XXXXX'; // root certificate content
  dio.httpClientAdapter = IOHttpClientAdapter(
    createHttpClient: () {
      final client = HttpClient();
      client.badCertificateCallback = (X509Certificate cert, String host, int port) {
        return cert.pem == PEM; // Verify the certificate.
      };
      return client;
    },
  );
}

Another way is creating a SecurityContext when create the HttpClient:

void initAdapter() {
  String PEM = 'XXXXX'; // root certificate content
  dio.httpClientAdapter = IOHttpClientAdapter(
    onHttpClientCreate: (_) {
      final SecurityContext sc = SecurityContext();
      sc.setTrustedCertificates(File(pathToTheCertificate));
      final HttpClient client = HttpClient(context: sc);
      return client;
    },
  );
}

In this way, the format of setTrustedCertificates() must be PEM or PKCS12. PKCS12 requires password to use, which will expose the password in the code, so it's not recommended to use in common cases.

HTTP/2 support

dio_http2_adapter is a Dio HttpClientAdapter which supports HTTP/2.

Cancellation

You can cancel a request using a CancelToken. One token can be shared with multiple requests. When a token's cancel() is invoked, all requests with this token will be cancelled.

final cancelToken = CancelToken();
dio.get(url, cancelToken: cancelToken).catchError((DioException error) {
  if (CancelToken.isCancel(error)) {
    print('Request canceled: ${error.message}');
  } else {
    // handle error.
  }
});
// Cancel the requests with "cancelled" message.
token.cancel('cancelled');

There is a complete example here.

Extends Dio class

Dio is an abstract class with factory constructor, so we don't extend Dio class direct. We can extend DioForNative or DioForBrowser instead, for example:

import 'package:dio/dio.dart';
import 'package:dio/io.dart';
// If in browser, import 'package:dio/browser.dart'.

class Http extends DioForNative {
  Http([BaseOptions options]) : super(options) {
    // do something
  }
}

We can also implement a custom Dio client:

class MyDio with DioMixin implements Dio {
  // ...
}

Cross-Origin Resource Sharing on Web (CORS)

If a request is not a simple request, the Web browser will send a CORS preflight request that checks to see if the CORS protocol is understood and a server is aware using specific methods and headers.

You can modify your requests to match the definition of simple request, or add a CORS middleware for your service to handle CORS requests.

Changelog

CHANGELOG

Before you upgrade: Breaking changes might happen in major and minor versions of packages. See the Migration Guide for the complete breaking changes list.

Unreleased

None.

5.4.3+1

  • Fix type promotions for the UTF-8 encoder on previous Dart SDKs.

5.4.3

  • Remove sockets detach in IOHttpClientAdapter.
  • Allows to define FormData.boundaryName instead of the default --dio-boundary-.

5.4.2+1

  • Revert "Catch sync/async exceptions in interceptors' handlers".

5.4.2

  • Fix receiveTimeout throws exception after the request has been cancelled.
  • Catch sync/async exceptions in interceptors' handlers.
  • Throws precise StateError for handler's duplicated calls.

5.4.1

  • Provide fix suggestions for dart fix.
  • Fix receiveTimeout for streamed responses.
  • Fix cancellation for streamed responses and downloads when using IOHttpClientAdapter.
  • Fix receive progress for streamed responses and downloads when using IOHttpClientAdapter.
  • Support relative baseUrl on the Web platform.
  • Avoid fake uncaught exceptions during debugging with IDEs.

5.4.0

  • Improve SyncTransformer's stream transform.
  • Allow case-sensitive header keys with the preserveHeaderCase flag through options.
  • Fix receiveTimeout for the IOHttpClientAdapter.
  • Fix receiveTimeout for the download method of DioForNative.
  • Improve the stream byte conversion.

5.3.4

  • Raise warning for Maps other than Map<String, dynamic> when encoding request data.
  • Improve exception messages.
  • Allow ResponseDecoder and RequestEncoder to be async.
  • Ignores Duration.zero timeouts.

5.3.3

  • Fix failing requests throw DioExceptions with .unknown instead of .connectionError on SocketException.
  • Removes the accidentally added options argument for Options.compose.
  • Fix wrong formatting of multi-value header in BrowserHttpClientAdapter.
  • Add warning in debug mode when trying to send data with a GET request in web.
  • Reduce cases in which browsers would trigger a CORS preflight request.
  • Add warnings in debug mode when using sendTimeout and onSendProgress with an empty request body.
  • Fix receiveTimeout not working correctly on web.
  • Fix ImplyContentTypeInterceptor can be removed by Interceptors.clear() by default.

5.3.2

  • Revert removed download for DioMixin.
  • Fix for Dio.download not cleaning the file on data handling error.

5.3.1

  • Improve package descriptions and code formats.
  • Improve comments.
  • Fix error when cloning MultipartFile from FormData with regression test.
  • Deprecate MultipartFile constructor in favor MultipartFile.fromStream.
  • Add FormData.clone.

5.3.0

  • Remove http from dev_dependencies.
  • Add support for cloning MultipartFile from FormData.
  • Only produce null response body when ResponseType.json.

5.2.1+1

  • Fix changelog on pub.dev.

5.2.1

  • Revert changes to handling of List<int> body data.

5.2.0+1

  • Fix DioErrorType deprecation hint.

5.2.0

  • Make LogInterceptor prints in DEBUG mode (when the assertion is enabled) by default.
  • Deprecate DioError in favor of DioException.
  • Fix IOHttpClientAdapter.onHttpClientCreate Repeated calls
  • IOHttpClientAdapter.onHttpClientCreate has been deprecated and is scheduled for removal in Dio 6.0.0 - Please use the replacement IOHttpClientAdapter.createHttpClient instead.
  • Using CancelToken no longer closes and re-creates HttpClient for each request when IOHttpClientAdapter is used.
  • Fix timeout handling for browser receiveTimeout.
  • Improve performance when sending binary data (List<int>/Uint8List).

5.1.2

  • Allow FormData to send a null entry value as an empty string.

5.1.1

  • Revert changes to CancelToken.cancel() behavior, as a result the DioError provided by the CancelToken.cancelError does not contain useful information when the token was not used with a request.
  • Fix wrong ListFormat being used for comparison during encoding of FormData and application/x-www-form-urlencoded, resulting in potential wrong output encoding for ListFormat.multi and ListFormat.multiCompatible since Dio 4.0.x.
  • Respect Options.listFormat when encoding x-www-url-encoded content.

5.1.0

  • Fix double-completion when using connectionTimeout on web platform.
  • Allow defining adapter methods through their constructors.
  • Fix FormData encoding regression for maps with dynamic keys, introduced in 5.0.3.
  • Mark several static DioMixin functions as @internal.
  • Make DioError.stackTrace non-nullable.
  • Ensure DioError.stackTrace always points to the correct call site.

5.0.3

  • Imply List<Map> as JSON content in ImplyContentTypeInterceptor.
  • Fix FormData encoding for collections and objects.

5.0.2

  • Improve code formats according to linter rules.
  • Remove the force conversion for the response body.
  • Fix DioErrorType.cancel in Interceptors.
  • Fix wrong encoding of collection query parameters.
  • Fix "unsupported operation" error on web platform.

5.0.1

  • Add ImplyContentTypeInterceptor as a default interceptor.
  • Add Headers.multipartFormDataContentType for headers usage.
  • Fix variable shadowing of withCredentials in browser_adapter.dart.

5.0.0

  • Raise the min Dart SDK version to 2.15.0 to support BackgroundTransformer.
  • Change Dio.transformer from DefaultTransformer to BackgroundTransformer.
  • Remove plain ASCII check in FormData.
  • Allow asynchronous method with savePath.
  • Allow data in all request methods.
  • A platform independent HttpClientAdapter can now be instantiated by doing dio.httpClientAdapter = HttpClientAdapter();.
  • Add ValidateCertificate to handle certificate pinning better.
  • Support Content-Disposition header case sensitivity.

Breaking Changes

  • The default charset utf-8 in Headers content type constants has been removed.
  • BaseOptions.setRequestContentTypeWhenNoPayload has been removed.
  • Improve DioErrors. There are now more cases in which the inner original stacktrace is supplied.
  • HttpClientAdapter must now be implemented instead of extended.
  • Any classes specific to dart:io platforms can now be imported via import 'package:dio/io.dart';. Classes specific to web can be imported via import 'package:dio/browser.dart';.
  • connectTimeout, sendTimeout, and receiveTimeout are now Durations.

4.0.6

  • fix #1452

4.0.5

  • require Dart 2.12.1 which fixes exception handling for secure socket connections (#45214)
  • Only delete file if it exists when downloading.
  • Fix BrowserHttpClientAdapter canceled hangs
  • Correct JSON MIME Type detection
  • [Web] support send/receive progress in web platform
  • refactor timeout logic
  • use 'arraybuffer' instead of 'blob' for xhr requests in web platform

4.0.4

  • Fix fetching null data in a response

4.0.3

  • fix #1311

4.0.2

  • Add QueuedInterceptor
  • merge #1316 #1317

4.0.1

  • merge pr #1177 #1196 #1205 #1224 #1225 #1227 #1256 #1263 #1291
  • fix #1257

4.0.0

stable version

4.0.0-prev3

  • fix #1091 , #1089 , #1087

4.0.0-prev2

  • fix #1082 and # 1076

4.0.0-prev1

Interceptors: Add handler for Interceptor APIs which can specify the subsequent interceptors processing logic more finely (whether to skip them or not).

4.0.0-beta7

  • fix #1074

4.0.0-beta6

  • fix #1070

4.0.0-beta5

  • support ListParam

4.0.0-beta4

  • fix #1060

4.0.0-beta3

  • rename CollectionFormat to ListFormat
  • change default value of Options.listFormat from multiCompatible to multi
  • add upload_stream_test.dart

4.0.0-beta2

  • support null-safety
  • add CollectionFormat configuration in Options
  • add fetch API for Dio
  • rename DioErrorType enums from uppercase to camel style
  • rename 'Options.merge' to 'Options.copyWith'

3.0.10 2020.8.7

  1. fix #877 'dio.interceptors.errorLock.lock()'
  2. fix #851
  3. fix #641

3.0.9 2020.2.24

  • Add test cases

3.0.8 2019.12.29

  • Code style improvement

3.0.7 2019.11.25

  • Merge #574 : fix upload image header error, support both oss and other server

3.0.6 2019.11.22

  • revert #562, and fixed #566

3.0.5 2019.11.19

  • merge #557 #531

3.0.4 2019.10.29

  • fix #502 #515 #523

3.0.3 2019.10.1

  • fix encode bug

3.0.2 2019.9.26

  • fix #474 #480

3.0.2-dev.1 2019.9.20

  • fix #470 #471

3.0.1 2019.9.20

  • Fix #467
  • Export DioForNative and DioForBrowser classes.

3.0.0

New features

Change List

  • Options.cookies

  • Options.connectionTimeout ;We should config connection timed out in BaseOptions. For keep-alive reasons, not every request requires a separate connection。

  • Options.followRedirects、Options.maxRedirects、Response.redirects don't make sense in Flutter Web,because redirection can be automatically handled by browsers.

  • FormData.from,use FormData.fromMap instead.

  • Delete Formdata.asBytes()、Formdata.asBytesAsync() , use Formdata.readAsBytes() instead.

  • Delete UploadFileInfo class, MultipartFile instead.

  • The return type of Interceptor's callback changes from FutureOr<dynamic> to Future. The reason is here.

  • The type of Response.headers changes from HttpHeaders to Headers, because HttpHeaders is in "dart:io" library which is not supported in Flutter Web.

2.1.16

Add deleteOnError parameter to downloadUri

2.1.14

  • fix #402 #385 #422

2.1.13

  • fix #369

2.1.12

  • fix #367 #365

2.1.10

  • fix #360

2.1.9

  • support flutter version>=1.8 (fix #357)

2.1.8

  • fix #354 #312
  • Allow "delete" method with request body(#223)

2.1.7

  • fix #321 #318

2.1.6

  • fix #316

2.1.5

  • fix #309

2.1.4

  • Add options.responseDecoder
  • Make DioError catchable by implementing Exception instead of Error

2.1.3

Add statusMessage attribute for Response and ResponseBody

2.1.2

First Stable version for 2.x

2.0

Refactor the Interceptors

  • Support add Multiple Interceptors.
  • Add Log Interceptor
  • Add CookieManager Interceptor

API

  • Support Uri
  • Support queryParameters for all request API
  • Modify the get API

Options

  • Separate Options to three class: Options、BaseOptions、RequestOptions
  • Add queryParameters and cookies for BaseOptions

Adapter

  • Abstract HttpClientAdapter layer.
  • Provide a DefaultHttpClientAdapter which make http requests by dart:io:HttpClient

0.1.8

  • change file name "TransFormer" to "Transformer"
  • change "dio.transFormer" to "dio.transformer"
  • change deprecated "UTF8" to "utf8"

0.1.5

  • add clear method for dio instance

0.1.4

  • fix download bugs

0.1.3

  • support upload files with Array
  • support create HttpClient by user self in onHttpClientCreate
  • support generic
  • bug fix

0.0.1

  • Initial version, created by Stagehand

Installing

export PUB_HOSTED_URL=https://pub.mirror.p-hatan.ir
flutter pub add 'dio:5.4.3+1'
pubspec.yaml
name: dio
version: 5.4.3+1

description: |
  A powerful HTTP networking package,
  supports Interceptors,
  Aborting and canceling a request,
  Custom adapters, Transformers, etc.
topics:
  - dio
  - http
  - network
  - interceptor
  - middleware
homepage: https://github.com/cfug/dio
repository: https://github.com/cfug/dio/blob/main/dio
issue_tracker: https://github.com/cfug/dio/issues

environment:
  sdk: '>=2.15.0 <4.0.0'

dependencies:
  async: ^2.8.2
  http_parser: ^4.0.0
  meta: ^1.5.0
  path: ^1.8.0

dev_dependencies:
  lints: any
  test: ^1.5.1
  build_runner: any
  coverage: ^1.0.3
  crypto: ^3.0.2
  mockito: ^5.2.0

  # Shared test package.
  dio_test:
    git:
      url: https://github.com/cfug/dio
      path: dio_test

Version history

VersionPublishedArchiveSHA-256
0.0.1Cached · Upstream SHA-256 matchedDownload5bc41fc8…eddd8b
0.0.2Cached · Upstream SHA-256 matchedDownload4cac0107…91fd69
0.0.3Cached · Upstream SHA-256 matchedDownload7ce1180b…b9fad8
0.0.4Cached · Upstream SHA-256 matchedDownloada12b23ee…e96eb7
0.0.5Cached · Upstream SHA-256 matchedDownload169d5b7f…062689
0.0.6Cached · Upstream SHA-256 matchedDownload9e74de0d…dafe09
0.0.7Cached · Upstream SHA-256 matchedDownload22e05669…d96dfa
0.0.8Cached · Upstream SHA-256 matchedDownload50abafcc…ae6d76
0.0.9Cached · Upstream SHA-256 matchedDownload5f6f9d5a…ef2fc2
0.0.10Cached · Upstream SHA-256 matchedDownloade59ebb5b…17b838
0.0.11Cached · Upstream SHA-256 matchedDownloadcbeab948…689e68
0.0.12Cached · Upstream SHA-256 matchedDownloadb485e914…de23cc
0.0.13Cached · Upstream SHA-256 matchedDownload123c5841…4317d6
0.0.14Cached · Upstream SHA-256 matchedDownload72cb0bbc…e21b15
0.1.1Cached · Upstream SHA-256 matchedDownload62ab575e…a97e58
0.1.2Cached · Upstream SHA-256 matchedDownloadbda27230…2a7105
0.1.3Cached · Upstream SHA-256 matchedDownloadae23824f…2022be
0.1.4Cached · Upstream SHA-256 matchedDownloadda995108…68e860
0.1.5Cached · Upstream SHA-256 matchedDownload82cc6e7e…44be8d
0.1.6Cached · Upstream SHA-256 matchedDownload0afe7b54…ca098b
0.1.7Cached · Upstream SHA-256 matchedDownload8ffea790…949274
0.1.8Cached · Upstream SHA-256 matchedDownload39f62ea9…f765a0
1.0.0Cached · Upstream SHA-256 matchedDownload4a1f41f7…3cdf27
1.0.1Cached · Upstream SHA-256 matchedDownload7cc5af51…87cc00
1.0.2Cached · Upstream SHA-256 matchedDownload7fecdca6…3db3e3
1.0.3Cached · Upstream SHA-256 matchedDownload0fddaf68…f1a2e3
1.0.4Cached · Upstream SHA-256 matchedDownloadec5b8a46…27563c
1.0.5Cached · Upstream SHA-256 matchedDownload2a8b2d04…e73a92
1.0.6Cached · Upstream SHA-256 matchedDownload3853004e…ce3644
1.0.7Cached · Upstream SHA-256 matchedDownloadc44cfae4…2f77aa
1.0.8Cached · Upstream SHA-256 matchedDownload795030f2…37d5ba
1.0.9Cached · Upstream SHA-256 matchedDownload30684a27…c5300b
1.0.10Cached · Upstream SHA-256 matchedDownload3915eca0…9a138e
1.0.11Cached · Upstream SHA-256 matchedDownload830d5c1e…264e31
1.0.12Cached · Upstream SHA-256 matchedDownload0f20e63a…6cb856
1.0.13Cached · Upstream SHA-256 matchedDownloadf2fb84fd…dca6a8
1.0.14Cached · Upstream SHA-256 matchedDownloada08bfb31…dcfcb4
1.0.15Cached · Upstream SHA-256 matchedDownload127dead5…56ac22
1.0.16Cached · Upstream SHA-256 matchedDownload31159699…00b06b
1.0.17Cached · Upstream SHA-256 matchedDownloadaf70e1e1…44568c
2.0.0Cached · Upstream SHA-256 matchedDownloadf43c90e8…a8efdb
2.0.1Cached · Upstream SHA-256 matchedDownloade3f4a06b…f48e30
2.0.2Cached · Upstream SHA-256 matchedDownloadb2494d87…14ba57
2.0.3Cached · Upstream SHA-256 matchedDownloade8b10c4a…3b7cf3
2.0.4Cached · Upstream SHA-256 matchedDownloadc5573672…1e12b2
2.0.5Cached · Upstream SHA-256 matchedDownload7a01aad5…61e2e5
2.0.6Cached · Upstream SHA-256 matchedDownload6ca3e0fa…b8aa07
2.0.7Cached · Upstream SHA-256 matchedDownload95e034ef…617a60
2.0.8Cached · Upstream SHA-256 matchedDownload64ce4aef…0fe1f2
2.0.9Cached · Upstream SHA-256 matchedDownloaddcf4d22e…b3a294
2.0.10Cached · Upstream SHA-256 matchedDownloade848ec5b…e00d23
2.0.11Cached · Upstream SHA-256 matchedDownloade10bc8ba…fb0869
2.0.12Cached · Upstream SHA-256 matchedDownloadb952b98b…e51cac
2.0.13Cached · Upstream SHA-256 matchedDownloadad0a5ec2…42703f
2.0.14Cached · Upstream SHA-256 matchedDownload760754bc…d9d185
2.0.15Cached · Upstream SHA-256 matchedDownload106febea…74f9bb
2.0.16Cached · Upstream SHA-256 matchedDownload78baa870…4febcb
2.0.17Cached · Upstream SHA-256 matchedDownloadfab3b27d…b34d3f
2.0.18Cached · Upstream SHA-256 matchedDownloadcf252dc1…66621f
2.0.19Cached · Upstream SHA-256 matchedDownloadba1241f6…174412
2.0.20Cached · Upstream SHA-256 matchedDownload05fd4795…2d75c7
2.0.21Cached · Upstream SHA-256 matchedDownload6ec20e7a…845103
2.0.22Cached · Upstream SHA-256 matchedDownload9516eecb…0d28e9
2.0.23Cached · Upstream SHA-256 matchedDownload4c44720a…2383c1
2.1.0Cached · Upstream SHA-256 matchedDownload5a162a32…6ebd7b
2.1.1Cached · Upstream SHA-256 matchedDownload0585f94d…a1ce01
2.1.2Cached · Upstream SHA-256 matchedDownload76692010…2064d0
2.1.3Cached · Upstream SHA-256 matchedDownload1283cfd5…57805b
2.1.4Cached · Upstream SHA-256 matchedDownload4057b7d2…26c96e
2.1.5Cached · Upstream SHA-256 matchedDownload4cb1357b…1c0b9e
2.1.6Cached · Upstream SHA-256 matchedDownload4593d2c3…3fb868
2.1.7Cached · Upstream SHA-256 matchedDownload0e127cea…61b481
2.1.8Cached · Upstream SHA-256 matchedDownload815503e6…1be1d9
2.1.9Cached · Upstream SHA-256 matchedDownload2566bd41…5f879e
2.1.10Cached · Upstream SHA-256 matchedDownload844d05b5…157743
2.1.11Cached · Upstream SHA-256 matchedDownload6107ab69…2a9e71
2.1.12Cached · Upstream SHA-256 matchedDownloadfcc9326b…a64142
2.1.13Cached · Upstream SHA-256 matchedDownloade242b7e1…7f13f3
2.1.14Cached · Upstream SHA-256 matchedDownload29fcb893…ed6463
2.1.15Cached · Upstream SHA-256 matchedDownload3438f224…2d1b37
2.1.16Cached · Upstream SHA-256 matchedDownload5fb66ffd…a4835d
2.2.0Cached · Upstream SHA-256 matchedDownloada7e5346e…4565bf
2.2.1Cached · Upstream SHA-256 matchedDownload479c30bd…ad427c
2.2.2Cached · Upstream SHA-256 matchedDownload8ac4d649…17fcb3
3.0.0-dev.1Cached · Upstream SHA-256 matchedDownload03ce7b80…4faac2
3.0.0Cached · Upstream SHA-256 matchedDownloadf2b8c907…9cfad2
3.0.1Cached · Upstream SHA-256 matchedDownload7c54b490…9b2208
3.0.2-dev.1Cached · Upstream SHA-256 matchedDownload35ac5f65…d4ae3f
3.0.2Cached · Upstream SHA-256 matchedDownloadd0576184…0d7635
3.0.3Cached · Upstream SHA-256 matchedDownloadd76e0f80…f219bc
3.0.4Cached · Upstream SHA-256 matchedDownloaddf5b4f12…579ad7
3.0.5Cached · Upstream SHA-256 matchedDownloadf77f0947…d69d7e
3.0.6Cached · Upstream SHA-256 matchedDownload9ca0e64d…9de525
3.0.7Cached · Upstream SHA-256 matchedDownloadd71f4317…e7d25c
3.0.8-dev.1Cached · Upstream SHA-256 matchedDownload1b028070…e4322b
3.0.8Cached · Upstream SHA-256 matchedDownload155a7f6f…99664b
3.0.9Cached · Upstream SHA-256 matchedDownload49c26d80…876d06
3.0.10Cached · Upstream SHA-256 matchedDownload11979099…bcdd27
4.0.0-beta1Cached · Upstream SHA-256 matchedDownloade05c44c4…5cb588
4.0.0-beta2Cached · Upstream SHA-256 matchedDownloadc650d085…e93e7c
4.0.0-beta3Cached · Upstream SHA-256 matchedDownload186f0697…d4634a
4.0.0-beta4Cached · Upstream SHA-256 matchedDownload25d55004…048065
4.0.0-beta5Cached · Upstream SHA-256 matchedDownload4f625ee7…2e6c0a
4.0.0-beta6Cached · Upstream SHA-256 matchedDownloadabcc1d1d…b04235
4.0.0-beta7Cached · Upstream SHA-256 matchedDownload14c118b5…9d8eb5
4.0.0-prev1Cached · Upstream SHA-256 matchedDownload1b5e25c8…ff684f
4.0.0-prev2Cached · Upstream SHA-256 matchedDownloadb4f0f86a…bc773b
4.0.0-prev3Cached · Upstream SHA-256 matchedDownload0ee6bffb…a82e89
4.0.0Cached · Upstream SHA-256 matchedDownloadbf173c8b…612947
4.0.1Cached · Upstream SHA-256 matchedDownload826fe225…44a60f
4.0.2-beta1Cached · Upstream SHA-256 matchedDownloadec4c0dd1…821c6b
4.0.2Cached · Upstream SHA-256 matchedDownload5c290dbf…77057f
4.0.3Cached · Upstream SHA-256 matchedDownload06fc445e…bb0a9e
4.0.4Cached · Upstream SHA-256 matchedDownload5fd6e152…fd7b1c
4.0.5-beta1Cached · Upstream SHA-256 matchedDownload605f4b72…3f5aa5
4.0.5Cached · Upstream SHA-256 matchedDownloaddad4ffe0…6a996a
4.0.6Cached · Upstream SHA-256 matchedDownload7d328c4d…75e2e8
5.0.0Cached · Upstream SHA-256 matchedDownload9fdbf71b…67d316
5.0.1Cached · Upstream SHA-256 matchedDownload3709d746…e6287e
5.0.2Cached · Upstream SHA-256 matchedDownload2644a9e0…070d7b
5.0.3Cached · Upstream SHA-256 matchedDownload3e5c4a94…32100b
5.1.0Cached · Upstream SHA-256 matchedDownloadf7c26ddb…f8bfce
5.1.1Cached · Upstream SHA-256 matchedDownload0894a098…0f11e9
5.1.2Cached · Upstream SHA-256 matchedDownload347d56c2…e05059
5.2.0Cached · Upstream SHA-256 matchedDownloade44ce32c…c62e6d
5.2.0+1Cached · Upstream SHA-256 matchedDownloadb99b1d56…81bdf2
5.2.1Cached · Upstream SHA-256 matchedDownloaddfda195c…711d1e
5.2.1+1Cached · Upstream SHA-256 matchedDownloada9d76e72…6752b8
5.3.0Cached · Upstream SHA-256 matchedDownload3866d67f…b49993
5.3.1Cached · Upstream SHA-256 matchedDownload9d6445da…cbdd2f
5.3.2Cached · Upstream SHA-256 matchedDownloadce75a1b4…bc4197
5.3.3Cached · Upstream SHA-256 matchedDownload417e2a6f…0140b7
5.3.4Cached · Upstream SHA-256 matchedDownload01870acd…dfea4c
5.4.0Cached · Upstream SHA-256 matchedDownload797e1e34…1645c3
5.4.1Cached · Upstream SHA-256 matchedDownload49af2838…6ce5a8
5.4.2Cached · Upstream SHA-256 matchedDownload50fec961…abeca9
5.4.2+1Cached · Upstream SHA-256 matchedDownload0978e9a3…70217f
5.4.3Cached · Upstream SHA-256 matchedDownload639179e1…834801
5.4.3+1Cached · Upstream SHA-256 matchedDownload11e40df5…9034b5
5.5.0Cached · Upstream SHA-256 matchedDownload77befddd…0de0c8
5.5.0+1Cached · Upstream SHA-256 matchedDownloade17f6b30…e73714
5.6.0Cached · Upstream SHA-256 matchedDownload0dfb6b6a…715fb0
5.7.0Cached · Upstream SHA-256 matchedDownload5598aa79…efc260
5.8.0Cached · Upstream SHA-256 matchedDownload5fe8c827…c8d5b0
5.8.0+1Cached · Upstream SHA-256 matchedDownload253a18bb…c8dbc9
5.9.0Cached · Upstream SHA-256 matchedDownloadd90ee579…ac66a9
5.9.1Cached · Upstream SHA-256 matchedDownloadb9d46fae…e57b25
5.9.2Cached · Upstream SHA-256 matchedDownloadaff32c08…e64f8c
5.10.0Cached · Upstream SHA-256 matchedDownloadea2bad3c…0922b0
5.11.0Cached · Upstream SHA-256 matchedDownload0df44ebb…abbb3c
5.11.1Cached · Upstream SHA-256 matchedDownload852ec3b4…4192c1

Dependencies

async "^2.8.2"

http_parser "^4.0.0"

meta "^1.5.0"

path "^1.8.0"