Rhttp
[Archived] Make HTTP requests using Rust from Flutter.
Install / Use
/learn @Tienisto/RhttpREADME
rhttp
ARCHIVE NOTICE: This repository has been archived. Follow development on Codeberg.
Make HTTP requests using Rust for Flutter developers.
About
This package is a Dart wrapper around the reqwest crate, which is a fast and reliable HTTP client for Rust. For optimal performance, we use FFI with flutter_rust_bridge to call Rust code.
The default HTTP client in Dart is part of dart:io, which lacks configurability and performance compared to other HTTP clients.
Furthermore, HTTP/2 and HTTP/3 are either missing or not supported by default.
Compared to cronet_http and cupertino_http, this package offers a unified, feature-rich API that also works on Windows and Linux.
The APK size will increase by 2 MB on arm64 and 6 MB if compiled for all architectures (x64, arm32, arm64).
Web is currently not supported.
Features
- ✅ HTTP/1, HTTP/1.1, HTTP/2, and HTTP/3 support
- ✅ TLS 1.2 and 1.3 support
- ✅ Connection pooling
- ✅ Interceptors
- ✅ Retry (optional)
- ✅ Certificate pinning
- ✅ Proxy support
- ✅ Custom DNS resolution
- ✅ Cookies
- ✅ Strong type safety
- ✅ DevTools support (Network tab)
- ✅ Compatible with dart:io, http, and dio
Benchmark
rhttp is much faster at downloading large files and a bit faster at downloading small files compared to the default HTTP client in Dart.
| Small Files (1 KB) | Large Files (10 MB) |
|----------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|
|
|
|
Referred packages: dio (5.5.0+1), http (1.2.2), rhttp (0.3.0)
Checkout the benchmark code here.
Table of Contents
- Getting Started
- Request Basics
- Request Lifecycle
- Client Settings
- Intercept
- Error Handling
- Compatibility Layer
Getting Started
➤ Installation
- Install Rust via rustup.
- Rust 1.80.0 or later is required.
- For Android: Install Command-line tools
- Make sure to have the latest NDK installed. #44
- Add
rhttptopubspec.yaml:
dependencies:
rhttp: <version>
➤ Initialization
import 'package:rhttp/rhttp.dart';
void main() async {
await Rhttp.init(); // add this
runApp(MyApp());
}
➤ Usage
import 'package:rhttp/rhttp.dart';
void main() async {
await Rhttp.init();
// Make a GET request
HttpTextResponse response = await Rhttp.get('https://example.com');
// Read the response
int statusCode = response.statusCode;
String body = response.body;
}
Alternatively, you can use the RhttpCompatibleClient that implements the Client of the http package.
For more information, see Compatibility Layer.
import 'package:rhttp/rhttp.dart';
import 'package:http/http.dart' as http;
void main() async {
await Rhttp.init();
http.Client client = await RhttpCompatibleClient.create();
http.Response response = await client.get(Uri.parse('https://example.com'));
print(response.statusCode);
print(response.body);
}
Request Basics
➤ HTTP methods
You can make requests using different HTTP methods:
// Pass the method as an argument
await Rhttp.requestText(method: HttpMethod.post, url: 'https://example.com');
// Use the helper methods
await Rhttp.post('https://example.com');
➤ Request query parameters
You can add query parameters to the URL:
await Rhttp.get('https://example.com', query: {'key': 'value'});
➤ Request Headers
You can add headers to the request:
await Rhttp.post(
'https://example.com',
headers: const HttpHeaders.map({
HttpHeaderName.contentType: 'application/json',
}),
);
➤ Request Body
You can add a body to the request. There are different types of bodies you can use:
Text
Pass a string to the HttpBody.text constructor.
// Raw body
await Rhttp.post(
'https://example.com',
body: HttpBody.text('raw body'),
);
JSON
Pass a JSON data structure to the HttpBody.json constructor.
The Content-Type header will be set to application/json if not provided.
await Rhttp.post(
'https://example.com',
body: HttpBody.json({'key': 'value'}),
);
Binary
Pass a Uint8List to the HttpBody.bytes constructor.
await Rhttp.post(
'https://example.com',
body: HttpBody.bytes(Uint8List.fromList([0, 1, 2])),
);
Stream
Pass a Stream<List<int>> to the HttpBody.stream constructor.
It is recommended to also provide a length to automatically set the Content-Length header.
await Rhttp.post(
'https://example.com',
body: HttpBody.stream(
Stream.fromIterable([[1, 2, 3]]),
length: 3,
),
);
Form
Pass a flat map to the HttpBody.form constructor.
The Content-Type header will be set to application/x-www-form-urlencoded if not provided.
await Rhttp.post(
'https://example.com',
body: HttpBody.form({'key': 'value'}),
);
Multipart
Pass a map of MultipartItem to the HttpBody.multipart constructor.
The Content-Type header will be overridden to multipart/form-data with a random boundary.
await Rhttp.post(
'https://example.com',
body: HttpBody.multipart({
'name': const MultipartItem.text(
text: 'Tom',
),
'profile_image': MultipartItem.bytes(
bytes: Uint8List.fromList(bytes),
fileName: 'image.jpeg',
),
}),
)
➤ Response Body
To let Rust do most of the work, you must specify the expected response body type before making the request.
HttpTextResponse response = await Rhttp.getText('https://example.com');
String body = response.body;
HttpBytesResponse response = await Rhttp.getBytes('https://example.com');
Uint8List body = response.body;
HttpStreamResponse response = await Rhttp.getStream('https://example.com');
Stream<Uint8List> body = response.body;
They all extend the HttpResponse class, which contains the following properties:
| Property | Description |
|-------------------------------------------|-----------------------------------------------------------------|
| String? remoteIp | The remote IP address of the server that sent the response. |
| HttpRequest request | The HTTP request that this response is associated with. |
| HttpVersion version | The HTTP version of this response. |
| int statusCode | The HTTP status code of this response. |
| List<(String, String)> headers | The HTTP headers of this response. |
| Map<String, String> headerMap | Response headers converted as a map. |
| Map<String, List<String>> headerMapList | Response headers converted as a map respecting multiple values. |
Request Lifecycle
➤ Cancel Requests
You can cancel a request by providing a CancelToken.
If the same CancelToken is used for multiple requests, all requests will be canceled.
If a canceled CancelToken is used for a request, the request will be canceled immediately.
final cancelToken = CancelToken();
final
Related Skills
node-connect
349.7kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
109.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
349.7kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
349.7kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
