Repository navigation
v5.0.0
This is a major release that significantly redesigns and modernises the library. It introduces several breaking changes.
Native runtime and installation
- Removed
node-libcurland replaced it with a Rust Node-API v8 binding. libcurl remains the underlying HTTP transport. - The postinstall script that downloaded
node-libcurlbinaries from GitHub is no longer needed. Native binaries are distributed through platform-specific optional npm packages. Installation and import do not download binaries through lifecycle scripts or compile native code. - Added prebuilt distribution for
- Windows x64, arm64, and ia32
- macOS x64 and arm64
- Linux x64 and arm64 on both glibc and musl. GNU/Linux prebuilds require GLIBC 2.31 or newer.
- Lowered the minimum Node.js version from 22 to 16.17.0. Node-API binaries are shared across compatible Node.js versions rather than built for each Node.js major.
- Added explicit source builds and custom native binary loading. Linux and Windows bundle libcurl with HTTP/2 support by default. macOS uses system libcurl. Default TLS backends use OpenSSL on Linux, Schannel on Windows, and system trust on macOS.
Breaking changes
- Multipart API: Replaced
formData: HttpPostField[]withform: FormData. Payload precedence is nowform, thenjson, thenbody, instead ofjson, thenbody, thenformData. - Removed low-level API: Removed
setEasyOptions,SetEasyOptionCallback, andHttpPostField. Use the dedicated proxy, TLS, local binding, and TCP keepalive options. Arbitrary libcurl option callbacks are no longer exposed. - Removed options: Replaced
insecurewith the inverserejectUnauthorizedoption. Removeddebugand its request-input dump in transport errors. - Timeout semantics:
timeoutnow limits the wait for response headers, not the complete transfer. UseoverallTimeoutfor the complete operation, including redirects and retries, andsocketTimeoutfor inactivity. - Redirect headers: Caller-supplied headers are dropped on every redirect by default, including same-origin redirects. Forward selected headers through
allowRedirectHeaders. Payload headers are removed when a redirect changes the method and discards the body. - Proxy configuration: Ambient proxy environment variables are ignored. Configure an explicit HTTP or HTTPS proxy through
proxy. - Compression: gzip/deflate negotiation and decompression are enabled by default. Decompressed responses have
content-encodingandcontent-lengthremoved. Usegzip: falseto keep the encoded body. - Query strings:
qsnow uses nested bracket notation and RFC 3986 encoding. Existing queries are parsed and re-serialised. Dates use ISO strings, and an explicitundefinedremoves a matching existing query value. Review signed URLs and exact URL assertions. - Request headers and validation: Undefined header values are rejected rather than skipped. Header arrays follow Node-style handling. Options and JSON serialisability are validated at runtime. Invalid headers, unsupported framing, and incorrect
Content-Lengthvalues are rejected. Multipart requests cannot supply their ownContent-Length. - Response headers: Repeated fields now follow Node-style joining and singleton rules rather than always becoming arrays.
set-cookieis always an array when present. Trailers are validated but are not merged into response headers. - Request restrictions: Only HTTP and HTTPS URLs are supported, including redirect targets.
CONNECTis rejected,TRACEcannot contain a non-empty body, andOPTIONSwith content requires a non-emptyContent-Type. - Errors and imports: Removed the
sync-request-curl/errorsentry point. Import errors from the package root.getBody()now throwsResponseErrorfor HTTP status codes of 300 or above. Request-layer failures can throwRequestErrorwithETIMEDOUT,ERR_TOO_MANY_REDIRECTS, orERR_REQUEST_FAILED. Native transport failures retain numericCurlErrorcodes. - TypeScript:
Response.bodyis now typed asBuffer, and response mocks needisError(). JSON inputs useJsonLikeinstead ofany. UsegetBody()rather thangetBody(undefined)for an unencoded body.
New features and improvements
- Added GET retries with
retry,retryDelay, andmaxRetries. Retry and delay callbacks receive the error, buffered response, and attempt number. Retries are disabled by default. When enabled, defaults are five retries and a 200 ms delay. - Added private file and memory caches with freshness checks,
Vary, conditional revalidation, permanent redirect reuse, and invalidation after successful unsafe requests. AddedcacheNamespaceand synchronousisMatch,isExpired, andcanCachepolicy hooks. Caching is disabled by default and bypassed for requests carrying credentials, cookies, or bodies, and for custom transport settings. - Added authenticated HTTP/HTTPS proxies,
caFile,localAddress,localInterface, and configurabletcpKeepAlive. Added connection reuse through keep-alive NodeAgentinstances, with native pool cleanup on agent destruction. Custom transport settings bypass shared agent pools. - Added synchronous
FormDatasupport for strings, numbers, booleans, Buffers, and Blobs. Includes filename and content-type handling,knownLengthcompatibility, raw part headers, and synchronous boundary, header, buffer, and length helpers. Stream-valued fields and asynchronous helpers are not supported. - Added
URLobject inputs, case-insensitive methods, andPROPFINDtyping. Improved internationalised hostname handling and nested query serialisation, including circular-value and prototype-pollution safeguards. - Added
response.isError(), which checks for status 0 or 400 and above. Response helpers now observe changes to public response properties and remain callable when detached.getJSON()continues to parse JSON without rejecting HTTP error statuses. Added theutf-16leencoding alias. - Preserved explicit JSON
Content-Type,Authorization, andAccept-Encodingheaders. Removed implicitAcceptand raw-bodyContent-Typedefaults and automaticContent-Length: 0for empty GET, DELETE, and HEAD requests. - Hardened response framing and header parsing, including Node's configured header-size limit, non-ASCII header bytes, and folded headers. Redirects can proceed without waiting for the redirect body when caching and custom retry policies do not need it.
- Consolidated public types and error classes at the package root while retaining ESM and callable CommonJS support. Added generated API documentation and expanded compatibility, native packaging, source-build, and cross-platform release checks.
Migration guide
-
Upgrade and remove the old installer workaround. Remove the GitHub binary-download postinstall step and any
node-libcurldependency or override used only for this package. Keep optional dependencies enabled so the package manager installs the matching native binary.npm install sync-request-curl@^5 --include=optional
The
--include=optionaloption is typically enabled by default, although specified explicitly above in case you have configured your package manager to not install optional packages. If you do not wish to install binaries via optional packages, refer to the build from source instructions. -
Update imports. Move error imports to the root. Public types are also available there. CommonJS remains available through
require('sync-request-curl').import request, { FormData, CurlError, RequestError, ResponseError } from 'sync-request-curl' import type { Options, Response } from 'sync-request-curl'
-
Replace multipart arrays. Use this package's
FormData, not global webFormDataor the separateform-datapackage. Read files into Buffers instead of passing file paths. Multipart payloads are buffered in memory.import { readFileSync } from 'node:fs' import request, { FormData } from 'sync-request-curl' const form = new FormData() form.append('file', readFileSync('./report.txt'), { filename: 'report.txt', contentType: 'text/plain', }) form.append('description', 'Report upload') const response = request('POST', 'https://example.com/upload', { form })
-
Replace legacy transport options. Change a v4 whole-request
timeouttooverallTimeout. Replace proxy callbacks withproxy: { url, username, password }. Mapinsecure: truetorejectUnauthorized: falseonly when disabling certificate and hostname verification is intentional. PrefercaFilefor custom trust, and removedebugandsetEasyOptions. -
Review changed defaults and error handling. Allow-list only headers safe to forward across redirect origins. Remove undefined header entries, review query encoding and response-header assertions, and set
gzip: falsewhere raw compressed bytes are required. HandleRequestErrorandResponseErroralongsideCurlErrorrather than matching error text. -
Build explicitly when a prebuilt binary is unavailable or optional dependencies are omitted. There is no automatic source-build fallback.
npm exec --no -- sync-request-curl-build- Source builds require Rust 1.88 or newer, Cargo, and the platform's native build tools. Build with the Node.js architecture that will load the addon.
- Use
--libcurl=systemor--libcurl=bundledto override platform defaults. System mode fails if a compatible system libcurl cannot be found. - Use
SYNC_REQUEST_CURL_NATIVE_PATHto load an externally managed.nodebinary.
Pull Requests
What's Changed
- feat: replace node-libcurl with Node-API libcurl binding by @nktnet1 in #188
- feat: migration from c/c++ to rust by @nktnet1 in #189
- feat: api v5 major changes by @nktnet1 in #190
- feat: support native source builds and Windows x86 prebuilds by @nktnet1 in #191
- fix: address cache isolation and native transport lifecycle bugs by @nktnet1 in #192
- release: beta conditions by @nktnet1 in #193
- refactor: share release validation and publishing between CLI and CI by @nktnet1 in #194
- feat: keywords, error formatting, version labels by @nktnet1 in #195
- feat: docs cleanup, build from source with options by @nktnet1 in #196
- fix: type incompatibility by @nktnet1 in #197
- fix: restore CommonJS root type exports, remove /types and /errors by @nktnet1 in #198
- fix: then request feature parity by @nktnet1 in #199
- fix: restore response timeout semantics by @nktnet1 in #200
- fix: reuse cached permanent redirects by @nktnet1 in #201
- feat: add synchronous cache policy hooks by @nktnet1 in #202
- fix: resolve API and runtime inconsistencies by @nktnet1 in #203
- fix: align sync-request compatibility docs and encoding by @nktnet1 in #204
- fix: request, response, retry + header parity by @nktnet1 in #205
- fix: valibot error safe parse to avoid exposing ValiError by @nktnet1 in #206
- fix: restore then-request response parity by @nktnet1 in #207
- feat: http-basic feature parity by @nktnet1 in #208
- feat: add synchronous FormData compatibility by @nktnet1 in #209
Full Changelog: v4.0.3...v5.0.0