http

v1.6.0

A composable, multi-platform, Future-based API for HTTP requests.

Архив пакета: https://pubdev.letsnova.ru/api/archives/http/1.6.0.tar.gz

Установкаdart pub add http

README

pub package package publisher

A composable, Future-based library for making HTTP requests.

This package contains a set of high-level functions and classes that make it easy to consume HTTP resources. It's multi-platform (mobile, desktop, and browser) and supports multiple implementations.

Using

The easiest way to use this library is via the top-level functions. They allow you to make individual HTTP requests with minimal hassle:

import 'package:http/http.dart' as http;
                
                var url = Uri.https('example.com', 'whatsit/create');
                var response = await http.post(url, body: {'name': 'doodle', 'color': 'blue'});
                print('Response status: ${response.statusCode}');
                print('Response body: ${response.body}');
                
                print(await http.read(Uri.https('example.com', 'foobar.txt')));
                

[!NOTE] Flutter applications may require additional configuration to make HTTP requests.

If you're making multiple requests to the same server, you can keep open a persistent connection by using a Client rather than making one-off requests. If you do this, make sure to close the client when you're done:

var client = http.Client();
                try {
                  var response = await client.post(
                      Uri.https('example.com', 'whatsit/create'),
                      body: {'name': 'doodle', 'color': 'blue'});
                  var decodedResponse = jsonDecode(utf8.decode(response.bodyBytes)) as Map;
                  var uri = Uri.parse(decodedResponse['uri'] as String);
                  print(await client.get(uri));
                } finally {
                  client.close();
                }
                

[!TIP] For detailed background information and practical usage examples, see:

You can also exert more fine-grained control over your requests and responses by creating Request or StreamedRequest objects yourself and passing them to Client.send.

This package is designed to be composable. This makes it easy for external libraries to work with one another to add behavior to it. Libraries wishing to add behavior should create a subclass of BaseClient that wraps another Client and adds the desired behavior:

class UserAgentClient extends http.BaseClient {
                  final String userAgent;
                  final http.Client _inner;
                
                  UserAgentClient(this.userAgent, this._inner);
                
                  @override
                  Future<http.StreamedResponse> send(http.BaseRequest request) {
                    request.headers['user-agent'] = userAgent;
                    return _inner.send(request);
                  }
                }
                

Testing

For better testability, especially in Flutter applications, it's recommended to use a Client instance rather than the top-level functions like http.get() or http.post(). This approach makes it easier to mock HTTP requests in your tests.

// Instead of using static methods (harder to test):
                // var response = await http.get(Uri.https('example.com', 'data.json'));
                
                // Use a Client instance (easier to test):
                class DataService {
                  final http.Client client;
                
                  DataService({http.Client? client}) : client = client ?? http.Client();
                
                  Future<String> fetchData() async {
                    var response = await client.get(Uri.https('example.com', 'data.json'));
                    return response.body;
                  }
                }
                

In your tests, you can easily mock the HTTP client:

import 'package:http/testing.dart';
                import 'package:test/test.dart';
                
                void main() {
                  test('fetchData returns expected data', () async {
                    final mockClient = MockClient((request) async {
                      return http.Response('{"key": "value"}', 200);
                    });
                
                    final dataService = DataService(client: mockClient);
                    final result = await dataService.fetchData();
                
                    expect(result, '{"key": "value"}');
                  });
                }
                

[!TIP] You can also use package:mockito to mock http.Client. For more detailed guidance, see the Flutter testing cookbook, which demonstrates best practices for mocking HTTP requests.

Retrying requests

package:http/retry.dart provides a class RetryClient to wrap an underlying http.Client which transparently retries failing requests.

import 'package:http/http.dart' as http;
                import 'package:http/retry.dart';
                
                Future<void> main() async {
                  final client = RetryClient(http.Client());
                  try {
                    print(await client.read(Uri.http('example.org', '')));
                  } finally {
                    client.close();
                  }
                }
                

By default, this retries any request whose response has status code 503 Temporary Failure up to three retries. It waits 500ms before the first retry, and increases the delay by 1.5x each time. All of this can be customized using the RetryClient() constructor.

Aborting requests

Some clients, such as BrowserClient, IOClient, and RetryClient, support aborting requests before they complete.

Aborting in this way can only be performed when using Client.send or BaseRequest.send with an Abortable request (such as AbortableRequest).

To abort a request, complete the Abortable.abortTrigger Future.

If the request is aborted before the response Future completes, then the response Future will complete with RequestAbortedException. If the response is a StreamedResponse and the the request is cancelled while the response stream is being consumed, then the response stream will contain a RequestAbortedException.

import 'dart:async';
                
                import 'package:http/http.dart' as http;
                
                Future<void> main() async {
                  final abortTrigger = Completer<void>();
                  final client = Client();
                  final request = AbortableRequest(
                    'GET',
                    Uri.https('example.com'),
                    abortTrigger: abortTrigger.future,
                  );
                
                  // Whenever abortion is required:
                  // > abortTrigger.complete();
                
                  // Send request
                  final StreamedResponse response;
                  try {
                    response = await client.send(request);
                  } on RequestAbortedException {
                    // request aborted before it was fully sent
                    rethrow;
                  }
                
                  // Using full response bytes listener
                  response.stream.listen(
                    (data) {
                      // consume response bytes
                    },
                    onError: (Object err) {
                      if (err is RequestAbortedException) {
                        // request aborted whilst response bytes are being streamed;
                        // the stream will always be finished early
                      }
                    },
                    onDone: () {
                      // response bytes consumed, or partially consumed if finished
                      // early due to abortion
                    },
                  );
                
                  // Alternatively, using `asFuture`
                  try {
                    await response.stream.listen(
                      (data) {
                        // consume response bytes
                      },
                    ).asFuture<void>();
                  } on RequestAbortedException {
                    // request aborted whilst response bytes are being streamed
                    rethrow;
                  }
                    // response bytes fully consumed
                }
                

Choosing an implementation

There are multiple implementations of the package:http Client interface. By default, package:http uses BrowserClient on the web and IOClient on all other platforms. You can choose a different Client implementation based on the needs of your application.

You can change implementations without changing your application code, except for a few lines of configuration.

Some well-supported implementations are:

Implementation Supported Platforms SDK Caching HTTP3/QUIC Platform Native
package:httpIOClient Android, iOS, Linux, macOS, Windows Dart, Flutter
package:httpBrowserClient Web Dart, Flutter ✅︎ ✅︎
package:cupertino_httpCupertinoClient iOS, macOS Flutter ✅︎ ✅︎ ✅︎
package:cronet_httpCronetClient Android Flutter ✅︎ ✅︎
package:fetch_clientFetchClient Web Dart, Flutter ✅︎ ✅︎ ✅︎

[!TIP] If you are writing a Dart package or Flutter plugin that uses package:http, you should not depend on a particular Client implementation. Let the application author decide what implementation is best for their project. You can make that easier by accepting an explicit Client argument. For example:

Future<Album> fetchAlbum({Client? client}) async {
                  client ??= Client();
                  ...
                }
                

Configuration

To use an HTTP client implementation other than the default, you must:

  1. Add the HTTP client as a dependency.
  2. Configure the HTTP client.
  3. Connect the HTTP client to the code that uses it.

1. Add the HTTP client as a dependency.

To add a package compatible with the Dart SDK to your project, use dart pub add.

For example:

# Replace  "fetch_client" with the package that you want to use.
                dart pub add fetch_client
                

To add a package that requires the Flutter SDK, use flutter pub add.

For example:

# Replace  "cupertino_http" with the package that you want to use.
                flutter pub add cupertino_http
                

2. Configure the HTTP client.

Different package:http Client implementations may require different configuration options.

Add a function that returns a correctly configured Client. You can return a different Client on different platforms.

For example:

Client httpClient() {
                  if (Platform.isAndroid) {
                    final engine = CronetEngine.build(
                        cacheMode: CacheMode.memory,
                        cacheMaxSize: 1000000);
                    return CronetClient.fromCronetEngine(engine);
                  }
                  if (Platform.isIOS || Platform.isMacOS) {
                    final config = URLSessionConfiguration.ephemeralSessionConfiguration()
                      ..cache = URLCache.withCapacity(memoryCapacity: 1000000);
                    return CupertinoClient.fromSessionConfiguration(config);
                  }
                  return IOClient();
                }
                

[!TIP] The Flutter HTTP example application demonstrates configuration best practices.

Supporting browser and native

If your application can be run in the browser and natively, you must put your browser and native configurations in separate files and import the correct file based on the platform.

For example:

// -- http_client_factory.dart
                Client httpClient() {
                  if (Platform.isAndroid) {
                    return CronetClient.defaultCronetEngine();
                  }
                  if (Platform.isIOS || Platform.isMacOS) {
                    return CupertinoClient.defaultSessionConfiguration();
                  }
                  return IOClient();
                }
                
// -- http_client_factory_web.dart
                Client httpClient() => FetchClient();
                
// -- main.dart
                import 'http_client_factory.dart'
                    if (dart.library.js_interop) 'http_client_factory_web.dart'
                
                // The correct `httpClient` will be available.
                

3. Connect the HTTP client to the code that uses it.

The best way to pass Client to the places that use it is explicitly through arguments.

For example:

void main() {
                  final client = httpClient();
                  fetchAlbum(client, ...);
                }
                

When using the Flutter SDK, you can use a one of many state management approaches.

[!TIP] The Flutter HTTP example application demonstrates how to make the configured Client available using package:provider and package:http_image_provider.

When using the Dart SDK, you can use runWithClient to ensure that the correct Client is used when explicit argument passing is not an option. For example, if you depend on code that uses top-level functions (e.g. http.post) or calls the Client() constructor. When an Isolate is spawned, it does not inherit any variables from the calling Zone, so runWithClient needs to be used in each Isolate that uses package:http.

You can ensure that only the Client that you have explicitly configured is used by defining no_default_http_client=true in the environment. This will also allow the default Client implementation to be removed, resulting in a reduced application size.

$ flutter build appbundle --dart-define=no_default_http_client=true ...
                $ dart compile exe --define=no_default_http_client=true ...
                

История изменений

1.6.0

  • Breaking Change the behavior of Request.body so that a charset parameter is only added for text and XML media types. This brings the behavior of package:http in line with RFC-8259.
  • On the web, fix cancellations for StreamSubscriptions of response bodies waiting for the next chunk.
  • Export MediaType from package:http_parser.
  • Added a section on testing to README.md.

1.5.0

  • Fixed a bug in IOClient where the HttpClient's response stream was cancelled after the response stream was completed.
  • Added support for aborting requests before they complete.
  • Clarify that some header names may not be sent/received.

1.4.0

  • Fixed default encoding for application/json without a charset to use utf8 instead of latin1, ensuring proper JSON decoding.
  • Avoid references to window in BrowserClient, restoring support for web workers and NodeJS.

1.3.0

  • Fixed unintended HTML tags in doc comments.
  • Switched BrowserClient to use Fetch API instead of XMLHttpRequest.

1.2.2

  • Require package web: '>=0.5.0 <2.0.0'.

1.2.1

  • Require Dart ^3.3
  • Require package:web ^0.5.0.

1.2.0

  • Add MockClient.pngResponse, which makes it easier to fake image responses.
  • Added the ability to fetch the URL of the response through BaseResponseWithUrl.
  • Add the ability to get headers as a Map<String, List<String> to BaseResponse.

1.1.2

  • Allow web: '>=0.3.0 <0.5.0'.

1.1.1

  • BrowserClient throws ClientException when the 'Content-Length' header is invalid.
  • IOClient trims trailing whitespace on header values.
  • Require Dart 3.2
  • Browser: support Wasm by using package:web.

1.1.0

  • Add better error messages for SocketExceptions when using IOClient.
  • Make StreamedRequest.sink a StreamSink. This makes request.sink.close() return a Future instead of void, but the returned future should not be awaited. The Future returned from sink.close() may only complete after the request has been sent.

1.0.0

  • Requires Dart 3.0 or later.
  • Add base, final, and interface modifiers to some classes.

0.13.6

  • BrowserClient throws an exception if send is called after close.
  • If no_default_http_client=true is set in the environment then disk usage is reduced in some circumstances.
  • Require Dart 2.19

0.13.5

  • Allow async callbacks in RetryClient.
  • In MockHttpClient use the callback returned Response.request instead of the argument value to give more control to the callback. This may be breaking for callbacks which return incomplete Responses and relied on the default.

0.13.4

  • Throw a more useful error when a client is used after it has been closed.
  • Require Dart 2.14.

0.13.3

  • Validate that the method parameter of BaseRequest is a valid "token".

0.13.2

  • Add package:http/retry.dart with RetryClient. This is the same implementation as package:http_retry which will be discontinued.

0.13.1

  • Fix code samples in README to pass a Uri instance.

0.13.0

  • Migrate to null safety.
  • Add const constructor to ByteStream.
  • Migrate BrowserClient from blob to arraybuffer.
  • Breaking All APIs which previously allowed a String or Uri to be passed now require a Uri.
  • Breaking Added a body and encoding argument to Client.delete. This is only breaking for implementations which override that method.

0.12.2

  • Fix error handler callback type for response stream errors to avoid masking root causes.

0.12.1

  • Add IOStreamedResponse which includes the ability to detach the socket. When sending a request with an IOClient the response will be an IOStreamedResponse.
  • Remove dependency on package:async.

0.12.0+4

  • Fix a bug setting the 'content-type' header in MultipartRequest.

0.12.0+3

  • Documentation fixes.

0.12.0+2

  • Documentation fixes.

0.12.0

New Features

  • The regular Client factory constructor is now usable anywhere that dart:io or dart:html are available, and will give you an IoClient or BrowserClient respectively.
  • The package:http/http.dart import is now safe to use on the web (or anywhere that either dart:io or dart:html are available).

Breaking Changes

  • In order to use or reference the IoClient directly, you will need to import the new package:http/io_client.dart import. This is typically only necessary if you are passing a custom HttpClient instance to the constructor, in which case you are already giving up support for web.

0.11.3+17

  • Use new Dart 2 constant names. This branch is only for allowing existing code to keep running under Dart 2.

0.11.3+16

  • Stop depending on the stack_trace package.

0.11.3+15

  • Declare support for async 2.0.0.

0.11.3+14

  • Remove single quote ("'" - ASCII 39) from boundary characters. Causes issues with Google Cloud Storage.

0.11.3+13

  • remove boundary characters that package:http_parser cannot parse.

0.11.3+12

  • Don't quote the boundary header for MultipartRequest. This is more compatible with server quirks.

0.11.3+11

  • Fix the SDK constraint to only include SDK versions that support importing dart:io everywhere.

0.11.3+10

  • Stop using dart:mirrors.

0.11.3+9

  • Remove an extra newline in multipart chunks.

0.11.3+8

  • Properly specify Content-Transfer-Encoding for multipart chunks.

0.11.3+7

  • Declare compatibility with http_parser 3.0.0.

0.11.3+6

  • Fix one more strong mode warning in http/testing.dart.

0.11.3+5

  • Fix some lingering strong mode warnings.

0.11.3+4

  • Fix all strong mode warnings.

0.11.3+3

  • Support http_parser 2.0.0.

0.11.3+2

  • Require Dart SDK >= 1.9.0

  • Eliminate many uses of Chain.track from the stack_trace package.

0.11.3+1

  • Support http_parser 1.0.0.

0.11.3

  • Add a Client.patch shortcut method and a matching top-level patch method.

0.11.2

  • Add a BrowserClient.withCredentials property.

0.11.1+3

  • Properly namespace an internal library name.

0.11.1+2

  • Widen the version constraint on unittest.

0.11.1+1

  • Widen the version constraint for stack_trace.

0.11.1

  • Expose the IOClient class which wraps a dart:io HttpClient.

0.11.0+1

  • Fix a bug in handling errors in decoding XMLHttpRequest responses for BrowserClient.

0.11.0

  • The package no longer depends on dart:io. The BrowserClient class in package:http/browser_client.dart can now be used to make requests on the browser.

  • Change MultipartFile.contentType from dart:io's ContentType type to http_parser's MediaType type.

  • Exceptions are now of type ClientException rather than dart:io's HttpException.

0.10.0

  • Make BaseRequest.contentLength and BaseResponse.contentLength use null to indicate an unknown content length rather than -1.

  • The contentLength parameter to new BaseResponse is now named rather than positional.

  • Make request headers case-insensitive.

  • Make MultipartRequest more closely adhere to browsers' encoding conventions.