A powerful Http client for Dart, which supports Interceptors, FormData, Request Cancellation, File Downloading, Timeout etc.

Last update: May 23, 2022

Language: English | 中文简体

dio

Pub support

A powerful Http client for Dart, which supports Interceptors, Global configuration, FormData, Request Cancellation, File downloading, Timeout etc.

Get started

Add dependency

dependencies:
  dio: ^4.0.5-beta1

Already know Dio 3 and just want to learn about what's new in Dio 4? Check out the Migration Guide!

Super simple to use

import 'package:dio/dio.dart';
void getHttp() async {
  try {
    var response = await Dio().get('http://www.google.com');
    print(response);
  } catch (e) {
    print(e);
  }
}

awesome-dio

🎉 A curated list of awesome things related to dio.

Plugins (support 4.x)

Plugins Status Description
dio_cookie_manager Pub A cookie manager for Dio
dio_http2_adapter Pub A Dio HttpClientAdapter which support Http/2.0
dio_smart_retry Pub Flexible retry library for Dio
http_certificate_pinning Pub Https Certificate pinning for Flutter
curl_logger_dio_interceptor Pub A Flutter curl-command generator for Dio.
dio_http_cache Pub A simple cache library for Dio like Rxcache in Android
pretty_dio_logger Pub Pretty Dio logger is a Dio interceptor that logs network calls in a pretty, easy to read format.

Related Projects

Welcome to submit Dio's third-party plugins and related libraries here .

Table of contents

Examples

Performing a GET request:

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());

Performing a POST request:

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

Performing multiple concurrent requests:

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

Downloading a file:

response = await dio.download('https://www.google.com/', './xx.html');

Get response stream:

Response<ResponseBody> rs;
rs = await Dio().get<ResponseBody>(url,
  options: Options(responseType: ResponseType.stream),  // set responseType to `stream`
);
print(rs.data.stream); //response stream

Get response with bytes:

Response<List<int>> rs 
rs = await Dio().get<List<int>>(url,
 options: Options(responseType: ResponseType.bytes), // set responseType to `bytes`
);
print(rs.data); // List<int>

Sending FormData:

var formData = FormData.fromMap({
  'name': 'wendux',
  'age': 25,
});
var response = await dio.post('/info', data: formData);

Uploading multiple files to server by FormData:

var formData = FormData.fromMap({
  'name': 'wendux',
  'age': 25,
  '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'),
  ]
});
var response = await dio.post('/info', data: formData);

Listening the uploading progress:

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

Post binary data by Stream:

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

…you can find all examples code here.

Dio APIs

Creating an instance and set default configs.

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

The core API in Dio instance is:

Future request(String path, {data,Map queryParameters, Options options,CancelToken cancelToken, ProgressCallback onSendProgress, ProgressCallback onReceiveProgress)

response = await dio.request(
  '/test',
  data: {'id':12,'name':'xx'},
  options: Options(method:'GET'),
);

Request method aliases

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:

{
  /// 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 parameters
  Map<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`
  late CollectionFormat collectionFormat;

}

There is a complete example here.

Response Schema

The response for a request contains the following information.

{
  /// Response body. may have been transformed, please refer to [ResponseType].
  T? data;
  /// Response headers.
  Headers headers;
  /// The corresponding request info.
  Options request;
  /// 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:

Response response = await dio.get('https://www.google.com');
print(response.data);
print(response.headers);
print(response.requestOptions);
print(response.statusCode);

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:(options, handler){
     // Do something before request is sent
     return 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 data
     return 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 error
     return  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)`.  
    }
));

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}');
    return super.onRequest(options, handler);
  }
  @override
  Future onResponse(Response response, ResponseInterceptorHandler handler) {
    print('RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}');
    return super.onResponse(response, handler);
  }
  @override
  Future onError(DioError err, ErrorInterceptorHandler handler) {
    print('ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}');
    return 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'));
  },
));
Response response = await dio.get('/test');
print(response.data);//'fake data'

QueuedInterceptor

Interceptor can be executed concurrently, that is, all of 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(one by one) 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. The code is as follows:

  var dio = Dio();
  //  dio instance to request token
  var tokenDio = Dio();
  String? csrfToken;
  dio.options.baseUrl = 'http://www.dtworkroom.com/doris/1/2.0.0/';
  tokenDio.options = dio.options;
  dio.interceptors.add(QueuedInterceptorsWrapper(
    onRequest: (options, handler) {
      print('send request:path:${options.path},baseURL:${options.baseUrl}');
      if (csrfToken == null) {
        print('no token,request token firstly...');
        tokenDio.get('/token').then((d) {
          options.headers['csrfToken'] = csrfToken = d.data['data']['token'];
          print('request token succeed, value: ' + d.data['data']['token']);
          print(
              'continue to perform request:path:${options.path},baseURL:${options.path}');
          handler.next(options);
        }).catchError((error, stackTrace) {
          handler.reject(error, true);
        });
      } else {
        options.headers['csrfToken'] = csrfToken;
        return handler.next(options);
      }
    },
   ); 

You can clean the waiting queue by calling clear();

For complete codes click here.

Log

You can set LogInterceptor to print request/response log automaticlly, for example:

dio.interceptors.add(LogInterceptor(responseBody: false)); //开启请求日志

Custom Interceptor

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

Cookie Manager

dio_cookie_manager package is a cookie manager for Dio.

Handling Errors

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

try {
  //404
  await dio.get('https://wendux.github.io/xsddddd');
} on DioError 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)
  }
}

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? request;
  /// Error descriptions.
  String message;

  DioErrorType type;
  /// The original error/exception object; It's usually not null when `type`
  /// is DioErrorType.DEFAULT
  dynamic? error;
}

DioErrorType

enum DioErrorType {
  /// 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.

var formData = FormData.fromMap({
  'name': 'wendux',
  'age': 25,
  'file': await MultipartFile.fromFile('./text.txt',filename: 'upload.txt')
});
response = await dio.post('/info', data: formData);

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。

FormData.fromMap({
  'files': [
    MultipartFile.fromFileSync('./example/upload.txt', filename: 'upload.txt'),
    MultipartFile.fromFileSync('./example/upload.txt', filename: 'upload.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 “[]”,you should create FormData as follows(Don't use FormData.fromMap):

var 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'),
  ),
]);

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

// Must be top-level function
_parseAndDecode(String response) {
  return jsonDecode(response);
}

parseJson(String text) {
  return compute(_parseAndDecode, text);
}

void main() {
  ...
  //Custom jsonDecodeCallback
  (dio.transformer as 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 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.

dio.httpClientAdapter = new DefaultHttpClientAdapter();

Here is a simple example to custom adapter.

Using proxy

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

import 'package:dio/dio.dart';
import 'package:dio/adapter.dart';
...
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
  // config the http client
  client.findProxy = (uri) {
    //proxy all request to localhost:8888
    return 'PROXY localhost:8888';
  };
  // you can also create a new HttpClient to dio
  // return HttpClient();
};

There is a complete example here.

Https certificate verification

There are two ways to verify the https certificate. Suppose the certificate format is PEM, the code like:

String PEM='XXXXX'; // certificate content
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate  = (client) {
  client.badCertificateCallback=(X509Certificate cert, String host, int port){
    if(cert.pem==PEM){ // Verify the certificate
      return true;
    }
    return false;
  };
};

Another way is creating a SecurityContext when create the HttpClient:

(dio.httpClientAdapter as DefaultHttpClientAdapter).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');

There is a complete example here.

Extends Dio class

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/dio.dart';
import 'package:dio/native_imp.dart'; //If in browser, import 'package:dio/browser_imp.dart'

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

We can also implement our Dio client:

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

Copyright & License

This open source project authorized by https://flutterchina.club , and the license is MIT.

Features and bugs

Please file feature requests and bugs at the issue tracker.

Donate

Buy a cup of coffee for me (Scan by wechat):

GitHub

https://github.com/flutterchina/dio
Comments
  • 1. ios13.3.1请求某些证书的https证书时会出现整个app卡死现象

    New Issue Checklist

    • [x] I have searched for a similar issue in the project and found none

    Issue Info

    | Info | Value | | | ------------------------------ | ----------------------------------------------------- | ---- | | Platform Name | ios | | | Platform Version | 13.3.1 | | | Dio Version | 3.0.9 | | | Android Studio / Xcode Version | Xcode 10.2.1 | | | Repro rate | sometimes | | | Repro with our demo prj | e.g. does it happen with our demo project? | | | Demo project link | e.g. link to a demo project that highlights the issue | |

    Issue Description and Steps

    Please fill in the detailed description of the issue (full output of any stack trace, compiler error, ...) and the steps to reproduce the issue.

    ios13.3.1请求某些ssl证书(如过期证书)的https时会出现整个app卡死现象,貌似用Flutter自带的http也会出现, 能不能弄个原生的选项,看dart的不怎么稳定啊。。。

    Reviewed by ghostgzt at 2020-03-15 13:06
  • 2. Locking interceptors doesn't work when multiple requests are enqueued

    New Issue Checklist

    • [x] I have searched for a similar issue in the project and found none

    Issue Info

    | Info | Value | | | ------------------------------ | ----------------------------------------------------- | ---- | | Platform Name | e.g. flutter | | | Platform Version | e.g. master | | | Dio Version | e.g. 3.0.7 | | | Android Studio / Xcode Version | e.g. IntelliJ | | | Repro rate | e.g. all the time (100%) | | Repro with our demo prj | No | |

    Issue Description and Steps

    I'm using an interceptor with locks to lock the interceptor while a token is being refreshed. If multiple requests are enqueued while the lock is active, once it becomes unlocked, all of the requests run at once, rather than executing sequentially.

    Reviewed by josh-burton at 2019-12-05 01:22
  • 3. Content size exceeds specified contentLength on formdata upload

    =====================================

    
    var formData = new FormData.from({
              "param1": "-1",
              "param2": "-1",
              "param3": "-1",
              "param4": "-1",
              "param5": "-1",
              "music": new UploadFileInfo(new File(fileUrl), "audio.m4a"),
            });
    
     final response = await _api.post(uploadUrl, data:formData,
            onSendProgress: (sent, total) {
          print("uploadFile ${sent / total}");
        });
    
    
    • fileUrl comes from device storage.
    • fileUrl is valid, as upload process begins, and it was tested;

    Produces this error:

    flutter: DioError [DioErrorType.DEFAULT]: HttpException: Content size exceeds specified contentLength. 234777 bytes written while expected 234769. [----dio-boundary-0252882641--] Can someone help we with this?

    Reviewed by vinters768 at 2019-05-23 18:08
  • 4. Flutter Web - XMLHttpRequest error

    | Info | Value | | | ------------------------------ | ----------------------------------------------------- | ---- | | Platform Name | flutter web | | | Platform Version | 1.12.13+hotfix.9 | | | Dio Version | 3.0.9 | | | Repro with our demo prj | e.g. does it happen with our demo project? |

    Future<Response> get({
        String innerPath = "",
        CancelToken cancelToken,
        Map<String, String> queryParameters = const {},
      }) async {
        try {
          final response = await _client.get(
            "/$_path/$innerPath",
            cancelToken: cancelToken,
            queryParameters: queryParameters,
          );
          throwIfNoSuccess(response);
          return response;
        } catch (e) {
          throw e;
        }
      }
    

    It works on Android and iOS side. I get this error on the flutter-web.

    Request path : [GET] 'A url to make get request' Request data : null Error message : XMLHttpRequest error. DioError [DioErrorType.RESPONSE]: XMLHttpRequest error.

    Reviewed by cankarabag at 2020-04-21 17:24
  • 5. Cannot read set-cookie from response header in Flutter Web

    According to #585, cookies are automatically managed by the browser, but they are not in Flutter Web. (They works well in Android/iOS). I can see a set-cookie value from the response header in the browser dev tap, but they are not saved in Cookies Storage and not appeared on the console when I print all the headers from the response, it only shows like the below. [Response Headers] {cache-control: no-cache, no-store, max-age=0, must-revalidate, content-type: application/json; charset=utf-8, expires: -1, pragma: no-cache}

    I also tried the this code from @whimthen but it is not working for me.

    There are quite many people experiencing this issue and no certain workaround. I'd appreciate there would be an exact workaround.

    Reviewed by yerim1210 at 2021-01-12 09:02
  • 6. flutter web - dio bloc's (freezes) ui while getting json response

    Using default flutter project simple dio.get freezes CircularProgressIndicator while receiving response. Tested first on iphone and ipad, works fine. Then converted project to flutter web.

    //code import 'package:dio/dio.dart'; import 'package:flutter/material.dart';

    void main() { runApp(MyApp()); }

    class MyApp extends StatelessWidget {

    // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData(

        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
    

    } }

    class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key);

    final String title;

    @override _MyHomePageState createState() => _MyHomePageState(); }

    class _MyHomePageState extends State { int _counter = 1;

    void _incrementCounter() async {

    setState(() {
      _counter++;
    });
    
    if (_counter % 2 == 0){
      try {
        print("Call api");
        var dio = Dio();
    
    
        Response response = await dio.get('https://antara.oxyproductservices.com/all');
    
        if(response.statusCode == 200) {
          print('Status ok');
          print(response.data);
        }else{
          print('ERROR -- ${response.statusCode}');
        }
      }catch(error){
        print('Dio error: $error');
      }
    
    }
    

    }

    @override Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            _presentProgress(),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
    

    }

    _presentProgress() { if (_counter % 2 == 0){ return CircularProgressIndicator(); }else{ return Text('Press (+) to send Api request'); } }

    }

    Reviewed by kele82 at 2020-10-14 10:14
  • 7. Web: freeze UI

    New Issue Checklist

    • [x] I have searched for a similar issue in the project and found none

    Issue Info

    | Info | Value | | | ------------------------------ | ----------------------------------------------------- | ---- | | Platform Name | web | | | Platform Version | | | | Dio Version | 3.0.8 | | | Repro rate | 100% | | | Repro with our demo prj | | | | Demo project link | | |

    Issue Description and Steps

    When I dio.get big JSON file (2-5 Mb) - I have freeze UI on the Web about 10-30 seconds. Standard HttpClient work fine.

    Reviewed by Gorniv at 2020-02-03 07:35
  • 8. onSendProgress "jumps" to 99% and waits there until finished

    Please see this issue: https://stackoverflow.com/questions/61635094/flutter-how-to-increase-onsendprogress-calls-for-a-fluid-progress-bar-animation It's happening to me too and it looks like a bug in Dio.

    Platform name is Flutter, Dio version is 3.0.10.

    Reviewed by lirantzairi at 2020-09-04 16:23
  • 9. connectTimeout/receiveTimeout doesn't work

    New Issue Checklist

    • [X] I have searched for a similar issue in the project and found none

    Issue Info

    | Info | Value | | | ------------------------------ | ----------------------------------------------------- | ---- | | Platform Name | flutter / android | | | Platform Version | 1.12.13+hotfix.8 / 7.0 | | | Dio Version | 3.0.9 | | | Repro rate | all the time (100%) | |

    Issue Description and Steps

    Dio options:

     __dio = Dio(BaseOptions(
          headers: {"Accept": "application/json"},
          responseType: ResponseType.json,
          receiveTimeout: 30000,
          connectTimeout: 5000,
          followRedirects: false,
          receiveDataWhenStatusError: true,
          baseUrl: _baseUrl,
        ));
    

    When my server takes more then 5s to process something, it fails with timeout. BUT the CONNECT timeout is 5s, not the RECEIVE timeout.

    I expect that connect has resolved since it has successfully connected to the client (it didn't receive any response yet, hence the bigger receiveTimeout setting).

    Reviewed by JCKodel at 2020-03-30 19:58
  • 10. Dio is forcing headers to lowercase

    Dio version: dio: ^3.0.8

    When I set Dio header like this

    dio.options.headers['Authorization'] = 'dGVzdDp0ZXN0';

    I expect request header to look like this

    Authorization: Basic dGVzdDp0ZXN0

    Not like this (notice that capital "A" was transformed to "a")

    authorization: Basic dGVzdDp0ZXN0

    Reason for this is HERE. All headers are transformed to lower case. I can only guess what your motivation for this was, but this is wrong.

    Please read about it HERE and HERE

    Even Dart team is currently reverting this https://dart-review.googlesource.com/c/sdk/+/119100

    Dio 2.1.5 did not have this behavior. I was able to use AltHttpClient with Dio and headers where left AS IS.

    Reviewed by shaxxx at 2020-01-10 08:58
  • 11. 图片上传,Postman请求成功,但是dio上传失败~

    dio: 3.0.4 Dart: 2.5.0 Flutter: 1.9.1+hotfix.6

    上传文件代码: static Future upLoadFile(String method, String uri, String filePath, ResponceSuccess responceSuccess, ResponceError responceError, {Map<String, dynamic> body}) async { // 头部 Map<String, dynamic> heads = { "Content-Type": "multipart/form-data", "platform-type": "SHOP_KEEPER" }; // token if (!StringUtils.isEmpty(Api.getInstance().token)) { heads['token'] = Api.getInstance().token; } Options op = Options(method: method, headers: heads);

    String name =
        filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length);
    
    FormData formData = FormData.fromMap(
        {"file": await MultipartFile.fromFile(filePath, filename: name)});
    
    return _dio
        .request<Map<String, dynamic>>(uri,
            queryParameters: body ?? Map<String, dynamic>(),
            data: formData,
            options: op)
        .then((resp) {
      doResponse(resp, responceSuccess, responceError);
    });
    

    }

    上传一直失败,dio还尝试3.0.0还有3.0.5版本,一样失败~

    Reviewed by cuixiaodong at 2019-11-22 00:46
  • 12. A lot of connection errors when send requests in Timer.periodic

    I need to send a POST request every minute. So I use Timer.periodic for it. In debug mode there is no problem. But in production there are hundreds of: SocketException: Failed host lookup Connecting timed out [0ms] SocketException: Software caused connection abort SocketException: Bad file descriptor HandshakeException: Connection terminated during handshake

    I see them in Sentry. I am absolutely sure there was no problems with internet connection. Besides, half of requests reach the destination.

    void _startSendingDeviceActivity() {
      _sendDeviceActiviryTimer?.cancel();
      _sendDeviceActivity();
      _sendDeviceActiviryTimer = Timer.periodic(const Duration(minutes: 1), _sendDeviceActivity);
    }
    
    Future<void> _sendDeviceActivity([_]) async {
      final DeviceInfo deviceInfo = await DeviceActivity.getDeviceInfo();
      _userApi.sendDeviceActivity(deviceInfo);
    }
    
    @override
    void dispose() {
      _sendDeviceActiviryTimer?.cancel();
      super.dispose();
    }
    

    New Issue Checklist

    • [x] I have searched for a similar issue in the project and found none

    Issue Info

    | Info | Value | | | ------------------------------ | ----------------------------------------------------- | ---- | | Platform Name | flutter | | | Platform Version | 2.10.5 | | | Dio Version | 4.0.6 | | | Android Studio / Xcode Version | Android Studio 2021.1.1 patch 2 / Xcode 13.2.1 | | | Repro rate | sometimes ~50% | | | Repro with our demo prj | idk | | | Demo project link | - | |

    Issue Description and Steps

    Please fill in the detailed description of the issue (full output of any stack trace, compiler error, ...) and the steps to reproduce the issue.

    Reviewed by justjew at 2022-05-21 14:52
  • 13. 如何获取整个request body

    看这个库,https://pub.dev/packages/tigertally_flutter_plugin/example 我需要将repuestbody进行加密 java代码是

    Buffer buffer = new Buffer();
    request.writeTo(buffer);
    buffer.readUtf8();
    

    flutter的dio的RequestOptions怎么实现呢?

    Reviewed by fingdo at 2022-05-19 08:07
  • 14. Future already completed

    When calling requests, the error has been thrown randomly.

    Error: Bad state: Future already completed at Object.throw_ [as throw] (http://localhost:1234/dart_sdk.js:5067:11) at _AsyncCompleter.new.completeError (http://localhost:1234/dart_sdk.js:35195:51) at http://localhost:1234/packages/dio/src/interceptors/log.dart.lib.js:651:25 at _RootZone.runUnary (http://localhost:1234/dart_sdk.js:40441:59) at _FutureListener.then.handleValue (http://localhost:1234/dart_sdk.js:35363:29) at handleValueCallback (http://localhost:1234/dart_sdk.js:35931:49) at Function._propagateToListeners (http://localhost:1234/dart_sdk.js:35969:17) at _Future.new.[_complete] (http://localhost:1234/dart_sdk.js:35809:25) at http://localhost:1234/dart_sdk.js:34915:30 at internalCallback (http://localhost:1234/dart_sdk.js:26619:11)

    _dio.interceptors.add(CustomInterceptors());
    
    // ...
    
    class CustomInterceptors extends Interceptor {
      @override
      void onError(DioError err, ErrorInterceptorHandler handler) async {
        if (err.response != null) {
          if (err.response!.statusCode == 401) {
            // ...
            handler.resolve(response);
          } else {
            handler.next(err);
          }
        }
    
        return super.onError(err, handler);
      }
    }
    

    Issue Info

    | Info | Value |
    | ------------------------------ | ----------------------------------------------------- | | Platform Name | Chrome |
    | Dio Version | 4.0.6 |
    | Android Studio Version | 2021.1.1 Patch 2 |

    Issue Description and Steps

    Tried using flutter config --no-analytics. It didn't work.

    Reviewed by jargalbat at 2022-05-19 02:36
  • 15. [Interceptor] How do I implement retry interceptor within attempt count?

    Firstly, I'm sorry because my english is not good. I'm trying implement retry interceptor. Mean, when countAttempt reach to maxAttempt, it is will stop. Mean, in code:

    if(countAttempt <= maxAttempt){
    countAttempt++;
    doRetry();
    }else{
    //Stop.
    }
    

    I have BaseInterceptor:

    abstract class BaseInterceptor extends InterceptorsWrapper {
      int get maxAttempt => 3;
    
      late Future Function() future;
    
      BaseInterceptor(this.future);
    
      int countAttempt = 0;
    
      @override
      void onError(DioError err, ErrorInterceptorHandler handler) async {
        super.onError(err, handler);
        Logger().e("Found an error $countAttempt");
        if (countAttempt <= maxAttempt) {
          countAttempt++;
          await future();
        }
      }
    
      @override
      void onResponse(Response response, ResponseInterceptorHandler handler) {
        super.onResponse(response, handler);
        print("onResponse triggered");
      }
    
      @override
      void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
        super.onRequest(options, handler);
        print("onRequest triggered");
      }
    }
    

    and RetryInterceptor extends above class:

    class RetryInterceptor extends BaseInterceptor {
     RetryInterceptor({required Future Function() future}) : super(future);
    
     @override
     int get maxAttempt => 5;
    }
    

    Finally, I using:

    class UserRepository implements IUserRepository {
    @override
    Future<Model> getUser({int page = 1}) async {
      final dio = Dio();
      dio.interceptors.add(RetryInterceptor(future: getUser)); //This
      Response response;
      response = await dio.get('https://reqres.in/api/users',
          queryParameters: {'per_page': 10, 'page': page});
      final user = Model.fromJson(response.data);
      return user;
    }
    }
    

    My problem is countAttempt always is 0 that cause retry called infinity. I tried combine singleton but it seem not suitable. What the way I can do it?

    Reviewed by NTA-trongpq at 2022-05-13 01:45
  • 16. FormData and Multiparfile can't use from flutter

    I want send to form data to php webserver. But I have no idea. Why Can't use FormData and MultipartFile in Dio plugin.

    [{
    	"resource": "~/Documents/project/flutter/lab/lib/app/controller/board/board_write_controller.dart",
    	"owner": "_generated_diagnostic_collection_name_#0",
    	"code": {
    		"value": "ambiguous_import",
    		"target": {
    			"$mid": 1,
    			"external": "https://dart.dev/diagnostics/ambiguous_import",
    			"path": "/diagnostics/ambiguous_import",
    			"scheme": "https",
    			"authority": "dart.dev"
    		}
    	},
    	"severity": 8,
    	"message": "The name 'FormData' is defined in the libraries 'package:dio/src/form_data.dart (via package:dio/dio.dart)' and 'package:get/get_connect/http/src/multipart/form_data.dart'.\nTry using 'as prefix' for one of the import directives, or hiding the name from all but one of the imports.",
    	"source": "dart",
    	"startLineNumber": 87,
    	"startColumn": 22,
    	"endLineNumber": 87,
    	"endColumn": 30
    }]
    
    
    [{
    	"resource": "~/Documents/project/flutter/lab/lib/app/controller/board/board_write_controller.dart",
    	"owner": "_generated_diagnostic_collection_name_#0",
    	"code": {
    		"value": "ambiguous_import",
    		"target": {
    			"$mid": 1,
    			"external": "https://dart.dev/diagnostics/ambiguous_import",
    			"path": "/diagnostics/ambiguous_import",
    			"scheme": "https",
    			"authority": "dart.dev"
    		}
    	},
    	"severity": 8,
    	"message": "The name 'MultipartFile' is defined in the libraries 'package:dio/src/multipart_file.dart (via package:dio/dio.dart)' and 'package:get/get_connect/http/src/multipart/multipart_file.dart'.\nTry using 'as prefix' for one of the import directives, or hiding the name from all but one of the imports.",
    	"source": "dart",
    	"startLineNumber": 90,
    	"startColumn": 17,
    	"endLineNumber": 90,
    	"endColumn": 30
    }]
    
    Reviewed by yangsh91 at 2022-05-12 06:23

Related

Youtube API in Dart app. Used for downloading media and search request.

Youtube API Youtube API made by using Dart and Flutter in a cross-platform app. Used for downloading media and search request. For an idea of how the

Nov 4, 2021
An HTTP file downloader packed with many features -> resumable downloads, multiple connections, buffering, auto-retry, etc.

An HTTP file downloader packed with many features -> resumable downloads, multiple connections, buffering, auto-retry, etc. Features Resumable downloa

Feb 2, 2022
App HTTP Client is a wrapper around the HTTP library Dio to make network requests and error handling simpler, more predictable, and less verbose.

App HTTP Client App HTTP Client is a wrapper around the HTTP library Dio to make network requests and error handling simpler, more predictable, and le

May 15, 2022
Charlatan - A library for configuring and providing fake http responses to your dio HTTP client.

charlatan This package provides the ability to configure and return fake HTTP responses from your Dio HTTP Client. This makes it easy to test the beha

Feb 24, 2022
Powerful, helpfull, extensible and highly customizable API's that wrap http client to make communication easier with Axelor server with boilerplate code free.
Powerful, helpfull, extensible and highly customizable API's that wrap http client to make communication easier with Axelor server with boilerplate code free.

flutter_axelor_sdk Powerful, helpful, extensible and highly customizable API's that wrap http client to make communication easier with Axelor server w

Nov 12, 2021
Http request inspector for Flutter application
Http request inspector for  Flutter application

Alice Alice is an HTTP Inspector tool for Flutter which helps debugging http requests. It catches and stores http requests and responses, which can be

Dec 4, 2021
A pure Dart utility library that checks for an internet connection by opening a socket to a list of specified addresses, each with individual port and timeout. Defaults are provided for convenience.

data_connection_checker A pure Dart utility library that checks for an internet connection by opening a socket to a list of specified addresses, each

Mar 24, 2022
A lightweight and customizable http client that allows you to create offline-first dart app easily.

Enjoyable & customizable offline-first REST API client Unruffled is lightweight and customizable http client that allows you to create offline-first e

May 20, 2022
This repo contains a collection of permission related Flutter plugins which can be used to request permissions to access device resources in a cross-platform way.

Flutter Permission Plugins Deprecation Notice This repository has been replaced by the Flutter permission_handler plugin and will not longer be mainta

Dec 13, 2021
dos downloader app is developed for downloading video. You can download video from YouTube and Facebook. You can also play video on background

dosdownloader Dos downloader app is developed for downloading video. You can download video from YouTube and Facebook. You can also play video on back

Dec 8, 2021
Flutter frontend for downloading free album and playlists (based on a YouTube URL) and uploading them to a Plex server.
Flutter frontend for downloading free album and playlists (based on a YouTube URL) and uploading them to a Plex server.

Flutter frontend for downloading free album and playlists (based on a YouTube URL) and uploading them to a Plex server. (The project is currently in progress. There are some additional features and ideas I want to implement.)

Jan 9, 2022
A simple flutter app that downloads a file from the internet, shows a custom-made download progress dialog and saves the file to device's internal storage

http_downloader A simple flutter app that downloads a file from the internet using the http plugin. It has a custom-designed progress dialog which dis

Apr 6, 2021
Flutter file based routing - File based routing and nested layouts for Flutter

Flutter File Based Routing I was inspired by the routing in remix.run with neste

Jan 26, 2022
Flutter video compress - Generate a new file by compressed video, and provide metadata. Get video thumbnail from a video path, supports JPEG/GIF. To reduce app size not using FFmpeg in IOS.
Flutter video compress - Generate a new file by compressed video, and provide metadata. Get video thumbnail from a video path, supports JPEG/GIF. To reduce app size not using FFmpeg in IOS.

flutter_video_compress Generate a new path by compressed video, Choose to keep the source video or delete it by a parameter. Get video thumbnail from

May 3, 2022
Weather app using Bloc architecture pattern & generic HTTP client with interface implementation and much more for more detail read Readme
Weather app using Bloc architecture pattern & generic HTTP client with interface implementation and much more for more detail read Readme

weather Weather application for current weather, hourly forecast for 48 hours, Daily forecast for 7 days and national weather alerts. How to Run Insta

Jan 28, 2022
Todo is an Simple Task Management App coded using Dart which is a peogramming language for Flutter SDK(2.5) supports Null Safety 📑🚩

Todo ?? ?? ?? Introduction Todo is an Simple Task Management App coded using Dart which is a peogramming language for Flutter SDK(2.5) supports Null S

Mar 12, 2022
A Flutter plugin to request the device unlock screen.

device_unlock A Flutter plugin to request the device unlock screen on Android and iOS. How does it work The following attempts and fallbacks are made:

May 11, 2022
A sample app of using the image_picker + path_provider and permission_handler package to request permission and store photos on mobile
A sample app of using the image_picker + path_provider and permission_handler package to request permission and store photos on mobile

image_picker_example A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you sta

Apr 19, 2022
Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.

Flutter permission_handler plugin The Flutter permission_handler plugin is build following the federated plugin architecture. A detailed explanation o

May 17, 2022