ht 0.3.1
ht: ^0.3.1 copied to clipboard
Fetch-style HTTP types and protocol abstractions for Dart.
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