tangerine 2.0.2 → 2.1.1
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 +571 -25
- package/index.d.ts +7 -0
- package/index.js +142 -43
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -398,6 +398,7 @@ Similar to the `options` argument from `new dns.promises.Resolver(options)` invo
|
|
|
398
398
|
| `returnHTTPErrors` | `Boolean` | `false` | Whether to return HTTP errors instead of mapping them to corresponding DNS errors. |
|
|
399
399
|
| `smartRotate` | `Boolean` | `true` | Whether to do smart server rotation if servers fail. |
|
|
400
400
|
| `defaultHTTPErrorMessage` | `String` | `"Unsuccessful HTTP response"` | Default fallback message if `statusCode` returned from HTTP request was not found in [http.STATUS_CODES](https://nodejs.org/api/http.html#httpstatus_codes). |
|
|
401
|
+
| `parallelResolution` | `Boolean` | `false` | Enable parallel resolution for querying DNS servers. |
|
|
401
402
|
|
|
402
403
|
|
|
403
404
|
## Cache
|
|
@@ -533,15 +534,27 @@ We have written extensive benchmarks to show that :tangerine: Tangerine is as fa
|
|
|
533
534
|
|
|
534
535
|
#### Latest Automated Benchmark Results
|
|
535
536
|
|
|
536
|
-
**Last Updated:**
|
|
537
|
+
**Last Updated:** 2026-03-05
|
|
537
538
|
|
|
538
539
|
| Node Version | Platform | Arch | Timestamp |
|
|
539
540
|
| ------------ | -------- | ---- | ------------ |
|
|
540
541
|
| v18.20.8 | linux | x64 | Dec 21, 2025 |
|
|
541
|
-
| v20.19.6 | linux | x64 |
|
|
542
|
+
| v20.19.6 | linux | x64 | Jan 22, 2026 |
|
|
543
|
+
| v20.20.0 | linux | x64 | Feb 25, 2026 |
|
|
542
544
|
| v22.21.1 | linux | x64 | Dec 21, 2025 |
|
|
545
|
+
| v22.22.0 | linux | x64 | Jan 23, 2026 |
|
|
543
546
|
| v24.12.0 | linux | x64 | Dec 21, 2025 |
|
|
547
|
+
| v24.13.0 | linux | x64 | Feb 19, 2026 |
|
|
548
|
+
| v24.13.1 | linux | x64 | Mar 4, 2026 |
|
|
549
|
+
| v24.14.0 | linux | x64 | Mar 5, 2026 |
|
|
544
550
|
| v25.2.1 | linux | x64 | Dec 21, 2025 |
|
|
551
|
+
| v25.3.0 | linux | x64 | Jan 14, 2026 |
|
|
552
|
+
| v25.4.0 | linux | x64 | Jan 20, 2026 |
|
|
553
|
+
| v25.5.0 | linux | x64 | Jan 27, 2026 |
|
|
554
|
+
| v25.6.0 | linux | x64 | Feb 4, 2026 |
|
|
555
|
+
| v25.6.1 | linux | x64 | Feb 11, 2026 |
|
|
556
|
+
| v25.7.0 | linux | x64 | Feb 25, 2026 |
|
|
557
|
+
| v25.8.0 | linux | x64 | Mar 4, 2026 |
|
|
545
558
|
|
|
546
559
|
<details>
|
|
547
560
|
<summary>Click to expand detailed benchmark results</summary>
|
|
@@ -597,12 +610,12 @@ Fastest without caching is: dns.promises.reverse without caching
|
|
|
597
610
|
|
|
598
611
|
```text
|
|
599
612
|
Started: lookup
|
|
600
|
-
tangerine.lookup POST with caching using Cloudflare x
|
|
601
|
-
tangerine.lookup POST without caching using Cloudflare x
|
|
602
|
-
tangerine.lookup GET with caching using Cloudflare x
|
|
603
|
-
tangerine.lookup GET without caching using Cloudflare x
|
|
604
|
-
dns.promises.lookup with caching using Cloudflare x
|
|
605
|
-
dns.promises.lookup without caching using Cloudflare x 3,
|
|
613
|
+
tangerine.lookup POST with caching using Cloudflare x 820 ops/sec ±195.45% (88 runs sampled)
|
|
614
|
+
tangerine.lookup POST without caching using Cloudflare x 212 ops/sec ±2.98% (79 runs sampled)
|
|
615
|
+
tangerine.lookup GET with caching using Cloudflare x 290,812 ops/sec ±0.74% (88 runs sampled)
|
|
616
|
+
tangerine.lookup GET without caching using Cloudflare x 260 ops/sec ±2.00% (82 runs sampled)
|
|
617
|
+
dns.promises.lookup with caching using Cloudflare x 8,961,323 ops/sec ±0.78% (86 runs sampled)
|
|
618
|
+
dns.promises.lookup without caching using Cloudflare x 3,143 ops/sec ±0.57% (85 runs sampled)
|
|
606
619
|
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
607
620
|
```
|
|
608
621
|
|
|
@@ -610,29 +623,67 @@ Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
|
610
623
|
|
|
611
624
|
```text
|
|
612
625
|
Started: resolve
|
|
613
|
-
tangerine.resolve POST with caching using Cloudflare x 1,
|
|
614
|
-
tangerine.resolve POST without caching using Cloudflare x
|
|
615
|
-
tangerine.resolve GET with caching using Cloudflare x 1,
|
|
616
|
-
tangerine.resolve GET without caching using Cloudflare x
|
|
617
|
-
tangerine.resolve POST with caching using Google x 1,
|
|
618
|
-
tangerine.resolve POST without caching using Google x
|
|
619
|
-
tangerine.resolve GET with caching using Google x 1,
|
|
620
|
-
tangerine.resolve GET without caching using Google x
|
|
621
|
-
resolver.resolve with caching using Cloudflare x 7,
|
|
622
|
-
resolver.resolve without caching using Cloudflare x
|
|
623
|
-
Fastest without caching is: tangerine.resolve GET without caching using
|
|
626
|
+
tangerine.resolve POST with caching using Cloudflare x 1,034 ops/sec ±195.81% (89 runs sampled)
|
|
627
|
+
tangerine.resolve POST without caching using Cloudflare x 221 ops/sec ±1.83% (80 runs sampled)
|
|
628
|
+
tangerine.resolve GET with caching using Cloudflare x 1,044,036 ops/sec ±0.36% (89 runs sampled)
|
|
629
|
+
tangerine.resolve GET without caching using Cloudflare x 272 ops/sec ±1.57% (83 runs sampled)
|
|
630
|
+
tangerine.resolve POST with caching using Google x 1,035,748 ops/sec ±0.31% (89 runs sampled)
|
|
631
|
+
tangerine.resolve POST without caching using Google x 236 ops/sec ±0.93% (85 runs sampled)
|
|
632
|
+
tangerine.resolve GET with caching using Google x 1,027,998 ops/sec ±0.25% (89 runs sampled)
|
|
633
|
+
tangerine.resolve GET without caching using Google x 230 ops/sec ±1.04% (83 runs sampled)
|
|
634
|
+
resolver.resolve with caching using Cloudflare x 7,717,855 ops/sec ±0.67% (85 runs sampled)
|
|
635
|
+
resolver.resolve without caching using Cloudflare x 24.10 ops/sec ±180.34% (37 runs sampled)
|
|
636
|
+
Fastest without caching is: tangerine.resolve GET without caching using Cloudflare
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
**reverse:**
|
|
640
|
+
|
|
641
|
+
```text
|
|
642
|
+
spawnSync /bin/sh ETIMEDOUT
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
##### Node.js v20.20.0
|
|
646
|
+
|
|
647
|
+
**lookup:**
|
|
648
|
+
|
|
649
|
+
```text
|
|
650
|
+
Started: lookup
|
|
651
|
+
tangerine.lookup POST with caching using Cloudflare x 732 ops/sec ±195.51% (87 runs sampled)
|
|
652
|
+
tangerine.lookup POST without caching using Cloudflare x 117 ops/sec ±1.61% (79 runs sampled)
|
|
653
|
+
tangerine.lookup GET with caching using Cloudflare x 299,941 ops/sec ±1.15% (89 runs sampled)
|
|
654
|
+
tangerine.lookup GET without caching using Cloudflare x 117 ops/sec ±1.43% (80 runs sampled)
|
|
655
|
+
dns.promises.lookup with caching using Cloudflare x 1,383 ops/sec ±195.97% (87 runs sampled)
|
|
656
|
+
dns.promises.lookup without caching using Cloudflare x 2,374 ops/sec ±0.56% (86 runs sampled)
|
|
657
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
**resolve:**
|
|
661
|
+
|
|
662
|
+
```text
|
|
663
|
+
Started: resolve
|
|
664
|
+
tangerine.resolve POST with caching using Cloudflare x 974 ops/sec ±195.82% (89 runs sampled)
|
|
665
|
+
tangerine.resolve POST without caching using Cloudflare x 130 ops/sec ±1.30% (87 runs sampled)
|
|
666
|
+
tangerine.resolve GET with caching using Cloudflare x 1,049,956 ops/sec ±1.53% (85 runs sampled)
|
|
667
|
+
tangerine.resolve GET without caching using Cloudflare x 117 ops/sec ±1.79% (79 runs sampled)
|
|
668
|
+
tangerine.resolve POST with caching using Google x 1,019,993 ops/sec ±0.48% (88 runs sampled)
|
|
669
|
+
tangerine.resolve POST without caching using Google x 106 ops/sec ±4.78% (83 runs sampled)
|
|
670
|
+
tangerine.resolve GET with caching using Google x 1,030,533 ops/sec ±0.28% (89 runs sampled)
|
|
671
|
+
tangerine.resolve GET without caching using Google x 123 ops/sec ±0.59% (83 runs sampled)
|
|
672
|
+
resolver.resolve with caching using Cloudflare x 7,658,904 ops/sec ±0.60% (86 runs sampled)
|
|
673
|
+
resolver.resolve without caching using Cloudflare x 13.28 ops/sec ±201.81% (11 runs sampled)
|
|
674
|
+
Fastest without caching is: tangerine.resolve POST without caching using Cloudflare
|
|
624
675
|
```
|
|
625
676
|
|
|
626
677
|
**reverse:**
|
|
627
678
|
|
|
628
679
|
```text
|
|
629
680
|
Started: reverse
|
|
630
|
-
tangerine.reverse GET with caching x
|
|
631
|
-
tangerine.reverse GET without caching x
|
|
632
|
-
resolver.reverse with caching x
|
|
633
|
-
resolver.reverse without caching x
|
|
634
|
-
dns.promises.reverse with caching x 7,
|
|
635
|
-
dns.promises.reverse without caching x
|
|
681
|
+
tangerine.reverse GET with caching x 991 ops/sec ±195.36% (87 runs sampled)
|
|
682
|
+
tangerine.reverse GET without caching x 129 ops/sec ±0.76% (86 runs sampled)
|
|
683
|
+
resolver.reverse with caching x 0.10 ops/sec ±0.01% (5 runs sampled)
|
|
684
|
+
resolver.reverse without caching x 2.80 ops/sec ±112.00% (74 runs sampled)
|
|
685
|
+
dns.promises.reverse with caching x 7,904,185 ops/sec ±0.60% (85 runs sampled)
|
|
686
|
+
dns.promises.reverse without caching x 8.68 ops/sec ±202.85% (14 runs sampled)
|
|
636
687
|
Fastest without caching is: tangerine.reverse GET without caching
|
|
637
688
|
```
|
|
638
689
|
|
|
@@ -674,6 +725,51 @@ Fastest without caching is: tangerine.resolve GET without caching using Google
|
|
|
674
725
|
spawnSync /bin/sh ETIMEDOUT
|
|
675
726
|
```
|
|
676
727
|
|
|
728
|
+
##### Node.js v22.22.0
|
|
729
|
+
|
|
730
|
+
**lookup:**
|
|
731
|
+
|
|
732
|
+
```text
|
|
733
|
+
Started: lookup
|
|
734
|
+
tangerine.lookup POST with caching using Cloudflare x 1,163 ops/sec ±195.31% (90 runs sampled)
|
|
735
|
+
tangerine.lookup POST without caching using Cloudflare x 54.38 ops/sec ±5.55% (88 runs sampled)
|
|
736
|
+
tangerine.lookup GET with caching using Cloudflare x 313,634 ops/sec ±0.27% (89 runs sampled)
|
|
737
|
+
tangerine.lookup GET without caching using Cloudflare x 55.58 ops/sec ±6.39% (71 runs sampled)
|
|
738
|
+
dns.promises.lookup with caching using Cloudflare x 9,649,217 ops/sec ±0.65% (88 runs sampled)
|
|
739
|
+
dns.promises.lookup without caching using Cloudflare x 3,178 ops/sec ±0.70% (85 runs sampled)
|
|
740
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
**resolve:**
|
|
744
|
+
|
|
745
|
+
```text
|
|
746
|
+
Started: resolve
|
|
747
|
+
tangerine.resolve POST with caching using Cloudflare x 1,186 ops/sec ±195.79% (89 runs sampled)
|
|
748
|
+
tangerine.resolve POST without caching using Cloudflare x 55.82 ops/sec ±5.02% (84 runs sampled)
|
|
749
|
+
tangerine.resolve GET with caching using Cloudflare x 1,099,153 ops/sec ±0.22% (90 runs sampled)
|
|
750
|
+
tangerine.resolve GET without caching using Cloudflare x 59.25 ops/sec ±5.73% (73 runs sampled)
|
|
751
|
+
tangerine.resolve POST with caching using Google x 1,095 ops/sec ±195.81% (88 runs sampled)
|
|
752
|
+
tangerine.resolve POST without caching using Google x 60.23 ops/sec ±10.05% (80 runs sampled)
|
|
753
|
+
tangerine.resolve GET with caching using Google x 1,107,393 ops/sec ±0.67% (90 runs sampled)
|
|
754
|
+
tangerine.resolve GET without caching using Google x 54.10 ops/sec ±10.64% (74 runs sampled)
|
|
755
|
+
resolver.resolve with caching using Cloudflare x 8,395,785 ops/sec ±0.65% (89 runs sampled)
|
|
756
|
+
resolver.resolve without caching using Cloudflare x 67.84 ops/sec ±0.83% (80 runs sampled)
|
|
757
|
+
Fastest without caching is: resolver.resolve without caching using Cloudflare, tangerine.resolve POST without caching using Google
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
**reverse:**
|
|
761
|
+
|
|
762
|
+
```text
|
|
763
|
+
Started: reverse
|
|
764
|
+
tangerine.reverse GET with caching x 1,114 ops/sec ±195.34% (89 runs sampled)
|
|
765
|
+
tangerine.reverse GET without caching x 55.88 ops/sec ±4.70% (89 runs sampled)
|
|
766
|
+
resolver.reverse with caching x 8,531,724 ops/sec ±0.82% (84 runs sampled)
|
|
767
|
+
resolver.reverse without caching x 68.04 ops/sec ±0.73% (81 runs sampled)
|
|
768
|
+
dns.promises.reverse with caching x 8,533,071 ops/sec ±0.84% (81 runs sampled)
|
|
769
|
+
dns.promises.reverse without caching x 67.08 ops/sec ±0.82% (79 runs sampled)
|
|
770
|
+
Fastest without caching is: resolver.reverse without caching
|
|
771
|
+
```
|
|
772
|
+
|
|
677
773
|
##### Node.js v24.12.0
|
|
678
774
|
|
|
679
775
|
**lookup:**
|
|
@@ -712,6 +808,141 @@ Fastest without caching is: tangerine.resolve GET without caching using Google
|
|
|
712
808
|
spawnSync /bin/sh ETIMEDOUT
|
|
713
809
|
```
|
|
714
810
|
|
|
811
|
+
##### Node.js v24.13.0
|
|
812
|
+
|
|
813
|
+
**lookup:**
|
|
814
|
+
|
|
815
|
+
```text
|
|
816
|
+
Started: lookup
|
|
817
|
+
tangerine.lookup POST with caching using Cloudflare x 330,489 ops/sec ±1.61% (85 runs sampled)
|
|
818
|
+
tangerine.lookup POST without caching using Cloudflare x 248 ops/sec ±1.98% (80 runs sampled)
|
|
819
|
+
tangerine.lookup GET with caching using Cloudflare x 321,967 ops/sec ±0.26% (90 runs sampled)
|
|
820
|
+
tangerine.lookup GET without caching using Cloudflare x 224 ops/sec ±1.85% (76 runs sampled)
|
|
821
|
+
dns.promises.lookup with caching using Cloudflare x 734 ops/sec ±195.99% (87 runs sampled)
|
|
822
|
+
dns.promises.lookup without caching using Cloudflare x 2,207 ops/sec ±0.51% (85 runs sampled)
|
|
823
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
**resolve:**
|
|
827
|
+
|
|
828
|
+
```text
|
|
829
|
+
Started: resolve
|
|
830
|
+
tangerine.resolve POST with caching using Cloudflare x 1,158,368 ops/sec ±0.28% (90 runs sampled)
|
|
831
|
+
tangerine.resolve POST without caching using Cloudflare x 246 ops/sec ±1.93% (80 runs sampled)
|
|
832
|
+
tangerine.resolve GET with caching using Cloudflare x 1,114,486 ops/sec ±0.29% (88 runs sampled)
|
|
833
|
+
tangerine.resolve GET without caching using Cloudflare x 252 ops/sec ±1.20% (85 runs sampled)
|
|
834
|
+
tangerine.resolve POST with caching using Google x 1,134,382 ops/sec ±0.24% (88 runs sampled)
|
|
835
|
+
tangerine.resolve POST without caching using Google x 168 ops/sec ±36.15% (70 runs sampled)
|
|
836
|
+
tangerine.resolve GET with caching using Google x 1,139,056 ops/sec ±0.61% (90 runs sampled)
|
|
837
|
+
tangerine.resolve GET without caching using Google x 297 ops/sec ±2.73% (75 runs sampled)
|
|
838
|
+
resolver.resolve with caching using Cloudflare x 8,289,380 ops/sec ±7.32% (88 runs sampled)
|
|
839
|
+
resolver.resolve without caching using Cloudflare x 316 ops/sec ±1.92% (79 runs sampled)
|
|
840
|
+
Fastest without caching is: resolver.resolve without caching using Cloudflare
|
|
841
|
+
```
|
|
842
|
+
|
|
843
|
+
**reverse:**
|
|
844
|
+
|
|
845
|
+
```text
|
|
846
|
+
Started: reverse
|
|
847
|
+
tangerine.reverse GET with caching x 339,770 ops/sec ±0.42% (90 runs sampled)
|
|
848
|
+
tangerine.reverse GET without caching x 240 ops/sec ±2.18% (77 runs sampled)
|
|
849
|
+
resolver.reverse with caching x 8,523,002 ops/sec ±0.83% (87 runs sampled)
|
|
850
|
+
resolver.reverse without caching x 15.57 ops/sec ±194.42% (31 runs sampled)
|
|
851
|
+
dns.promises.reverse with caching x 8,765,472 ops/sec ±1.03% (82 runs sampled)
|
|
852
|
+
dns.promises.reverse without caching x 5.51 ops/sec ±179.54% (80 runs sampled)
|
|
853
|
+
Fastest without caching is: tangerine.reverse GET without caching
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
##### Node.js v24.13.1
|
|
857
|
+
|
|
858
|
+
**lookup:**
|
|
859
|
+
|
|
860
|
+
```text
|
|
861
|
+
Started: lookup
|
|
862
|
+
tangerine.lookup POST with caching using Cloudflare x 333,315 ops/sec ±1.61% (85 runs sampled)
|
|
863
|
+
tangerine.lookup POST without caching using Cloudflare x 227 ops/sec ±1.93% (82 runs sampled)
|
|
864
|
+
tangerine.lookup GET with caching using Cloudflare x 320,901 ops/sec ±0.68% (90 runs sampled)
|
|
865
|
+
tangerine.lookup GET without caching using Cloudflare x 262 ops/sec ±2.60% (81 runs sampled)
|
|
866
|
+
dns.promises.lookup with caching using Cloudflare x 10,104,926 ops/sec ±1.20% (84 runs sampled)
|
|
867
|
+
dns.promises.lookup without caching using Cloudflare x 2,172 ops/sec ±0.39% (86 runs sampled)
|
|
868
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
**resolve:**
|
|
872
|
+
|
|
873
|
+
```text
|
|
874
|
+
Started: resolve
|
|
875
|
+
tangerine.resolve POST with caching using Cloudflare x 1,155,993 ops/sec ±0.68% (89 runs sampled)
|
|
876
|
+
tangerine.resolve POST without caching using Cloudflare x 238 ops/sec ±1.44% (82 runs sampled)
|
|
877
|
+
tangerine.resolve GET with caching using Cloudflare x 1,130,246 ops/sec ±0.43% (89 runs sampled)
|
|
878
|
+
tangerine.resolve GET without caching using Cloudflare x 271 ops/sec ±1.13% (85 runs sampled)
|
|
879
|
+
tangerine.resolve POST with caching using Google x 534 ops/sec ±195.91% (89 runs sampled)
|
|
880
|
+
tangerine.resolve POST without caching using Google x 180 ops/sec ±23.75% (71 runs sampled)
|
|
881
|
+
tangerine.resolve GET with caching using Google x 1,127,220 ops/sec ±0.26% (91 runs sampled)
|
|
882
|
+
tangerine.resolve GET without caching using Google x 194 ops/sec ±16.84% (63 runs sampled)
|
|
883
|
+
resolver.resolve with caching using Cloudflare x 8,475,317 ops/sec ±0.93% (83 runs sampled)
|
|
884
|
+
resolver.resolve without caching using Cloudflare x 345 ops/sec ±1.00% (78 runs sampled)
|
|
885
|
+
Fastest without caching is: resolver.resolve without caching using Cloudflare
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
**reverse:**
|
|
889
|
+
|
|
890
|
+
```text
|
|
891
|
+
Started: reverse
|
|
892
|
+
tangerine.reverse GET with caching x 331,840 ops/sec ±0.57% (89 runs sampled)
|
|
893
|
+
tangerine.reverse GET without caching x 241 ops/sec ±1.30% (80 runs sampled)
|
|
894
|
+
resolver.reverse with caching x 8,769,670 ops/sec ±0.60% (87 runs sampled)
|
|
895
|
+
resolver.reverse without caching x 24.95 ops/sec ±193.07% (22 runs sampled)
|
|
896
|
+
dns.promises.reverse with caching x 8,895,968 ops/sec ±0.71% (88 runs sampled)
|
|
897
|
+
dns.promises.reverse without caching x 0.05 ops/sec ±112.55% (5 runs sampled)
|
|
898
|
+
Fastest without caching is: tangerine.reverse GET without caching
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
##### Node.js v24.14.0
|
|
902
|
+
|
|
903
|
+
**lookup:**
|
|
904
|
+
|
|
905
|
+
```text
|
|
906
|
+
Started: lookup
|
|
907
|
+
tangerine.lookup POST with caching using Cloudflare x 1,403 ops/sec ±195.16% (90 runs sampled)
|
|
908
|
+
tangerine.lookup POST without caching using Cloudflare x 70.67 ops/sec ±3.34% (84 runs sampled)
|
|
909
|
+
tangerine.lookup GET with caching using Cloudflare x 317,797 ops/sec ±0.25% (91 runs sampled)
|
|
910
|
+
tangerine.lookup GET without caching using Cloudflare x 63.36 ops/sec ±6.51% (78 runs sampled)
|
|
911
|
+
dns.promises.lookup with caching using Cloudflare x 9,932,885 ops/sec ±1.21% (87 runs sampled)
|
|
912
|
+
dns.promises.lookup without caching using Cloudflare x 2,310 ops/sec ±0.39% (89 runs sampled)
|
|
913
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
**resolve:**
|
|
917
|
+
|
|
918
|
+
```text
|
|
919
|
+
Started: resolve
|
|
920
|
+
tangerine.resolve POST with caching using Cloudflare x 1,269 ops/sec ±195.78% (89 runs sampled)
|
|
921
|
+
tangerine.resolve POST without caching using Cloudflare x 85.54 ops/sec ±0.68% (81 runs sampled)
|
|
922
|
+
tangerine.resolve GET with caching using Cloudflare x 1,117,794 ops/sec ±0.40% (90 runs sampled)
|
|
923
|
+
tangerine.resolve GET without caching using Cloudflare x 69.12 ops/sec ±5.91% (84 runs sampled)
|
|
924
|
+
tangerine.resolve POST with caching using Google x 1,675 ops/sec ±195.71% (90 runs sampled)
|
|
925
|
+
tangerine.resolve POST without caching using Google x 57.66 ops/sec ±13.41% (79 runs sampled)
|
|
926
|
+
tangerine.resolve GET with caching using Google x 1,117,350 ops/sec ±0.62% (90 runs sampled)
|
|
927
|
+
tangerine.resolve GET without caching using Google x 56.23 ops/sec ±5.75% (72 runs sampled)
|
|
928
|
+
resolver.resolve with caching using Cloudflare x 8,740,674 ops/sec ±0.82% (83 runs sampled)
|
|
929
|
+
resolver.resolve without caching using Cloudflare x 71.31 ops/sec ±1.31% (72 runs sampled)
|
|
930
|
+
Fastest without caching is: tangerine.resolve POST without caching using Cloudflare
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
**reverse:**
|
|
934
|
+
|
|
935
|
+
```text
|
|
936
|
+
Started: reverse
|
|
937
|
+
tangerine.reverse GET with caching x 1,286 ops/sec ±195.26% (90 runs sampled)
|
|
938
|
+
tangerine.reverse GET without caching x 85.95 ops/sec ±0.80% (81 runs sampled)
|
|
939
|
+
resolver.reverse with caching x 8,753,410 ops/sec ±0.98% (85 runs sampled)
|
|
940
|
+
resolver.reverse without caching x 72.25 ops/sec ±1.42% (74 runs sampled)
|
|
941
|
+
dns.promises.reverse with caching x 8,707,156 ops/sec ±0.92% (84 runs sampled)
|
|
942
|
+
dns.promises.reverse without caching x 71.90 ops/sec ±1.46% (70 runs sampled)
|
|
943
|
+
Fastest without caching is: tangerine.reverse GET without caching
|
|
944
|
+
```
|
|
945
|
+
|
|
715
946
|
##### Node.js v25.2.1
|
|
716
947
|
|
|
717
948
|
**lookup:**
|
|
@@ -757,6 +988,321 @@ dns.promises.reverse without caching x 5.11 ops/sec ±189.52% (76 runs sampled)
|
|
|
757
988
|
Fastest without caching is: resolver.reverse without caching, dns.promises.reverse without caching
|
|
758
989
|
```
|
|
759
990
|
|
|
991
|
+
##### Node.js v25.3.0
|
|
992
|
+
|
|
993
|
+
**lookup:**
|
|
994
|
+
|
|
995
|
+
```text
|
|
996
|
+
Started: lookup
|
|
997
|
+
tangerine.lookup POST with caching using Cloudflare x 1,178 ops/sec ±195.33% (88 runs sampled)
|
|
998
|
+
tangerine.lookup POST without caching using Cloudflare x 86.96 ops/sec ±1.37% (82 runs sampled)
|
|
999
|
+
tangerine.lookup GET with caching using Cloudflare x 340,510 ops/sec ±0.25% (90 runs sampled)
|
|
1000
|
+
tangerine.lookup GET without caching using Cloudflare x 89.52 ops/sec ±1.42% (84 runs sampled)
|
|
1001
|
+
dns.promises.lookup with caching using Cloudflare x 1,352 ops/sec ±195.97% (88 runs sampled)
|
|
1002
|
+
dns.promises.lookup without caching using Cloudflare x 3,261 ops/sec ±0.86% (83 runs sampled)
|
|
1003
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
**resolve:**
|
|
1007
|
+
|
|
1008
|
+
```text
|
|
1009
|
+
Started: resolve
|
|
1010
|
+
tangerine.resolve POST with caching using Cloudflare x 1,099 ops/sec ±195.82% (89 runs sampled)
|
|
1011
|
+
tangerine.resolve POST without caching using Cloudflare x 88.57 ops/sec ±0.78% (83 runs sampled)
|
|
1012
|
+
tangerine.resolve GET with caching using Cloudflare x 1,182,619 ops/sec ±0.51% (91 runs sampled)
|
|
1013
|
+
tangerine.resolve GET without caching using Cloudflare x 89.35 ops/sec ±9.03% (88 runs sampled)
|
|
1014
|
+
tangerine.resolve POST with caching using Google x 1,174,915 ops/sec ±2.35% (89 runs sampled)
|
|
1015
|
+
tangerine.resolve POST without caching using Google x 129 ops/sec ±9.63% (75 runs sampled)
|
|
1016
|
+
tangerine.resolve GET with caching using Google x 1,187,141 ops/sec ±0.30% (89 runs sampled)
|
|
1017
|
+
tangerine.resolve GET without caching using Google x 195 ops/sec ±0.85% (84 runs sampled)
|
|
1018
|
+
resolver.resolve with caching using Cloudflare x 8,288,775 ops/sec ±10.11% (89 runs sampled)
|
|
1019
|
+
resolver.resolve without caching using Cloudflare x 105 ops/sec ±0.63% (82 runs sampled)
|
|
1020
|
+
Fastest without caching is: tangerine.resolve GET without caching using Google
|
|
1021
|
+
```
|
|
1022
|
+
|
|
1023
|
+
**reverse:**
|
|
1024
|
+
|
|
1025
|
+
```text
|
|
1026
|
+
Started: reverse
|
|
1027
|
+
tangerine.reverse GET with caching x 1,146 ops/sec ±195.30% (90 runs sampled)
|
|
1028
|
+
tangerine.reverse GET without caching x 88.05 ops/sec ±0.92% (83 runs sampled)
|
|
1029
|
+
resolver.reverse with caching x 8,812,418 ops/sec ±0.46% (85 runs sampled)
|
|
1030
|
+
resolver.reverse without caching x 3.08 ops/sec ±203.97% (19 runs sampled)
|
|
1031
|
+
dns.promises.reverse with caching x 8,647,756 ops/sec ±2.62% (87 runs sampled)
|
|
1032
|
+
dns.promises.reverse without caching x 0.09 ops/sec ±139.17% (6 runs sampled)
|
|
1033
|
+
Fastest without caching is: tangerine.reverse GET without caching
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
##### Node.js v25.4.0
|
|
1037
|
+
|
|
1038
|
+
**lookup:**
|
|
1039
|
+
|
|
1040
|
+
```text
|
|
1041
|
+
Started: lookup
|
|
1042
|
+
tangerine.lookup POST with caching using Cloudflare x 338,506 ops/sec ±2.96% (86 runs sampled)
|
|
1043
|
+
tangerine.lookup POST without caching using Cloudflare x 252 ops/sec ±1.53% (83 runs sampled)
|
|
1044
|
+
tangerine.lookup GET with caching using Cloudflare x 328,384 ops/sec ±0.24% (89 runs sampled)
|
|
1045
|
+
tangerine.lookup GET without caching using Cloudflare x 256 ops/sec ±2.15% (80 runs sampled)
|
|
1046
|
+
dns.promises.lookup with caching using Cloudflare x 10,091,995 ops/sec ±0.78% (85 runs sampled)
|
|
1047
|
+
dns.promises.lookup without caching using Cloudflare x 3,114 ops/sec ±0.68% (84 runs sampled)
|
|
1048
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
**resolve:**
|
|
1052
|
+
|
|
1053
|
+
```text
|
|
1054
|
+
Started: resolve
|
|
1055
|
+
tangerine.resolve POST with caching using Cloudflare x 1,178,120 ops/sec ±0.63% (89 runs sampled)
|
|
1056
|
+
tangerine.resolve POST without caching using Cloudflare x 268 ops/sec ±1.42% (84 runs sampled)
|
|
1057
|
+
tangerine.resolve GET with caching using Cloudflare x 1,158,024 ops/sec ±0.37% (88 runs sampled)
|
|
1058
|
+
tangerine.resolve GET without caching using Cloudflare x 263 ops/sec ±1.56% (82 runs sampled)
|
|
1059
|
+
tangerine.resolve POST with caching using Google x 1,126,115 ops/sec ±2.39% (89 runs sampled)
|
|
1060
|
+
tangerine.resolve POST without caching using Google x 203 ops/sec ±1.10% (85 runs sampled)
|
|
1061
|
+
tangerine.resolve GET with caching using Google x 1,124,263 ops/sec ±3.04% (88 runs sampled)
|
|
1062
|
+
tangerine.resolve GET without caching using Google x 231 ops/sec ±0.71% (85 runs sampled)
|
|
1063
|
+
resolver.resolve with caching using Cloudflare x 8,795,845 ops/sec ±0.45% (87 runs sampled)
|
|
1064
|
+
resolver.resolve without caching using Cloudflare x 299 ops/sec ±1.31% (69 runs sampled)
|
|
1065
|
+
Fastest without caching is: resolver.resolve without caching using Cloudflare
|
|
1066
|
+
```
|
|
1067
|
+
|
|
1068
|
+
**reverse:**
|
|
1069
|
+
|
|
1070
|
+
```text
|
|
1071
|
+
Started: reverse
|
|
1072
|
+
tangerine.reverse GET with caching x 346,432 ops/sec ±0.67% (87 runs sampled)
|
|
1073
|
+
tangerine.reverse GET without caching x 257 ops/sec ±1.24% (83 runs sampled)
|
|
1074
|
+
resolver.reverse with caching x 8,836,675 ops/sec ±0.85% (83 runs sampled)
|
|
1075
|
+
resolver.reverse without caching x 11.00 ops/sec ±189.21% (38 runs sampled)
|
|
1076
|
+
dns.promises.reverse with caching x 8,483,041 ops/sec ±1.55% (84 runs sampled)
|
|
1077
|
+
dns.promises.reverse without caching x 1.79 ops/sec ±162.11% (82 runs sampled)
|
|
1078
|
+
Fastest without caching is: tangerine.reverse GET without caching
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
##### Node.js v25.5.0
|
|
1082
|
+
|
|
1083
|
+
**lookup:**
|
|
1084
|
+
|
|
1085
|
+
```text
|
|
1086
|
+
Started: lookup
|
|
1087
|
+
tangerine.lookup POST with caching using Cloudflare x 336,308 ops/sec ±3.97% (90 runs sampled)
|
|
1088
|
+
tangerine.lookup POST without caching using Cloudflare x 142 ops/sec ±24.14% (42 runs sampled)
|
|
1089
|
+
tangerine.lookup GET with caching using Cloudflare x 331,518 ops/sec ±0.25% (90 runs sampled)
|
|
1090
|
+
tangerine.lookup GET without caching using Cloudflare x 317 ops/sec ±5.55% (84 runs sampled)
|
|
1091
|
+
dns.promises.lookup with caching using Cloudflare x 10,144,557 ops/sec ±0.80% (85 runs sampled)
|
|
1092
|
+
dns.promises.lookup without caching using Cloudflare x 3,269 ops/sec ±0.69% (84 runs sampled)
|
|
1093
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
1094
|
+
```
|
|
1095
|
+
|
|
1096
|
+
**resolve:**
|
|
1097
|
+
|
|
1098
|
+
```text
|
|
1099
|
+
Started: resolve
|
|
1100
|
+
tangerine.resolve POST with caching using Cloudflare x 1,173,581 ops/sec ±0.26% (90 runs sampled)
|
|
1101
|
+
tangerine.resolve POST without caching using Cloudflare x 336 ops/sec ±1.29% (83 runs sampled)
|
|
1102
|
+
tangerine.resolve GET with caching using Cloudflare x 1,154,032 ops/sec ±0.25% (90 runs sampled)
|
|
1103
|
+
tangerine.resolve GET without caching using Cloudflare x 211 ops/sec ±21.96% (60 runs sampled)
|
|
1104
|
+
tangerine.resolve POST with caching using Google x 1,143,112 ops/sec ±2.40% (87 runs sampled)
|
|
1105
|
+
tangerine.resolve POST without caching using Google x 247 ops/sec ±18.82% (74 runs sampled)
|
|
1106
|
+
tangerine.resolve GET with caching using Google x 1,169,919 ops/sec ±0.28% (90 runs sampled)
|
|
1107
|
+
tangerine.resolve GET without caching using Google x 312 ops/sec ±9.26% (78 runs sampled)
|
|
1108
|
+
resolver.resolve with caching using Cloudflare x 8,264,910 ops/sec ±3.31% (82 runs sampled)
|
|
1109
|
+
resolver.resolve without caching using Cloudflare x 322 ops/sec ±40.27% (68 runs sampled)
|
|
1110
|
+
Fastest without caching is: tangerine.resolve POST without caching using Cloudflare, tangerine.resolve GET without caching using Google
|
|
1111
|
+
```
|
|
1112
|
+
|
|
1113
|
+
**reverse:**
|
|
1114
|
+
|
|
1115
|
+
```text
|
|
1116
|
+
Started: reverse
|
|
1117
|
+
tangerine.reverse GET with caching x 337,763 ops/sec ±4.41% (90 runs sampled)
|
|
1118
|
+
tangerine.reverse GET without caching x 334 ops/sec ±1.57% (82 runs sampled)
|
|
1119
|
+
resolver.reverse with caching x 8,764,547 ops/sec ±1.05% (84 runs sampled)
|
|
1120
|
+
resolver.reverse without caching x 20.89 ops/sec ±188.69% (22 runs sampled)
|
|
1121
|
+
dns.promises.reverse with caching x 8,832,576 ops/sec ±0.52% (87 runs sampled)
|
|
1122
|
+
dns.promises.reverse without caching x 6.82 ops/sec ±176.67% (70 runs sampled)
|
|
1123
|
+
Fastest without caching is: tangerine.reverse GET without caching
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
##### Node.js v25.6.0
|
|
1127
|
+
|
|
1128
|
+
**lookup:**
|
|
1129
|
+
|
|
1130
|
+
```text
|
|
1131
|
+
Started: lookup
|
|
1132
|
+
tangerine.lookup POST with caching using Cloudflare x 1,022 ops/sec ±195.41% (85 runs sampled)
|
|
1133
|
+
tangerine.lookup POST without caching using Cloudflare x 46.93 ops/sec ±6.02% (78 runs sampled)
|
|
1134
|
+
tangerine.lookup GET with caching using Cloudflare x 329,068 ops/sec ±1.17% (87 runs sampled)
|
|
1135
|
+
tangerine.lookup GET without caching using Cloudflare x 47.00 ops/sec ±5.36% (77 runs sampled)
|
|
1136
|
+
dns.promises.lookup with caching using Cloudflare x 10,120,744 ops/sec ±2.31% (81 runs sampled)
|
|
1137
|
+
dns.promises.lookup without caching using Cloudflare x 3,219 ops/sec ±0.75% (85 runs sampled)
|
|
1138
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
**resolve:**
|
|
1142
|
+
|
|
1143
|
+
```text
|
|
1144
|
+
Started: resolve
|
|
1145
|
+
tangerine.resolve POST with caching using Cloudflare x 1,127 ops/sec ±195.81% (89 runs sampled)
|
|
1146
|
+
tangerine.resolve POST without caching using Cloudflare x 47.64 ops/sec ±5.35% (78 runs sampled)
|
|
1147
|
+
tangerine.resolve GET with caching using Cloudflare x 1,183,153 ops/sec ±0.42% (90 runs sampled)
|
|
1148
|
+
tangerine.resolve GET without caching using Cloudflare x 47.85 ops/sec ±5.73% (79 runs sampled)
|
|
1149
|
+
tangerine.resolve POST with caching using Google x 1,167 ops/sec ±195.80% (90 runs sampled)
|
|
1150
|
+
tangerine.resolve POST without caching using Google x 52.32 ops/sec ±14.47% (67 runs sampled)
|
|
1151
|
+
tangerine.resolve GET with caching using Google x 1,168,373 ops/sec ±2.94% (89 runs sampled)
|
|
1152
|
+
tangerine.resolve GET without caching using Google x 61.96 ops/sec ±11.75% (66 runs sampled)
|
|
1153
|
+
resolver.resolve with caching using Cloudflare x 8,658,908 ops/sec ±0.86% (83 runs sampled)
|
|
1154
|
+
resolver.resolve without caching using Cloudflare x 53.79 ops/sec ±0.56% (84 runs sampled)
|
|
1155
|
+
Fastest without caching is: tangerine.resolve GET without caching using Google
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
**reverse:**
|
|
1159
|
+
|
|
1160
|
+
```text
|
|
1161
|
+
Started: reverse
|
|
1162
|
+
tangerine.reverse GET with caching x 1,107 ops/sec ±195.37% (90 runs sampled)
|
|
1163
|
+
tangerine.reverse GET without caching x 47.62 ops/sec ±5.44% (78 runs sampled)
|
|
1164
|
+
resolver.reverse with caching x 8,843,572 ops/sec ±1.73% (86 runs sampled)
|
|
1165
|
+
resolver.reverse without caching x 53.71 ops/sec ±0.41% (84 runs sampled)
|
|
1166
|
+
dns.promises.reverse with caching x 8,869,703 ops/sec ±2.34% (85 runs sampled)
|
|
1167
|
+
dns.promises.reverse without caching x 54.03 ops/sec ±0.34% (85 runs sampled)
|
|
1168
|
+
Fastest without caching is: dns.promises.reverse without caching
|
|
1169
|
+
```
|
|
1170
|
+
|
|
1171
|
+
##### Node.js v25.6.1
|
|
1172
|
+
|
|
1173
|
+
**lookup:**
|
|
1174
|
+
|
|
1175
|
+
```text
|
|
1176
|
+
Started: lookup
|
|
1177
|
+
tangerine.lookup POST with caching using Cloudflare x 1,041 ops/sec ±195.41% (90 runs sampled)
|
|
1178
|
+
tangerine.lookup POST without caching using Cloudflare x 46.90 ops/sec ±7.12% (78 runs sampled)
|
|
1179
|
+
tangerine.lookup GET with caching using Cloudflare x 329,597 ops/sec ±1.03% (89 runs sampled)
|
|
1180
|
+
tangerine.lookup GET without caching using Cloudflare x 47.84 ops/sec ±5.63% (79 runs sampled)
|
|
1181
|
+
dns.promises.lookup with caching using Cloudflare x 10,033,729 ops/sec ±1.66% (86 runs sampled)
|
|
1182
|
+
dns.promises.lookup without caching using Cloudflare x 3,175 ops/sec ±0.61% (87 runs sampled)
|
|
1183
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
**resolve:**
|
|
1187
|
+
|
|
1188
|
+
```text
|
|
1189
|
+
Started: resolve
|
|
1190
|
+
tangerine.resolve POST with caching using Cloudflare x 1,066 ops/sec ±195.81% (86 runs sampled)
|
|
1191
|
+
tangerine.resolve POST without caching using Cloudflare x 48.96 ops/sec ±6.55% (81 runs sampled)
|
|
1192
|
+
tangerine.resolve GET with caching using Cloudflare x 1,133,219 ops/sec ±0.30% (90 runs sampled)
|
|
1193
|
+
tangerine.resolve GET without caching using Cloudflare x 47.66 ops/sec ±5.34% (79 runs sampled)
|
|
1194
|
+
tangerine.resolve POST with caching using Google x 1,132 ops/sec ±195.81% (89 runs sampled)
|
|
1195
|
+
tangerine.resolve POST without caching using Google x 48.55 ops/sec ±13.69% (66 runs sampled)
|
|
1196
|
+
tangerine.resolve GET with caching using Google x 1,130,722 ops/sec ±2.88% (89 runs sampled)
|
|
1197
|
+
tangerine.resolve GET without caching using Google x 53.90 ops/sec ±10.91% (67 runs sampled)
|
|
1198
|
+
resolver.resolve with caching using Cloudflare x 8,443,169 ops/sec ±2.56% (86 runs sampled)
|
|
1199
|
+
resolver.resolve without caching using Cloudflare x 53.86 ops/sec ±0.65% (84 runs sampled)
|
|
1200
|
+
Fastest without caching is: resolver.resolve without caching using Cloudflare
|
|
1201
|
+
```
|
|
1202
|
+
|
|
1203
|
+
**reverse:**
|
|
1204
|
+
|
|
1205
|
+
```text
|
|
1206
|
+
Started: reverse
|
|
1207
|
+
tangerine.reverse GET with caching x 1,105 ops/sec ±195.39% (89 runs sampled)
|
|
1208
|
+
tangerine.reverse GET without caching x 48.86 ops/sec ±6.37% (80 runs sampled)
|
|
1209
|
+
resolver.reverse with caching x 8,883,018 ops/sec ±0.41% (86 runs sampled)
|
|
1210
|
+
resolver.reverse without caching x 54.19 ops/sec ±0.53% (85 runs sampled)
|
|
1211
|
+
dns.promises.reverse with caching x 8,752,480 ops/sec ±2.56% (86 runs sampled)
|
|
1212
|
+
dns.promises.reverse without caching x 54.28 ops/sec ±0.35% (85 runs sampled)
|
|
1213
|
+
Fastest without caching is: dns.promises.reverse without caching, resolver.reverse without caching
|
|
1214
|
+
```
|
|
1215
|
+
|
|
1216
|
+
##### Node.js v25.7.0
|
|
1217
|
+
|
|
1218
|
+
**lookup:**
|
|
1219
|
+
|
|
1220
|
+
```text
|
|
1221
|
+
Started: lookup
|
|
1222
|
+
tangerine.lookup POST with caching using Cloudflare x 873 ops/sec ±195.51% (87 runs sampled)
|
|
1223
|
+
tangerine.lookup POST without caching using Cloudflare x 58.82 ops/sec ±7.44% (74 runs sampled)
|
|
1224
|
+
tangerine.lookup GET with caching using Cloudflare x 333,990 ops/sec ±1.19% (86 runs sampled)
|
|
1225
|
+
tangerine.lookup GET without caching using Cloudflare x 53.11 ops/sec ±10.66% (70 runs sampled)
|
|
1226
|
+
dns.promises.lookup with caching using Cloudflare x 626 ops/sec ±195.99% (86 runs sampled)
|
|
1227
|
+
dns.promises.lookup without caching using Cloudflare x 2,470 ops/sec ±0.50% (87 runs sampled)
|
|
1228
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
1229
|
+
```
|
|
1230
|
+
|
|
1231
|
+
**resolve:**
|
|
1232
|
+
|
|
1233
|
+
```text
|
|
1234
|
+
Started: resolve
|
|
1235
|
+
tangerine.resolve POST with caching using Cloudflare x 1,243 ops/sec ±195.79% (89 runs sampled)
|
|
1236
|
+
tangerine.resolve POST without caching using Cloudflare x 57.08 ops/sec ±11.16% (74 runs sampled)
|
|
1237
|
+
tangerine.resolve GET with caching using Cloudflare x 1,132,703 ops/sec ±0.28% (90 runs sampled)
|
|
1238
|
+
tangerine.resolve GET without caching using Cloudflare x 56.05 ops/sec ±5.64% (80 runs sampled)
|
|
1239
|
+
tangerine.resolve POST with caching using Google x 1,497 ops/sec ±195.73% (88 runs sampled)
|
|
1240
|
+
tangerine.resolve POST without caching using Google x 60.56 ops/sec ±7.75% (77 runs sampled)
|
|
1241
|
+
tangerine.resolve GET with caching using Google x 1,096,216 ops/sec ±2.92% (88 runs sampled)
|
|
1242
|
+
tangerine.resolve GET without caching using Google x 41.16 ops/sec ±24.89% (66 runs sampled)
|
|
1243
|
+
resolver.resolve with caching using Cloudflare x 8,732,718 ops/sec ±2.67% (86 runs sampled)
|
|
1244
|
+
resolver.resolve without caching using Cloudflare x 65.84 ops/sec ±1.17% (78 runs sampled)
|
|
1245
|
+
Fastest without caching is: resolver.resolve without caching using Cloudflare, tangerine.resolve POST without caching using Google
|
|
1246
|
+
```
|
|
1247
|
+
|
|
1248
|
+
**reverse:**
|
|
1249
|
+
|
|
1250
|
+
```text
|
|
1251
|
+
Started: reverse
|
|
1252
|
+
tangerine.reverse GET with caching x 1,193 ops/sec ±195.33% (88 runs sampled)
|
|
1253
|
+
tangerine.reverse GET without caching x 56.89 ops/sec ±11.00% (73 runs sampled)
|
|
1254
|
+
resolver.reverse with caching x 8,938,970 ops/sec ±0.65% (88 runs sampled)
|
|
1255
|
+
resolver.reverse without caching x 66.14 ops/sec ±2.95% (78 runs sampled)
|
|
1256
|
+
dns.promises.reverse with caching x 8,783,854 ops/sec ±1.77% (87 runs sampled)
|
|
1257
|
+
dns.promises.reverse without caching x 67.14 ops/sec ±0.80% (79 runs sampled)
|
|
1258
|
+
Fastest without caching is: dns.promises.reverse without caching, resolver.reverse without caching
|
|
1259
|
+
```
|
|
1260
|
+
|
|
1261
|
+
##### Node.js v25.8.0
|
|
1262
|
+
|
|
1263
|
+
**lookup:**
|
|
1264
|
+
|
|
1265
|
+
```text
|
|
1266
|
+
Started: lookup
|
|
1267
|
+
tangerine.lookup POST with caching using Cloudflare x 348,234 ops/sec ±1.43% (89 runs sampled)
|
|
1268
|
+
tangerine.lookup POST without caching using Cloudflare x 245 ops/sec ±1.75% (83 runs sampled)
|
|
1269
|
+
tangerine.lookup GET with caching using Cloudflare x 340,115 ops/sec ±0.72% (89 runs sampled)
|
|
1270
|
+
tangerine.lookup GET without caching using Cloudflare x 223 ops/sec ±2.25% (81 runs sampled)
|
|
1271
|
+
dns.promises.lookup with caching using Cloudflare x 1,759 ops/sec ±195.97% (88 runs sampled)
|
|
1272
|
+
dns.promises.lookup without caching using Cloudflare x 2,223 ops/sec ±0.55% (87 runs sampled)
|
|
1273
|
+
Fastest without caching is: dns.promises.lookup without caching using Cloudflare
|
|
1274
|
+
```
|
|
1275
|
+
|
|
1276
|
+
**resolve:**
|
|
1277
|
+
|
|
1278
|
+
```text
|
|
1279
|
+
Started: resolve
|
|
1280
|
+
tangerine.resolve POST with caching using Cloudflare x 1,224,642 ops/sec ±0.58% (87 runs sampled)
|
|
1281
|
+
tangerine.resolve POST without caching using Cloudflare x 248 ops/sec ±1.54% (83 runs sampled)
|
|
1282
|
+
tangerine.resolve GET with caching using Cloudflare x 1,168,649 ops/sec ±0.55% (85 runs sampled)
|
|
1283
|
+
tangerine.resolve GET without caching using Cloudflare x 264 ops/sec ±1.04% (82 runs sampled)
|
|
1284
|
+
tangerine.resolve POST with caching using Google x 1,411 ops/sec ±195.76% (87 runs sampled)
|
|
1285
|
+
tangerine.resolve POST without caching using Google x 178 ops/sec ±24.83% (67 runs sampled)
|
|
1286
|
+
tangerine.resolve GET with caching using Google x 1,188,395 ops/sec ±0.40% (88 runs sampled)
|
|
1287
|
+
tangerine.resolve GET without caching using Google x 237 ops/sec ±14.93% (74 runs sampled)
|
|
1288
|
+
resolver.resolve with caching using Cloudflare x 8.39 ops/sec ±196.00% (84 runs sampled)
|
|
1289
|
+
resolver.resolve without caching using Cloudflare x 109 ops/sec ±113.88% (68 runs sampled)
|
|
1290
|
+
Fastest without caching is: tangerine.resolve GET without caching using Cloudflare, tangerine.resolve POST without caching using Google
|
|
1291
|
+
```
|
|
1292
|
+
|
|
1293
|
+
**reverse:**
|
|
1294
|
+
|
|
1295
|
+
```text
|
|
1296
|
+
Started: reverse
|
|
1297
|
+
tangerine.reverse GET with caching x 346,448 ops/sec ±4.35% (86 runs sampled)
|
|
1298
|
+
tangerine.reverse GET without caching x 259 ops/sec ±1.42% (83 runs sampled)
|
|
1299
|
+
resolver.reverse with caching x 9,199,217 ops/sec ±0.52% (88 runs sampled)
|
|
1300
|
+
resolver.reverse without caching x 13.67 ops/sec ±188.06% (45 runs sampled)
|
|
1301
|
+
dns.promises.reverse with caching x 9,227,637 ops/sec ±0.33% (89 runs sampled)
|
|
1302
|
+
dns.promises.reverse without caching x 0.07 ops/sec ±133.35% (5 runs sampled)
|
|
1303
|
+
Fastest without caching is: tangerine.reverse GET without caching
|
|
1304
|
+
```
|
|
1305
|
+
|
|
760
1306
|
</details>
|
|
761
1307
|
|
|
762
1308
|
<!-- BENCHMARK_RESULTS_END -->
|
package/index.d.ts
CHANGED
|
@@ -134,6 +134,13 @@ export type TangerineOptions = {
|
|
|
134
134
|
*/
|
|
135
135
|
smartRotate?: boolean;
|
|
136
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Whether to resolve against all configured servers in parallel and return
|
|
139
|
+
* the first successful response.
|
|
140
|
+
* @default false
|
|
141
|
+
*/
|
|
142
|
+
parallelResolution?: boolean;
|
|
143
|
+
|
|
137
144
|
/**
|
|
138
145
|
* Default error message for unsuccessful HTTP responses.
|
|
139
146
|
* @default 'Unsuccessful HTTP response'
|
package/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const hostile = require('hostile');
|
|
|
13
13
|
const ipaddr = require('ipaddr.js');
|
|
14
14
|
const isStream = require('is-stream');
|
|
15
15
|
const mergeOptions = require('merge-options');
|
|
16
|
+
const pAny = require('p-any');
|
|
16
17
|
const pMap = require('p-map');
|
|
17
18
|
const pWaitFor = require('p-wait-for');
|
|
18
19
|
const packet = require('dns-packet');
|
|
@@ -451,6 +452,8 @@ class Tangerine extends dns.promises.Resolver {
|
|
|
451
452
|
returnHTTPErrors: false,
|
|
452
453
|
// whether to smart rotate and bump-to-end servers that have issues
|
|
453
454
|
smartRotate: true,
|
|
455
|
+
// whether to resolve all servers in parallel and use first successful result
|
|
456
|
+
parallelResolution: false,
|
|
454
457
|
// fallback if status code was not found in http.STATUS_CODES
|
|
455
458
|
defaultHTTPErrorMessage: 'Unsuccessful HTTP response'
|
|
456
459
|
},
|
|
@@ -490,6 +493,12 @@ class Tangerine extends dns.promises.Resolver {
|
|
|
490
493
|
if (!['verbatim', 'ipv4first'].includes(this.options.dnsOrder))
|
|
491
494
|
throw new Error('DNS order must be either verbatim or ipv4first');
|
|
492
495
|
|
|
496
|
+
if (this.options.parallelResolution === undefined)
|
|
497
|
+
this.options.parallelResolution = false;
|
|
498
|
+
|
|
499
|
+
if (typeof this.options.parallelResolution !== 'boolean')
|
|
500
|
+
throw new Error('parallelResolution must be a boolean');
|
|
501
|
+
|
|
493
502
|
// if `cache: false` then caching is disabled
|
|
494
503
|
// but note that this doesn't disable `got` dnsCache which is separate
|
|
495
504
|
// so to turn that off, you need to supply `dnsCache: undefined` in `got` object (?)
|
|
@@ -1131,7 +1140,7 @@ class Tangerine extends dns.promises.Resolver {
|
|
|
1131
1140
|
}
|
|
1132
1141
|
|
|
1133
1142
|
// <https://github.com/hildjj/dohdec/tree/main/pkg/dohdec>
|
|
1134
|
-
|
|
1143
|
+
|
|
1135
1144
|
async #query(name, rrtype = 'A', ecsSubnet, abortController) {
|
|
1136
1145
|
if (!dohdec) await pWaitFor(() => Boolean(dohdec));
|
|
1137
1146
|
debug('query', {
|
|
@@ -1158,46 +1167,105 @@ class Tangerine extends dns.promises.Resolver {
|
|
|
1158
1167
|
// <https://github.com/nodejs/node/issues/33353#issuecomment-627259827>
|
|
1159
1168
|
let buffer;
|
|
1160
1169
|
const errors = [];
|
|
1161
|
-
// NOTE: we would have used `p-map-series` but it did not support abort/break
|
|
1162
1170
|
const servers = [...this.options.servers];
|
|
1163
|
-
|
|
1171
|
+
|
|
1172
|
+
const parseBody = async (body) => {
|
|
1173
|
+
// <https://sindresorhus.com/blog/goodbye-nodejs-buffer>
|
|
1174
|
+
if (Buffer.isBuffer(body)) return body;
|
|
1175
|
+
if (typeof body.arrayBuffer === 'function')
|
|
1176
|
+
return Buffer.from(await body.arrayBuffer());
|
|
1177
|
+
if (isStream(body)) return getStream.buffer(body);
|
|
1178
|
+
const err = new TypeError('Unsupported body type');
|
|
1179
|
+
err.body = body;
|
|
1180
|
+
throw err;
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
const getRequestAbortController = (parallelAbortController) => {
|
|
1184
|
+
if (!parallelAbortController)
|
|
1185
|
+
return {
|
|
1186
|
+
requestAbortController: abortController,
|
|
1187
|
+
cleanupAbortController() {}
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
const requestAbortController = new AbortController();
|
|
1191
|
+
const parentSignal = abortController?.signal;
|
|
1192
|
+
const parallelSignal = parallelAbortController.signal;
|
|
1193
|
+
const onAbort = () => {
|
|
1194
|
+
if (!requestAbortController.signal.aborted)
|
|
1195
|
+
requestAbortController.abort(parentSignal.reason);
|
|
1196
|
+
};
|
|
1197
|
+
|
|
1198
|
+
const onParallelAbort = () => {
|
|
1199
|
+
if (!requestAbortController.signal.aborted)
|
|
1200
|
+
requestAbortController.abort(parallelSignal.reason);
|
|
1201
|
+
};
|
|
1202
|
+
|
|
1203
|
+
if (parentSignal?.aborted) onAbort();
|
|
1204
|
+
else if (parentSignal)
|
|
1205
|
+
parentSignal.addEventListener('abort', onAbort, { once: true });
|
|
1206
|
+
|
|
1207
|
+
if (parallelSignal.aborted) onParallelAbort();
|
|
1208
|
+
else
|
|
1209
|
+
parallelSignal.addEventListener('abort', onParallelAbort, {
|
|
1210
|
+
once: true
|
|
1211
|
+
});
|
|
1212
|
+
|
|
1213
|
+
return {
|
|
1214
|
+
requestAbortController,
|
|
1215
|
+
cleanupAbortController() {
|
|
1216
|
+
parentSignal?.removeEventListener('abort', onAbort);
|
|
1217
|
+
parallelSignal.removeEventListener('abort', onParallelAbort);
|
|
1218
|
+
}
|
|
1219
|
+
};
|
|
1220
|
+
};
|
|
1221
|
+
|
|
1222
|
+
const addServerErrors = (server, ipErrors) => {
|
|
1223
|
+
if (ipErrors.length === 0) return;
|
|
1224
|
+
|
|
1225
|
+
// if the `server` had all errors, then remove it and add to end
|
|
1226
|
+
// (this ensures we don't keep retrying servers that keep timing out)
|
|
1227
|
+
// (which improves upon default c-ares behavior)
|
|
1228
|
+
if (this.options.servers.size > 1 && this.options.smartRotate) {
|
|
1229
|
+
const err = this.constructor.combineErrors([
|
|
1230
|
+
new Error('Rotating DNS servers due to issues'),
|
|
1231
|
+
...ipErrors
|
|
1232
|
+
]);
|
|
1233
|
+
this.options.logger.error(err, { server });
|
|
1234
|
+
this.options.servers.delete(server);
|
|
1235
|
+
this.options.servers.add(server);
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
errors.push(...ipErrors);
|
|
1239
|
+
};
|
|
1240
|
+
|
|
1241
|
+
const throwOnNotFound = (err) => {
|
|
1242
|
+
if (err.code === dns.NOTFOUND) throw err;
|
|
1243
|
+
};
|
|
1244
|
+
|
|
1245
|
+
const queryServer = async (server, parallelAbortController) => {
|
|
1164
1246
|
const ipErrors = [];
|
|
1247
|
+
let lastError;
|
|
1248
|
+
|
|
1165
1249
|
for (let i = 0; i < this.options.tries; i++) {
|
|
1250
|
+
const { requestAbortController, cleanupAbortController } =
|
|
1251
|
+
getRequestAbortController(parallelAbortController);
|
|
1252
|
+
|
|
1166
1253
|
try {
|
|
1167
|
-
// <https://github.com/sindresorhus/p-map-series/blob/bc1b9f5e19ed62363bff3d7dc5ecc1fd820ccb51/index.js#L1-L11>
|
|
1168
1254
|
// eslint-disable-next-line no-await-in-loop
|
|
1169
1255
|
const response = await this.#request(
|
|
1170
1256
|
pkt,
|
|
1171
1257
|
server,
|
|
1172
|
-
|
|
1258
|
+
requestAbortController,
|
|
1173
1259
|
this.options.timeout * 2 ** i
|
|
1174
1260
|
);
|
|
1175
1261
|
|
|
1176
|
-
// if aborted signal then returns early
|
|
1177
|
-
// eslint-disable-next-line max-depth
|
|
1178
1262
|
if (response) {
|
|
1179
1263
|
const { body, headers } = response;
|
|
1180
1264
|
const statusCode = response.status || response.statusCode;
|
|
1181
1265
|
debug('response', { statusCode, headers });
|
|
1182
1266
|
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
// <https://sindresorhus.com/blog/goodbye-nodejs-buffer>
|
|
1186
|
-
// eslint-disable-next-line max-depth
|
|
1187
|
-
if (Buffer.isBuffer(body)) buffer = body;
|
|
1188
|
-
else if (typeof body.arrayBuffer === 'function')
|
|
1189
|
-
// eslint-disable-next-line no-await-in-loop
|
|
1190
|
-
buffer = Buffer.from(await body.arrayBuffer());
|
|
1191
|
-
// eslint-disable-next-line no-await-in-loop
|
|
1192
|
-
else if (isStream(body)) buffer = await getStream.buffer(body);
|
|
1193
|
-
else {
|
|
1194
|
-
const err = new TypeError('Unsupported body type');
|
|
1195
|
-
err.body = body;
|
|
1196
|
-
throw err;
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
break;
|
|
1200
|
-
}
|
|
1267
|
+
if (body && statusCode >= 200 && statusCode < 300)
|
|
1268
|
+
return parseBody(body);
|
|
1201
1269
|
|
|
1202
1270
|
// <https://github.com/nodejs/undici/issues/3353>
|
|
1203
1271
|
if (
|
|
@@ -1221,18 +1289,18 @@ class Tangerine extends dns.promises.Resolver {
|
|
|
1221
1289
|
}
|
|
1222
1290
|
} catch (err) {
|
|
1223
1291
|
debug(err);
|
|
1292
|
+
lastError = err;
|
|
1224
1293
|
|
|
1225
1294
|
//
|
|
1226
1295
|
// NOTE: if NOTFOUND error occurs then don't attempt further requests
|
|
1227
1296
|
// <https://nodejs.org/api/dns.html#dnssetserversservers>
|
|
1228
1297
|
//
|
|
1229
1298
|
|
|
1230
|
-
|
|
1299
|
+
throwOnNotFound(err);
|
|
1231
1300
|
|
|
1232
1301
|
if (err.status >= 429) ipErrors.push(err);
|
|
1233
1302
|
|
|
1234
1303
|
// break out of the loop if status code was not retryable
|
|
1235
|
-
|
|
1236
1304
|
if (
|
|
1237
1305
|
!(
|
|
1238
1306
|
err.statusCode &&
|
|
@@ -1241,26 +1309,43 @@ class Tangerine extends dns.promises.Resolver {
|
|
|
1241
1309
|
!(err.code && this.constructor.RETRY_ERROR_CODES.has(err.code))
|
|
1242
1310
|
)
|
|
1243
1311
|
break;
|
|
1312
|
+
} finally {
|
|
1313
|
+
cleanupAbortController();
|
|
1244
1314
|
}
|
|
1245
1315
|
}
|
|
1246
1316
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
// (this ensures we don't keep retrying servers that keep timing out)
|
|
1252
|
-
// (which improves upon default c-ares behavior)
|
|
1253
|
-
if (this.options.servers.size > 1 && this.options.smartRotate) {
|
|
1254
|
-
const err = this.constructor.combineErrors([
|
|
1255
|
-
new Error('Rotating DNS servers due to issues'),
|
|
1256
|
-
...ipErrors
|
|
1257
|
-
]);
|
|
1258
|
-
this.options.logger.error(err, { server });
|
|
1259
|
-
this.options.servers.delete(server);
|
|
1260
|
-
this.options.servers.add(server);
|
|
1261
|
-
}
|
|
1317
|
+
addServerErrors(server, ipErrors);
|
|
1318
|
+
|
|
1319
|
+
throw lastError || new Error(`No response from ${server}`);
|
|
1320
|
+
};
|
|
1262
1321
|
|
|
1263
|
-
|
|
1322
|
+
if (this.options.parallelResolution) {
|
|
1323
|
+
const parallelAbortController = new AbortController();
|
|
1324
|
+
|
|
1325
|
+
try {
|
|
1326
|
+
buffer = await pAny(
|
|
1327
|
+
servers.map((server) =>
|
|
1328
|
+
queryServer(server, parallelAbortController)
|
|
1329
|
+
)
|
|
1330
|
+
);
|
|
1331
|
+
} catch (err) {
|
|
1332
|
+
if (errors.length > 0) throw this.constructor.combineErrors(errors);
|
|
1333
|
+
throw err;
|
|
1334
|
+
} finally {
|
|
1335
|
+
if (!parallelAbortController.signal.aborted)
|
|
1336
|
+
parallelAbortController.abort('CANCELLED');
|
|
1337
|
+
}
|
|
1338
|
+
} else {
|
|
1339
|
+
// NOTE: we would have used `p-map-series` but it did not support abort/break
|
|
1340
|
+
for (const server of servers) {
|
|
1341
|
+
try {
|
|
1342
|
+
// eslint-disable-next-line no-await-in-loop
|
|
1343
|
+
buffer = await queryServer(server);
|
|
1344
|
+
break;
|
|
1345
|
+
} catch (err) {
|
|
1346
|
+
throwOnNotFound(err);
|
|
1347
|
+
debug(err);
|
|
1348
|
+
}
|
|
1264
1349
|
}
|
|
1265
1350
|
}
|
|
1266
1351
|
|
|
@@ -1943,6 +2028,20 @@ class Tangerine extends dns.promises.Resolver {
|
|
|
1943
2028
|
if (result.answers.length === 0 && !options.noThrowOnNODATA)
|
|
1944
2029
|
throw this.constructor.createError(name, rrtype, dns.NODATA);
|
|
1945
2030
|
|
|
2031
|
+
//
|
|
2032
|
+
// RFC 7672 Section 2.2.2: Expose DNSSEC validation status (AD flag)
|
|
2033
|
+
// When options.dnssecSecure is true, return an object with the answers
|
|
2034
|
+
// and a boolean indicating whether the response was DNSSEC-validated.
|
|
2035
|
+
// This allows callers (e.g. mx-connect DANE) to check if the MX host's
|
|
2036
|
+
// zone is signed before attempting TLSA lookups.
|
|
2037
|
+
//
|
|
2038
|
+
if (options?.dnssecSecure) {
|
|
2039
|
+
return {
|
|
2040
|
+
secure: Boolean(result.flag_ad),
|
|
2041
|
+
answers: result.answers
|
|
2042
|
+
};
|
|
2043
|
+
}
|
|
2044
|
+
|
|
1946
2045
|
// filter the answers for the same type
|
|
1947
2046
|
result.answers = result.answers.filter((answer) => answer.type === rrtype);
|
|
1948
2047
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tangerine",
|
|
3
3
|
"description": "Tangerine is the best Node.js drop-in replacement for dns.promises.Resolver using DNS over HTTPS (\"DoH\") via undici with built-in retries, timeouts, smart server rotation, AbortControllers, and caching support for multiple backends (with TTL and purge support).",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.1.1",
|
|
5
5
|
"author": "Forward Email (https://forwardemail.net)",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/forwardemail/nodejs-dns-over-https-tangerine/issues"
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"ipaddr.js": "^2.2.0",
|
|
19
19
|
"is-stream": "2.0.1",
|
|
20
20
|
"merge-options": "3.0.4",
|
|
21
|
+
"p-any": "3",
|
|
21
22
|
"p-map": "4",
|
|
22
23
|
"p-wait-for": "3",
|
|
23
24
|
"port-numbers": "6.0.1",
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"axios": "^1.7.3",
|
|
33
34
|
"benchmark": "^2.1.4",
|
|
34
35
|
"cross-env": "^7.0.3",
|
|
35
|
-
"eslint": "^
|
|
36
|
+
"eslint": "^8.57.1",
|
|
36
37
|
"eslint-config-xo-lass": "^2.0.1",
|
|
37
38
|
"fetch-mock": "^10.1.1",
|
|
38
39
|
"fixpack": "^4.0.0",
|