go_http 0.2.2
go_http: ^0.2.2 copied to clipboard
Reliable HTTP client for Dart — built for control, cancellation and consistency.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.2.2 - 2026-07-13 #
Added #
- Per-request delay:
RequestOptions.delaypauses before sending the request (rate-limiting / polite crawling). - Body byte limits:
RequestOptions.maxBytesToRead/maxBytesToSavethrowMaxBytesReadErrorwhen the decoded response body exceeds the configured threshold. - Drain-and-close for keep-alive:
IoTransportdrains remaining response bytes before throwing read errors, returning the connection to the pool. RateLimiter— token-bucket rate limiter with.take()→Future<void>(configurable tokens/sec and burst).ResizeableSemaphore— adaptive semaphore with runtimeresize(), FIFO fair ordering, non-negativeavailable.HostCircuitBreaker— per-host circuit breaker (closed/open/half-open), configurable failure threshold and cooldown,CircuitOpenErrorfor fail-fast.RateLimitPolicy.global()/.perHost()— policy wrapper overRateLimiterfor shared or per-host rate limiting.ResponseEnrichment,ResponseTiming,TlsInfo— enrichment data model attached toResponse.enrichment.RequestTrace— per-request phase timestamps (wroteRequest, gotFirstResponseByte, responseDone) populated byIoTransport.RetryPolicy.scanning()/.single()— retry presets for probing vs critical workloads.- Idempotency extended:
PUTandDELETEare now retried by default (matchinghttpx/retryablehttp). - Gzip-fallback:
IoTransportreturns raw body instead of crashing when a server sendsContent-Encoding: gzipon an uncompressed body. - Auto-scheme fallback:
IoTransport.tryHttpOnHttpsError(defaultfalse) retries a failed HTTPS connection once with HTTP. - Graceful two-step shutdown:
GoHttpClient.shutdown()(soft — stops new requests, waits for in-flight) anddispose()(hard — closes transport immediately).ClientShutdownErrorthrown on new requests after shutdown. Dialerabstract class +SocketDialer— pluggable socket-level dialer interface (integration withIoTransportpending transport rewrite).- IP-override:
RequestOptions.dialAddress— connect to a specific IP:port while keeping the original hostname in theHostheader. - Dialed-IP exposure:
Response.remoteAddressandResponseEnrichment.remoteAddress— IP address of the remote server that handled the request. TlsInfoenrichment:subject,issuer,fingerprintSha1,validFrom,validTofields; populated byIoTransportfromHttpClientResponse.certificate.GoHttpClient.validate()— returnsList<ValidationError>with config issues (timeout <= 0, redirects < 0, etc.). Non-throwing, suitable for UI/config check.AggregateError— multierr equivalent collecting multiple errors into one (for close-multiple-resources patterns).ValidationErrorclass — field + message pair for config validation results.- Two-level config:
ClientConfig(transport/timeout/TLS/proxy/cookies) +ExecutorConfig(interceptors/metrics/hooks/enrichers), bothvalidate(), both optional and backward-compatible inGoHttpClientconstructor. ProgressReporter— per-batch progress with RPS, percentage, elapsed, and ETA (ProgressReporter.summary).ResponseEnricherSPI —abstract class ResponseEnricherregistered viaExecutorConfig.enrichers, called per response in enrichment pipeline. Extra data lands inResponseEnrichment.extra.ResponseFilterinterface +StatusCodeFilter,RegexFilter,Match(OR/AND short-circuit) — ready for inclusion/exclusion in batch pipelines.BearerAuth— statelessBearerAuth('token')strategy forAuthInterceptor. LegacytokenProvider/tokenRefreshermarked@Deprecated.stderrLog— log helper writing todart:iostderr (fallback toprinton Web).LoggingInterceptornow defaults tostderrLog, keeping stdout clean for JSONL/result output.ClientConfig.fromJson()+mergeEnv()— load config from JSON map, override fromGO_HTTP_*env vars.PortSpec.parse('http:8080,https:443')— nmap-style scheme→port mapping.Headers.parse('Content-Type: application/json')factory — one or moreKey: Valuelines.ClientConfig.copyWith()— produce a modified copy preserving other fields.- Two-phase file writing —
ResultSink.jsonl()/.csv()write to a temp file (O_EXCL+ incrementing suffix) and atomically rename onclose(), preventing parallel-writer corruption. ClientConfig.minTlsVersion/maxTlsVersion— reserved config surface for TLS version constraints (forward-compat, SDK pending).ResultCallbacktypedef +List<ResultCallback>? onResultsparam onBatchExecutor.run()— chain multiple callbacks alongside legacyonResult.
0.2.1 - 2026-07-13 #
Added #
- Public
Headerscollection: case-insensitive, multi-value (Set-Cookie,Vary,Link),getAll/multiItems, sensitive-header masking intoString. UseClientDefaultsentinel for three-statetimeout/followRedirects(useClientDefault→ client default,null→ disable, value → override).buildRequest()/send()/request()split —buildRequestis the merge boundary;senddispatches a preparedRequestwithout re-merging (escape hatch:client.send(client.buildRequest(req))).baseUrloption onGoHttpClient(relative request URIs resolve against it).- Structured exception hierarchy:
HttpError→RequestError→TransportError(TimeoutError/NetworkError/ProtocolError/ProxyError/UnsupportedProtocol) → typed leaves (ConnectTimeoutError,ReadTimeoutError,WriteTimeoutError,ConnectError, …);HttpStatusErrordeliberately does not extendRequestErrorsocatch (RequestError)never swallows a 4xx/5xx. - Event hooks:
EventHookswith multicastrequest/responsecallback lists, hot-swappable at runtime viaGoHttpClient.eventHooks. Url(immutable wrapper overUri: lowercased scheme/host, default-port collapsed tonull,copyWith, RFC 3986join, password-maskedtoString) andQueryParams(immutable multi-value query:add/set/remove/mergereturn new instances,getList, JSON-style bool).RequestOptions.queryParametersis now aQueryParams.Multipartencoder (zero-dependencymultipart/form-data):MultipartFile/MultipartField,render()/stream()/encodedLength, random 16-byte boundary, content-type guessing from extension, HTML5 attribute escaping.GoHttpClientauto-serializes aMultipartrequest body and setsContent-Type.- Proxy support:
Proxy(http/https/socks5/direct, parse + maskedtoString),URLPattern(wildcard*host,all://scheme,specificity),ProxyMounts(most-specific route wins,null= explicit direct), andbuildSecurityContexthonoring explicitverify/SSL_CERT_FILEenv.GoHttpClienttakesproxyMounts,trustEnv,verify; native transport wiresfindProxy,badCertificateCallback, and a per-clientSecurityContext. Result<T>(never-throw batch outcome:Result.ok/Result.fail) and pluggableResultSinkSPI withjsonl/csvfactories; CSV output sanitizes formula-injection cells (=,+,-,@).- Auth SPI:
Authstrategy (BasicAuth,FunctionAuth) applied on the request path, plusDigestAuth(RFC 2617/7616, MD5/SHA-256, qop, cnonce, nonce-count) driven by the interceptor's 401WWW-Authenticatechallenge via the existing retry path.AuthInterceptornow takes anauthstrategy and still supports the legacy BearertokenProvider/tokenRefresherflow. - Body encoding:
encodeRequestdispatch ladder —json→application/json,Map→application/x-www-form-urlencoded, rawString/bytes/Multipartpass through.post/put/patch/deleteroute theirdata/jsonthrough it. - Content decoder registry:
ContentDecoderSPI +contentDecodersmap (gzip/deflate always, brotli/zstd optional viaregisterBrotli/registerZstd),decodeContentEncodingfor stacked encodings, deflate-ambiguity fix (zlib → raw fallback).IoTransportnow always setsautoUncompress=falseand decodes manually. Defaultaccept-encodingnarrowed togzip.
Changed #
- Updated
README.md— complete rewrite reflecting all current APIs (proxy, auth, decoders, batch, multipart, structured timeouts, headers, mock transport, error hierarchy, etc.) - Deleted
example/main.dart(duplicate ofsimple_get.dart); addedexample/post_json.dartdemonstratingjson:parameter - Updated
example/download_progress.dartto useonProgresscallback - Updated
Makefile: replacedexample-maintarget withexample-post-json
0.2.0 - 2026-07-12 #
Fixed #
- Timeouts now actually work:
connectTimeout/sendTimeout/receiveTimeoutare enforced per phase on native (dart:io) and as an overall request timeout on web. Exceeding a timeout throwsTimeoutError(previously these options were silently ignored). - Web binary responses:
WebTransportnow readsresponseType = 'arraybuffer', so binary data (images, gzipped bodies, files) is no longer corrupted. - Multi-value
Set-Cookie: cookies withExpires/multiple headers are parsed correctly (no longer split on the comma insideExpires). TheDomainattribute is honored for subdomain matching. - Error interceptors now run exactly once per attempt (previously twice for HTTP errors).
- Auth refresh retry:
AuthInterceptornow retries the request once after refreshing the token on401(previously refreshed but never retried). - Dead redirect code removed;
followRedirects/maxRedirectsare now wired into the IO transport. - Header keys normalized to lowercase in both transports for case-insensitive lookups.
IoTransportno longer mutates a caller-suppliedHttpClient.
Added #
RetrySignalcontrol-flow type returned by interceptors to request a bounded retry.Decoder<T>support (decoder:parameter) on all request methods for real type-safe decoding.ProgressCallback(onReceiveProgress:) on all request methods, with byte progress on native and web.- Convenience methods:
put,delete,patch,head,options. - Injectable
Loggersink forLoggingInterceptorandConsoleMetricsSink. maxAuthRetriesoption onGoHttpClient.queryParametersfromRequestOptionsare now applied to the request URI.
Changed #
- Retry backoff switched to stateless exponential backoff with equal jitter (AWS-recommended; safe to share a single policy across concurrent requests). Previously claimed "decorrelated jitter" but implemented a different, stateful algorithm.
CancellationTokenevent delivery is now synchronous (instant listener notification).
Tests #
- Added comprehensive test suite: retry policy, cookie store, cancellation, decoders, and client flow (retries, auth refresh, cancellation, error-interceptor cardinality, decoders, query params, convenience methods) via a fake transport.
0.1.1 - 2025-11-13 #
Added #
- Basic example (
example/main.dart) for pub.dev package validation - Makefile with development commands for code analysis, formatting, running examples, and version management
0.1.0 - 2025-01-13 #
Added #
- Basic HTTP client with GET and POST methods
- Request cancellation support via
CancellationToken - Retry policy with decorrelated jitter backoff algorithm
- Interceptors for request/response/error handling
- Built-in
LoggingInterceptorandAuthInterceptor - Cookie store with
MemoryCookieStoreimplementation - Metrics collection with
ConsoleMetricsSink - Cross-platform support (Dart CLI, Flutter, Web)
- IO transport for native platforms
- Web transport for browser platforms
- Redirect policy support
- Type-safe response handling with generics
- Comprehensive error types (
NetworkError,HttpResponseError,TimeoutError,CancellationError)
Security #
- Retries only for idempotent HTTP methods (GET, HEAD, OPTIONS)
- Sensitive headers are masked in logs
- TLS verification enabled by default