@aoxborrow/registrar-client 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +181 -33
- package/dist/index.cjs +742 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -3
- package/dist/index.d.ts +85 -3
- package/dist/index.js +736 -57
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/errors.ts +69 -1
- package/src/features.ts +42 -0
- package/src/http.ts +76 -5
- package/src/index.ts +10 -2
- package/src/registrar.ts +47 -2
- package/src/registrars/cloudflare.ts +3 -0
- package/src/registrars/dynadot.ts +3 -0
- package/src/registrars/gandi.ts +3 -0
- package/src/registrars/godaddy.ts +3 -0
- package/src/registrars/index.ts +2 -0
- package/src/registrars/namebright.ts +6 -2
- package/src/registrars/namecheap.ts +6 -1
- package/src/registrars/namecom.ts +708 -0
- package/src/registrars/namesilo.ts +4 -4
- package/src/registrars/porkbun.ts +3 -3
- package/src/registrars/spaceship.ts +3 -0
- package/src/types.ts +30 -1
- package/src/utils.ts +16 -1
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ npm install @aoxborrow/registrar-client
|
|
|
51
51
|
| `godaddy` | GoDaddy | PAT, or key + secret | ✓ | hybrid v3/v1; sandbox = OTE (v1 only) |
|
|
52
52
|
| `namebright` | NameBright | client ID + secret | — | OAuth2 bearer; production-only |
|
|
53
53
|
| `namecheap` | Namecheap | username + key + client IP | ✓ | XML API; IP allowlisting required |
|
|
54
|
+
| `namecom` | Name.com | username + API token | ✓ | Core v1; separate sandbox host and token |
|
|
54
55
|
| `namesilo` | NameSilo | API key | ✓ | JSON/XML API; key sent in query string |
|
|
55
56
|
| `porkbun` | Porkbun | key + secret | ✓ | sandbox via `pk1_sb_` key; per-domain opt-in |
|
|
56
57
|
| `spaceship` | Spaceship | key + secret | — | |
|
|
@@ -161,42 +162,46 @@ are the guaranteed contract; **extended** methods are opt-in per provider.
|
|
|
161
162
|
**Legend:** ✓ implemented · ✗ not available via the provider's API (throws
|
|
162
163
|
`NotImplementedError`) · a superscript marks a caveat noted below.
|
|
163
164
|
|
|
164
|
-
| Core method | CF | DY | GA | GD | NB | NC | NS | PB | SP |
|
|
165
|
-
| ------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
166
|
-
| `testConnection` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
167
|
-
| `listDomains` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
168
|
-
| `getDomain` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
169
|
-
| `checkAvailability` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
170
|
-
| `getPricing` | ✓ | ✓ᵃ | ✓ | ✓ᵃ | ✗ᵇ | ✓ | ✓ | ✓ | ✗ᵇ |
|
|
171
|
-
| `registerDomain` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
172
|
-
| `renewDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
173
|
-
| `setAutoRenew` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
174
|
-
| `transferIn` | ✗ᶜ | ✓ | ✓ | ✓ | ✗ᵈ | ✓ | ✓ | ✓ | ✓ |
|
|
175
|
-
| `updateNameservers` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
176
|
-
| `getNameservers` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
177
|
-
| `lockDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ |
|
|
178
|
-
| `unlockDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ |
|
|
179
|
-
| `setPrivacy` | ✓ | ✓ | ✓ᶠ | ✓ᵍ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ |
|
|
180
|
-
| `getContacts` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ |
|
|
181
|
-
| `updateContacts` | ✗ᶜ | ✓ | ✓ | ✓ | ✗ᵈ | ✓ | ✓ | ✓ | ✓ |
|
|
182
|
-
| `getDnsRecords` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
183
|
-
| `setDnsRecords` | ✓ | ✓ʰ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ʰ |
|
|
184
|
-
|
|
185
|
-
| Extended method | CF | DY | GA | GD | NB | NC | NS | PB | SP |
|
|
186
|
-
| --------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
187
|
-
| `getAuthCode` | ✗ | ✓ | ✓ | ✓ | ✓ | ✗ⁱ | ✗ⁱ | ✗ | ✓ |
|
|
188
|
-
| `getDnssec` | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ |
|
|
189
|
-
| `disableDnssec` | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ |
|
|
190
|
-
| `getEmailForwarding` | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ |
|
|
191
|
-
| `setEmailForwarding` | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ |
|
|
192
|
-
| `getDomainForwarding` | ✓ | ✓ʲ | ✓ᵏ | ✓ˡ | ✗ | ✓ | ✓ʲ | ✓ | ✗ |
|
|
193
|
-
| `setDomainForwarding` | ✓ | ✓ʲ | ✓ᵏ | ✓ˡ | ✗ | ✓ | ✓ʲ | ✓ | ✗ |
|
|
165
|
+
| Core method | CF | DY | GA | GD | NB | NC | NS | PB | SP | NM |
|
|
166
|
+
| ------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
167
|
+
| `testConnection` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
168
|
+
| `listDomains` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
169
|
+
| `getDomain` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
170
|
+
| `checkAvailability` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
171
|
+
| `getPricing` | ✓ | ✓ᵃ | ✓ | ✓ᵃ | ✗ᵇ | ✓ | ✓ | ✓ | ✗ᵇ | ✓ |
|
|
172
|
+
| `registerDomain` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
173
|
+
| `renewDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
174
|
+
| `setAutoRenew` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
175
|
+
| `transferIn` | ✗ᶜ | ✓ | ✓ | ✓ | ✗ᵈ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
176
|
+
| `updateNameservers` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
177
|
+
| `getNameservers` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
178
|
+
| `lockDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ |
|
|
179
|
+
| `unlockDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ |
|
|
180
|
+
| `setPrivacy` | ✓ | ✓ | ✓ᶠ | ✓ᵍ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ |
|
|
181
|
+
| `getContacts` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ |
|
|
182
|
+
| `updateContacts` | ✗ᶜ | ✓ | ✓ | ✓ | ✗ᵈ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
183
|
+
| `getDnsRecords` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
184
|
+
| `setDnsRecords` | ✓ | ✓ʰ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ʰ | ✓ |
|
|
185
|
+
|
|
186
|
+
| Extended method | CF | DY | GA | GD | NB | NC | NS | PB | SP | NM |
|
|
187
|
+
| --------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
188
|
+
| `getAuthCode` | ✗ | ✓ | ✓ | ✓ | ✓ | ✗ⁱ | ✗ⁱ | ✗ | ✓ | ✓ |
|
|
189
|
+
| `getDnssec` | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ᵐ |
|
|
190
|
+
| `disableDnssec` | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ᵐ |
|
|
191
|
+
| `getEmailForwarding` | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ᵐ |
|
|
192
|
+
| `setEmailForwarding` | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ᵐ |
|
|
193
|
+
| `getDomainForwarding` | ✓ | ✓ʲ | ✓ᵏ | ✓ˡ | ✗ | ✓ | ✓ʲ | ✓ | ✗ | ✗ᵐ |
|
|
194
|
+
| `setDomainForwarding` | ✓ | ✓ʲ | ✓ᵏ | ✓ˡ | ✗ | ✓ | ✓ʲ | ✓ | ✗ | ✗ᵐ |
|
|
194
195
|
|
|
195
196
|
`CF` Cloudflare · `DY` Dynadot · `GA` Gandi · `GD` GoDaddy · `NB` NameBright ·
|
|
196
|
-
`NC` Namecheap · `NS` NameSilo · `PB` Porkbun · `SP` Spaceship.
|
|
197
|
+
`NC` Namecheap · `NS` NameSilo · `PB` Porkbun · `SP` Spaceship · `NM` Name.com.
|
|
197
198
|
|
|
198
199
|
**Caveats**
|
|
199
200
|
|
|
201
|
+
- **ᵐ** Name.com DNSSEC and forwarding are not wired into this adapter yet;
|
|
202
|
+
they are not advertised as extended features. See [Name.com](#namecom-core-api)
|
|
203
|
+
for pricing, transfer and DNS limits.
|
|
204
|
+
|
|
200
205
|
- **ᵃ** `getPricing` is per-domain only (pass a full name, not a bare TLD) —
|
|
201
206
|
Dynadot and GoDaddy price via their availability endpoint and have no per-TLD
|
|
202
207
|
price table.
|
|
@@ -330,6 +335,90 @@ most providers need only the auth code (`TransferDomainInput`).
|
|
|
330
335
|
> per-TLD extended attributes, so TLDs that require them (`.us`, `.eu`, …) aren't
|
|
331
336
|
> registrable there yet.
|
|
332
337
|
|
|
338
|
+
## Name.com Core API
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
const namecom = createRegistrar(
|
|
342
|
+
'namecom',
|
|
343
|
+
{
|
|
344
|
+
username: 'your-username-test',
|
|
345
|
+
apiToken: 'your-development-test-token',
|
|
346
|
+
},
|
|
347
|
+
{ environment: 'sandbox' }
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
await namecom.listDomains();
|
|
351
|
+
await namecom.getPricing('example.com'); // exact domain prices, including premiums
|
|
352
|
+
await namecom.getPricing('.co.uk'); // explicit compound TLD; 'com' also works
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
The adapter uses [Core v1](https://docs.name.com/api/v1/overview), with HTTP Basic
|
|
356
|
+
Auth in the Authorization header. Production is `https://api.name.com/core/v1`;
|
|
357
|
+
sandbox is `https://api.dev.name.com/core/v1`. Use the Development/Test token and
|
|
358
|
+
`-test` username from [API settings](https://www.name.com/account/settings/api).
|
|
359
|
+
The username is used exactly as supplied. For 2FA accounts, API Access must be
|
|
360
|
+
enabled. New sandbox credentials can take up to 15 minutes to activate, per the
|
|
361
|
+
[testing guide](https://docs.name.com/guides/testing-environment).
|
|
362
|
+
|
|
363
|
+
All portfolio and DNS pages are consumed using `nextPage`, including short
|
|
364
|
+
intermediate pages. Missing boolean fields are Core's default `false` values.
|
|
365
|
+
`status` contains the returned registry lock statuses (lowercased, comma separated);
|
|
366
|
+
Core has no lifecycle-status field. `renewalDate` remains null because Core does
|
|
367
|
+
not report a scheduled renewal date. The shared `Domain` model has no price field:
|
|
368
|
+
use `getPricing(domainName)` for renewal prices, rather than estimating them from
|
|
369
|
+
TLD retail prices.
|
|
370
|
+
|
|
371
|
+
Pricing uses account-level USD amounts before VAT. Domain registration and renewal
|
|
372
|
+
quotes explicitly request one year; unavailable/null products remain undefined.
|
|
373
|
+
Transfer prices cover the registry's transfer term, which may exceed one year.
|
|
374
|
+
Bare compound strings such as `co.uk` are interpreted as domains; use `.co.uk` for
|
|
375
|
+
TLD pricing. Availability is restricted to standard/registry-premium registration,
|
|
376
|
+
batched in groups of 50; its discovery price covers the TLD minimum term, so no
|
|
377
|
+
one-year `period` is inferred.
|
|
378
|
+
|
|
379
|
+
Registration rechecks availability and obtains a quote for the requested term.
|
|
380
|
+
Premium create/renew/transfer requests send the exact matching purchase, renewal,
|
|
381
|
+
or transfer price; standard operations omit `purchasePrice`. Null/unavailable
|
|
382
|
+
quotes stop the operation before purchase. Registration defaults to one year;
|
|
383
|
+
pass the appropriate `years` for TLDs with a higher minimum. Aftermarket/backorder,
|
|
384
|
+
claims acknowledgments, IDN language attributes, and other TLD-specific registration
|
|
385
|
+
requirements are not exposed by the shared input types. Such registrations require
|
|
386
|
+
a provider-specific workflow. Transfers accept `authCode` and optional `privacy`;
|
|
387
|
+
explicit `years`, `contacts` or `autoRenew` are rejected before submission because
|
|
388
|
+
Core cannot apply them in its transfer request. Update settings after completion.
|
|
389
|
+
|
|
390
|
+
Mutations follow the shared [retry rules](#retries): a request Name.com may have
|
|
391
|
+
received is never re-sent. Transport/parse failures after a purchase report an
|
|
392
|
+
unknown outcome: inspect Name.com orders and domain/transfer status before retrying. An accepted order is
|
|
393
|
+
reported as accepted, not proof of final registry completion. Read operations
|
|
394
|
+
retain the shared retry policy and honor `Retry-After` / `X-RateLimit-Reset`.
|
|
395
|
+
HTTP errors retain typed status information but omit provider response bodies,
|
|
396
|
+
which may contain credentials, EPP codes or contact data.
|
|
397
|
+
|
|
398
|
+
Contacts require complete objects for each supplied role (including state), and
|
|
399
|
+
omitted roles are left unchanged on update. Postal code/company and EPP-style
|
|
400
|
+
phone numbers are mapped to Core's `zip`, `companyName` and E.164 fields. DNS
|
|
401
|
+
replacement reconciles individual record IDs, preserving unchanged records and
|
|
402
|
+
creating/updating before removing stale records. This is **not atomic**; failures
|
|
403
|
+
can leave a partial zone, which must be read before retrying. Supported DNS types
|
|
404
|
+
are A, AAAA, ANAME, CNAME, MX, NS, SRV and TXT, with a minimum TTL of 300 seconds.
|
|
405
|
+
Only auth-code retrieval is implemented as an extended feature in this version.
|
|
406
|
+
|
|
407
|
+
Offline tests exercise the published API contract. Run the dedicated sandbox
|
|
408
|
+
checks with credentials in `.env.testing`:
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
npm run test:integration -- test/integration/namecom.integration.test.ts
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Read checks are credential-gated and always use sandbox. To exercise registration,
|
|
415
|
+
renewal, flags, nameservers, contacts and DNS, additionally set
|
|
416
|
+
`NAMECOM_TEST_DOMAIN=registrar-client-<unique-suffix>.com`. This must be a disposable
|
|
417
|
+
sandbox name with that prefix. The test creates it if absent and leaves it in the
|
|
418
|
+
sandbox (Name.com offers no domain deletion/reset there); it is excluded from the
|
|
419
|
+
default offline suite. Transfer completion and production behavior need separate
|
|
420
|
+
verification; sandbox transfers are not deterministic.
|
|
421
|
+
|
|
333
422
|
## Sandbox environments
|
|
334
423
|
|
|
335
424
|
Providers that offer a test environment accept `{ environment: 'sandbox' }` at
|
|
@@ -393,8 +482,12 @@ implementations**:
|
|
|
393
482
|
Extend `BaseRegistrar`, pass a `baseUrl` + auth headers to `super()`, add the
|
|
394
483
|
static `displayName` / `configFields` / `helpText` metadata, override the
|
|
395
484
|
operations the API supports (mapping payloads to the shared types in
|
|
396
|
-
`src/types.ts`), and add the class to `src/registrars/index.ts`.
|
|
397
|
-
|
|
485
|
+
`src/types.ts`), and add the class to `src/registrars/index.ts`. Forward the
|
|
486
|
+
`opts` you are given into every `this.http` request: they carry the timeout and
|
|
487
|
+
signal, and tell the [retry rules](#retries) whether the call reads or writes.
|
|
488
|
+
For a REST API set `static safeMethods = REST_SAFE_METHODS`; otherwise wrap any
|
|
489
|
+
lookup a write performs first in `asRead(opts)`. The existing providers under
|
|
490
|
+
`src/registrars/` are working references.
|
|
398
491
|
|
|
399
492
|
**New providers are welcome** — if you've wired up a registrar, open a PR.
|
|
400
493
|
|
|
@@ -404,6 +497,61 @@ All failures throw a typed subclass of `RegistrarError` (`AuthenticationError`,
|
|
|
404
497
|
`NotFoundError`, `RateLimitError`, `TimeoutError`, `NotImplementedError`, …),
|
|
405
498
|
each carrying an HTTP-style `status`.
|
|
406
499
|
|
|
500
|
+
## Retries
|
|
501
|
+
|
|
502
|
+
Requests retry with exponential backoff (`retries`, default 2). What may be
|
|
503
|
+
re-sent depends on where the failure happened and on whether the call reads or
|
|
504
|
+
writes, and is the same for every provider:
|
|
505
|
+
|
|
506
|
+
| Failure | Read | Write |
|
|
507
|
+
| -------------------------------------------------------------------------- | ----- | -------------------------------------- |
|
|
508
|
+
| The registrar never saw it: DNS failure, connection refused, TLS handshake | Retry | Retry |
|
|
509
|
+
| `429`, honoring `Retry-After` | Retry | Retry |
|
|
510
|
+
| Outcome unknown: timeout, connection dropped mid-response, `5xx` | Retry | **Not re-sent.** `OutcomeUnknownError` |
|
|
511
|
+
| Any other response | Fail | Fail |
|
|
512
|
+
|
|
513
|
+
Reads and writes are told apart by feature, not by HTTP method (`FEATURE_CALLS`
|
|
514
|
+
lists every one). The method is no guide: Namecheap sends writes as `GET`, and
|
|
515
|
+
Porkbun sends reads as `POST`. `getAuthCode` counts as a write because some
|
|
516
|
+
registrars regenerate the code.
|
|
517
|
+
|
|
518
|
+
A write often reads first: current DNS records, a price, a zone id. Those
|
|
519
|
+
lookups changed nothing, so they are retried like any read and never reported as
|
|
520
|
+
an unknown outcome. REST providers get this from the HTTP method
|
|
521
|
+
(`static safeMethods = REST_SAFE_METHODS` treats `GET` and `HEAD` as reads);
|
|
522
|
+
providers whose method means nothing wrap the lookup's options in `asRead(opts)`.
|
|
523
|
+
|
|
524
|
+
A write whose outcome is unknown may have been applied, and a second renewal
|
|
525
|
+
charges twice. So the library reports it and leaves the decision to you: re-read
|
|
526
|
+
the domain, then retry if nothing changed. Providers that throw raise
|
|
527
|
+
`OutcomeUnknownError`; providers that return an `OperationResult` set
|
|
528
|
+
`outcome: 'unknown'` on it:
|
|
529
|
+
|
|
530
|
+
```ts
|
|
531
|
+
const result = await client.renewDomain('example.com', 1);
|
|
532
|
+
if (!result.success && result.outcome === 'unknown') {
|
|
533
|
+
const domain = await client.getDomain('example.com'); // did it go through?
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
Only positive evidence counts as "never sent": a pre-connection error code from
|
|
538
|
+
Node's `fetch`, or an error a custom transport marked with `markNotSent`.
|
|
539
|
+
Browsers and Workers report network failures opaquely, so there they count as
|
|
540
|
+
unknown.
|
|
541
|
+
|
|
542
|
+
### Custom transport
|
|
543
|
+
|
|
544
|
+
Pass `fetch` to route every request through your own transport, such as a
|
|
545
|
+
proxy:
|
|
546
|
+
|
|
547
|
+
```ts
|
|
548
|
+
const registrar = createRegistrar('namecheap', credentials, { fetch: proxiedFetch });
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
If the transport can fail before the request leaves, for instance a proxy that
|
|
552
|
+
refuses the tunnel, throw `markNotSent(error)` so the failure is retried even
|
|
553
|
+
for writes.
|
|
554
|
+
|
|
407
555
|
## Security
|
|
408
556
|
|
|
409
557
|
Credentials are sent as request **headers** wherever the registrar's API
|