request-got-adapter
v0.1.6
Published
Drop-in replacement for request-promise-native, backed by got. Same API, same options, same errors — no deprecated request-family dependencies.
Downloads
9,321
Maintainers
Readme
request-got-adapter
A drop-in replacement for request-promise-native, backed by got — with zero request-family dependencies.
The request ecosystem was deprecated in 2020 but still powers a lot of production code. Rewriting every call site to a modern HTTP client is a big, risky migration. This package takes the other path: keep your code exactly as it is and swap the engine underneath.
- const request = require('request-promise-native')
+ const request = require('request-got-adapter')That's the whole migration. Same options, same response shapes, same error classes, same TypeScript types.
You can even do it without touching code, via an npm alias:
{
"dependencies": {
"request-promise-native": "npm:request-got-adapter@^0.1.0"
}
}Install
npm install request-got-adapterRequires Node.js >= 22. Works from plain CommonJS (require) — the ESM-only got is loaded internally.
Usage
Exactly like request-promise-native:
const rp = require('request-got-adapter')
// simple GET — resolves with the body
const html = await rp('https://example.com')
// options object
const user = await rp({
uri: 'https://api.example.com/users/42',
qs: { include: 'profile' },
headers: { Authorization: 'Bearer token' },
json: true
})
// full response
const response = await rp({
uri: 'https://api.example.com/health',
resolveWithFullResponse: true,
simple: false
})
console.log(response.statusCode, response.headers)
// errors behave identically
const { StatusCodeError, RequestError } = require('request-got-adapter/errors')
try {
await rp({ uri: 'https://api.example.com/missing', json: true })
} catch (err) {
if (err instanceof StatusCodeError) {
console.log(err.statusCode) // 404
console.log(err.error) // parsed body
console.log(err.message) // '404 - {"error":"not found"}'
}
}TypeScript works the same way as with @types/request-promise-native:
import request, { type Options, type FullResponse } from 'request-got-adapter'
import { StatusCodeError } from 'request-got-adapter/errors'Compatibility philosophy
The contract is observable behavior parity with request-promise-native — down to error message formats, redirect semantics, and header behavior. A separate repo, request-got-adapter-parity-tests, runs one behavioral test suite against both the real request-promise-native and this adapter and expects identical results. If a test passes there for rpn and fails for this package, that's a bug here — no debate.
Notable parity details handled for you:
- No default
user-agentheader (got normally adds one) - No
accept-encoding/ decompression unless you passgzip: true(got normally auto-negotiates) - No automatic retries (got defaults to 2)
StatusCodeError.messageis`${statusCode} - ${JSON.stringify(body)}`— strings includedRequestError.messageisString(cause), e.g.'Error: getaddrinfo ENOTFOUND nope.example'- Timeouts map to
ETIMEDOUT(connect phase, withconnect: true) /ESOCKETTIMEDOUT(after connect) - Redirects: GET/HEAD followed by default (plain truthiness, like request), any method with
followAllRedirects; body/content-type/content-length stripped on any status except 401/307 (308 is not special in request), method rewritten to GET only underfollowAllRedirects(kept withfollowOriginalHttpMethod),refererheader added,maxRedirectscompared with request's raw JS coercion qs-based query/form serialization (arrays asa[0]=x&a[1]=y, RFC 3986 escaping),useQuerystringsupported- Option-validation errors reject the returned promise (and reach a provided callback) — never synchronous throws
Deliberate improvements over the reference — cases where real request on Node >= 22 crashes the whole process instead of rejecting, and this adapter rejects cleanly:
- object
bodywithoutjson: true(rejects with request'sArgument error, options.body.; request also crashes with an uncaught async TypeError) - invalid
encodingvalues likefalseor''(request throwsERR_UNKNOWN_ENCODINGsynchronously inside a stream handler) formDatacombined with abody(request writes the body after ending the multipart stream —write after end)
Supported options
| Option | Status |
|---|---|
| uri / url / baseUrl / method | ✅ |
| qs / qsStringifyOptions / qsParseOptions / useQuerystring | ✅ |
| headers (case-preserving, case-insensitive lookup) | ✅ |
| body / json (boolean or value) | ✅ |
| form / formData (multipart via form-data) | ✅ |
| auth — Basic, Bearer, sendImmediately: false, Digest | ✅ |
| oauth — OAuth 1.0 (HMAC-SHA1/SHA256, RSA-SHA1, PLAINTEXT; header/query/body transports, body_hash) | ✅ |
| simple / resolveWithFullResponse | ✅ |
| gzip / encoding (incl. null → Buffer) | ✅ |
| followRedirect / followAllRedirects / followOriginalHttpMethod / maxRedirects | ✅ |
| timeout / time (elapsedTime, timingPhases) | ✅ |
| strictSSL / rejectUnauthorized / ca / cert / key / pfx / passphrase | ✅ |
| agent / agentOptions / forever / .forever() | ✅ |
| jar / request.jar() / request.cookie() (tough-cookie) | ✅ |
| transform / transform2xxOnly | ✅ |
| response.caseless (case-insensitive header helper) | ✅ |
| localAddress / family / lookup | ✅ |
| .defaults() (chainable) | ✅ |
| Callback style (err, response, body) alongside promises | ✅ |
| Verb helpers .get/.post/.put/.patch/.del/.delete/.head/.options | ✅ |
GAPS / TODO
These request features are not implemented. Passing them throws a clear not implemented error rather than silently misbehaving (except where noted). PRs welcome.
| Option / feature | Status |
|---|---|
| Stream mode — .pipe(), .on('response'), .on('data') on the returned object | ❌ TODO — the returned object is a promise, not a duplex stream |
| .cancel() on the returned promise | ❌ not present (matches request-promise-native, which also lacks it) |
| har | ❌ throws |
| aws (AWS signing) | ❌ throws |
| httpSignature | ❌ throws |
| proxy / tunnel | ❌ throws — use an agent (e.g. hpagent) instead |
| multipart / preambleCRLF / postambleCRLF (raw multipart, not formData) | ❌ throws |
| jsonReviver / jsonReplacer | ❌ throws |
| pool | ❌ throws — use agent |
| removeRefererHeader | ❌ throws |
| followRedirect as a function | ❌ throws |
| request.debug / request.initParams | ❌ not present |
| TypeScript: rp.delete(...) | runtime works; types expose .del (delete is a reserved word in the type namespace) |
How it works
A thin, clean-room translation layer:
- Translate request-promise-native options into got options (
translate.ts) - Execute via got with parity settings (
throwHttpErrors: false,retry: {limit: 0},decompressoff unlessgzip: true) - Shape got's response back into request's response shape, or throw re-implemented
StatusCodeError/RequestError/TransformError
Dependencies: got, qs, tough-cookie, form-data. OAuth 1.0 signing and Digest auth are implemented natively with node:crypto. CI fails if any request-family package sneaks into the dependency tree.
License
MIT — see LICENSE
