ht
ht stands for HTTP Types. It provides a fetch-first set of Dart HTTP abstractions.
This package focuses on the type and semantics layer only. It does not implement an HTTP client or server runtime.
Installation
dart pub add ht
Or add it manually to pubspec.yaml:
dependencies:
ht: ^0.2.0
APIs
| Category | Types |
|---|---|
| Protocol | HttpMethod, HttpStatus, HttpVersion, MimeType |
| Message | Request, RequestInit, Response, ResponseInit, Body, BodyInit |
| Header/URL | Headers, URLSearchParams |
| Binary/Form | Blob, File, FormData |
Quick Example
import 'package:ht/ht.dart';
Future<void> main() async {
final request = Request(
RequestInput.uri(Uri.parse('https://api.example.com/tasks')),
RequestInit(
method: HttpMethod.post,
headers: Headers({'content-type': 'application/json; charset=utf-8'}),
body: '{"title":"rewrite ht"}',
),
);
final response = Response.json(
{'ok': true},
ResponseInit(status: HttpStatus.created),
);
print(request.method); // POST
print(request.headers.get('content-type')); // application/json; charset=utf-8
print(await response.text());
}
Body Semantics
Request and Response use a single-consume body model:
- After the first
text()/bytes()/json()/blob()call (or stream read),bodyUsed == true - Reading the same instance again throws
StateError - Use
clone()when multiple reads are required
FormData Example
import 'package:ht/ht.dart';
Future<void> main() async {
final form = FormData()
..append('name', Multipart.text('alice'))
..append(
'avatar',
Multipart.blob(
Blob(<Object>['binary'], 'text/plain;charset=utf-8'),
'avatar.txt',
),
);
final multipart = form.encodeMultipart();
final bytes = await multipart.bytes();
print(multipart.contentType); // multipart/form-data; boundary=...
print(multipart.contentLength); // body bytes length
print(bytes.length); // same as contentLength
}
Block Interop
Blob implements package:block Block, and BodyInit accepts Block
values directly:
import 'package:block/block.dart' as block;
import 'package:ht/ht.dart';
Future<void> main() async {
final body = block.Block(<Object>['hello'], type: 'text/plain');
final request = Request(
RequestInput.uri(Uri.parse('https://example.com')),
RequestInit(method: HttpMethod.post, body: body),
);
print(await request.text()); // hello
}
Blob Slice Semantics
Blob.slice(start, end) now follows Web Blob semantics. Negative indexes are
interpreted from the end of the blob:
final blob = Blob(<Object>['hello world'], 'text/plain;charset=utf-8');
final tail = blob.slice(-5);
print(await tail.text()); // world
Development
dart pub get
dart format --output=none --set-exit-if-changed .
dart analyze
dart test
dart run example/main.dart