excon 0.103.0 → 0.112.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c1759dde8542ab4e6147d2c51ce7e674d4fdd46b48f0aed3a77ed823917d336
4
- data.tar.gz: 5c4c66737d283ed9d4d186cd46809c5c2fd0fc346c06564140b39a131fdfb44f
3
+ metadata.gz: a595b595665aaaf9b650c664bca78bdc66ad05b80d7641333ce3acbeb6a80c46
4
+ data.tar.gz: 7200b150fded0987a7c57fb1155580efd0825472f375523ce12e2b0dce2ebf25
5
5
  SHA512:
6
- metadata.gz: 803189e9d2dc991e48114c4f5ec7071ff04e4ea3f88d6872b3bcfe066cda38055c98b44cad83e5b9edabb677684b75c1a673c232303826a87857ba214c75cf6b
7
- data.tar.gz: cab31317bdbc12398a33ce0b4a385584ca5c3e1cd2be2b201fb5e7ac0161b330e235d0ecd489fa304356367ab98fc868cc610d3afaf12bd3b4636ea182cda92e
6
+ metadata.gz: 27c315cb6b11bf5f09bdae2802d033cdee746d8d907c77324535452f03b42fe2f77375530761153062f5fc70f39972858e0dfe82d64edecc7e9ab83135ce93ba
7
+ data.tar.gz: 9c37add84efa4abb2766310f27a4aa7a151e31cc9e53cfdbd321c3aade0909b88d6d9ee0c9dea3accba8761dbb356d6570eb099bf24a52a96ea0576c1217edd9
data/README.md CHANGED
@@ -4,8 +4,8 @@ Usable, fast, simple Ruby HTTP 1.1
4
4
 
5
5
  Excon was designed to be simple, fast and performant. It works great as a general HTTP(s) client and is particularly well suited to usage in API clients.
6
6
 
7
- [![Build Status](https://github.com/excon/excon/actions/workflows/ruby.yml/badge.svg)](https://github.com/excon/excon/actions/workflows/ruby.yml)
8
- [![Gem Version](https://badge.fury.io/rb/excon.svg)](https://badge.fury.io/rb/excon)
7
+ [![Build Status](https://github.com/excon/excon/actions/workflows/ci.yml/badge.svg)](https://github.com/excon/excon/actions/workflows/ci.yml)
8
+ [![Gem Version](https://badge.fury.io/rb/excon.svg)](https://rubygems.org/gems/excon)
9
9
 
10
10
  - [Getting Started](#getting-started)
11
11
  - [Options](#options)
@@ -179,6 +179,10 @@ connection.request(:read_timeout => 360)
179
179
  # set longer write_timeout (default is 60 seconds)
180
180
  connection.request(:write_timeout => 360)
181
181
 
182
+ # set a request timeout in seconds (default is no timeout).
183
+ # the timeout may be an integer or a float to support sub-second granularity (e.g., 1, 60, 0.005 and 3.5).
184
+ connection.request(:timeout => 0.1) # timeout if the entire request takes longer than 100 milliseconds
185
+
182
186
  # Enable the socket option TCP_NODELAY on the underlying socket.
183
187
  #
184
188
  # This can improve response time when sending frequent short
@@ -192,10 +196,20 @@ connection = Excon.new('http://geemus.com/', :connect_timeout => 360)
192
196
  # opt-out of nonblocking operations for performance and/or as a workaround
193
197
  connection = Excon.new('http://geemus.com/', :nonblock => false)
194
198
 
199
+ # DEPRECATED in favour of `resolv_resolver` (see below)
195
200
  # set up desired dns_timeouts for resolving addresses (default is set by Resolv)
196
201
  # it accepts an integer or an array of integers for retrying with different timeouts
197
202
  # see Resolv::DNS#timeouts for more details (https://ruby-doc.org/3.2.2/stdlibs/resolv/Resolv/DNS.html#method-i-timeouts-3D)
198
203
  connection = Excon.new('http://geemus.com/', :dns_timeouts => 3)
204
+
205
+ # set a custom resolver for Resolv
206
+ # you can use custom nameservers and timeouts
207
+ # `timeouts` accepts an integer or an array of integers for retrying with different timeouts
208
+ # see Resolv::DNS#timeouts for more details (https://ruby-doc.org/3.2.2/stdlibs/resolv/Resolv/DNS.html#method-i-timeouts-3D)
209
+ dns_resolver = Resolv::DNS.new(nameserver: ['127.0.0.1'])
210
+ dns_resolver.timeouts = 3
211
+ resolver = Resolv.new([Resolv::Hosts.new, dns_resolver])
212
+ connection = Excon.new('http://geemus.com', :resolv_resolver => resolver)
199
213
  ```
200
214
 
201
215
  ## Chunked Requests
data/data/cacert.pem CHANGED
@@ -1,7 +1,9 @@
1
1
  ##
2
2
  ## Bundle of CA Root Certificates
3
3
  ##
4
- ## Certificate data from Mozilla as of: Tue Aug 22 03:12:04 2023 GMT
4
+ ## Certificate data from Mozilla as of: Tue Sep 24 03:12:04 2024 GMT
5
+ ##
6
+ ## Find updated versions here: https://curl.se/docs/caextract.html
5
7
  ##
6
8
  ## This is a bundle of X.509 certificates of public Certificate Authorities
7
9
  ## (CA). These were automatically extracted from Mozilla's root certificates
@@ -14,7 +16,7 @@
14
16
  ## Just configure this file as the SSLCACertificateFile.
15
17
  ##
16
18
  ## Conversion done with mk-ca-bundle.pl version 1.29.
17
- ## SHA256: 0ff137babc6a5561a9cfbe9f29558972e5b528202681b7d3803d03a3e82922bd
19
+ ## SHA256: 36105b01631f9fc03b1eca779b44a30a1a5890b9bf8dc07ccb001a07301e01cf
18
20
  ##
19
21
 
20
22
 
@@ -200,27 +202,6 @@ vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
200
202
  qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
201
203
  -----END CERTIFICATE-----
202
204
 
203
- Security Communication Root CA
204
- ==============================
205
- -----BEGIN CERTIFICATE-----
206
- MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
207
- U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
208
- HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
209
- U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
210
- ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
211
- 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
212
- DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
213
- 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
214
- DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
215
- JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
216
- DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
217
- 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
218
- mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
219
- s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
220
- 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
221
- FL39vmwLAw==
222
- -----END CERTIFICATE-----
223
-
224
205
  XRamp Global CA Root
225
206
  ====================
226
207
  -----BEGIN CERTIFICATE-----
@@ -669,39 +650,6 @@ YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
669
650
  kpeDMdmztcpHWD9f
670
651
  -----END CERTIFICATE-----
671
652
 
672
- Autoridad de Certificacion Firmaprofesional CIF A62634068
673
- =========================================================
674
- -----BEGIN CERTIFICATE-----
675
- MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
676
- BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
677
- MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
678
- QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
679
- NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
680
- Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
681
- B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
682
- 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
683
- ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
684
- plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
685
- MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
686
- LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
687
- bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
688
- vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
689
- EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
690
- DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
691
- cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
692
- bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
693
- ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
694
- 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
695
- R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
696
- T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
697
- Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
698
- osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
699
- crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
700
- saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
701
- KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
702
- 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
703
- -----END CERTIFICATE-----
704
-
705
653
  Izenpe.com
706
654
  ==========
707
655
  -----BEGIN CERTIFICATE-----
@@ -2654,36 +2602,6 @@ vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+
2654
2602
  CAezNIm8BZ/3Hobui3A=
2655
2603
  -----END CERTIFICATE-----
2656
2604
 
2657
- GLOBALTRUST 2020
2658
- ================
2659
- -----BEGIN CERTIFICATE-----
2660
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
2685
- -----END CERTIFICATE-----
2686
-
2687
2605
  ANF Secure Server Root CA
2688
2606
  =========================
2689
2607
  -----BEGIN CERTIFICATE-----
@@ -3449,3 +3367,300 @@ TFsR0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuYo7Ey7Nmj
3449
3367
  PqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcEoji2jbDwN/zIIX8/syQbPYtuzE2wFg2W
3450
3368
  HYMfRsCbvUOZ58SWLs5fyQ==
3451
3369
  -----END CERTIFICATE-----
3370
+
3371
+ TrustAsia Global Root CA G3
3372
+ ===========================
3373
+ -----BEGIN CERTIFICATE-----
3374
+ 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
3399
+ JQJ6+N1rZdVtTTDIZbpoFGWsJwt0ivKH
3400
+ -----END CERTIFICATE-----
3401
+
3402
+ TrustAsia Global Root CA G4
3403
+ ===========================
3404
+ -----BEGIN CERTIFICATE-----
3405
+ MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMwWjELMAkGA1UE
3406
+ BhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMMG1Ry
3407
+ dXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0yMTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJa
3408
+ MFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQw
3409
+ IgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
3410
+ AATxs8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbwLxYI+hW8
3411
+ m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJijYzBhMA8GA1UdEwEB/wQF
3412
+ MAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mDpm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/
3413
+ pDHel4NZg6ZvccveMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AA
3414
+ bbd+NvBNEU/zy4k6LHiRUKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xk
3415
+ dUfFVZDj/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA==
3416
+ -----END CERTIFICATE-----
3417
+
3418
+ CommScope Public Trust ECC Root-01
3419
+ ==================================
3420
+ -----BEGIN CERTIFICATE-----
3421
+ MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMwTjELMAkGA1UE
3422
+ BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz
3423
+ dCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNaFw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYT
3424
+ AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg
3425
+ RUNDIFJvb3QtMDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLx
3426
+ eP0CflfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJEhRGnSjot
3427
+ 6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
3428
+ A1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggqhkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2
3429
+ Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liW
3430
+ pDVfG2XqYZpwI7UNo5uSUm9poIyNStDuiw7LR47QjRE=
3431
+ -----END CERTIFICATE-----
3432
+
3433
+ CommScope Public Trust ECC Root-02
3434
+ ==================================
3435
+ -----BEGIN CERTIFICATE-----
3436
+ MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMwTjELMAkGA1UE
3437
+ BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz
3438
+ dCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRaFw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYT
3439
+ AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg
3440
+ RUNDIFJvb3QtMDIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/M
3441
+ MDALj2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmUv4RDsNuE
3442
+ SgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
3443
+ A1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggqhkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9
3444
+ Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/nich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs7
3445
+ 3u1Z/GtMMH9ZzkXpc2AVmkzw5l4lIhVtwodZ0LKOag==
3446
+ -----END CERTIFICATE-----
3447
+
3448
+ CommScope Public Trust RSA Root-01
3449
+ ==================================
3450
+ -----BEGIN CERTIFICATE-----
3451
+ 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
3475
+ 6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw
3476
+ -----END CERTIFICATE-----
3477
+
3478
+ CommScope Public Trust RSA Root-02
3479
+ ==================================
3480
+ -----BEGIN CERTIFICATE-----
3481
+ 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
3505
+ lM47ni3niAIi9G7oyOzWPPO5std3eqx7
3506
+ -----END CERTIFICATE-----
3507
+
3508
+ Telekom Security TLS ECC Root 2020
3509
+ ==================================
3510
+ -----BEGIN CERTIFICATE-----
3511
+ MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQswCQYDVQQGEwJE
3512
+ RTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJUZWxl
3513
+ a29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIwMB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIz
3514
+ NTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkg
3515
+ R21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqG
3516
+ SM49AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/OtdKPD/M1
3517
+ 2kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDPf8iAC8GXs7s1J8nCG6NC
3518
+ MEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6fMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
3519
+ AQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZ
3520
+ Mo7k+5Dck2TOrbRBR2Diz6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdU
3521
+ ga/sf+Rn27iQ7t0l
3522
+ -----END CERTIFICATE-----
3523
+
3524
+ Telekom Security TLS RSA Root 2023
3525
+ ==================================
3526
+ -----BEGIN CERTIFICATE-----
3527
+ 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
3553
+ -----END CERTIFICATE-----
3554
+
3555
+ FIRMAPROFESIONAL CA ROOT-A WEB
3556
+ ==============================
3557
+ -----BEGIN CERTIFICATE-----
3558
+ MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQswCQYDVQQGEwJF
3559
+ UzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4
3560
+ MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENBIFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2
3561
+ WhcNNDcwMzMxMDkwMTM2WjBuMQswCQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25h
3562
+ bCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFM
3563
+ IENBIFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zfe9MEkVz6
3564
+ iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6CcyvHZpsKjECcfIr28jlg
3565
+ st7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FD
3566
+ Y1w8ndYn81LsF7Kpryz3dvgwHQYDVR0OBBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB
3567
+ /wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgL
3568
+ cFBTApFwhVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dGXSaQ
3569
+ pYXFuXqUPoeovQA=
3570
+ -----END CERTIFICATE-----
3571
+
3572
+ TWCA CYBER Root CA
3573
+ ==================
3574
+ -----BEGIN CERTIFICATE-----
3575
+ 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
3600
+ -----END CERTIFICATE-----
3601
+
3602
+ SecureSign Root CA12
3603
+ ====================
3604
+ -----BEGIN CERTIFICATE-----
3605
+ MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTELMAkG
3606
+ A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT
3607
+ ZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJ
3608
+ BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU
3609
+ U2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3
3610
+ emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mtp7JIKwcc
3611
+ J/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zdJ1M3s6oYwlkm7Fsf0uZl
3612
+ fO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gurFzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBF
3613
+ EaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1Uef
3614
+ NzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
3615
+ AQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOC
3616
+ AQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQi
3617
+ LUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpce
3618
+ mik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPS
3619
+ vWKErI4cqc1avTc7bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhga
3620
+ aaI5gdka9at/yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==
3621
+ -----END CERTIFICATE-----
3622
+
3623
+ SecureSign Root CA14
3624
+ ====================
3625
+ -----BEGIN CERTIFICATE-----
3626
+ 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
3651
+ -----END CERTIFICATE-----
3652
+
3653
+ SecureSign Root CA15
3654
+ ====================
3655
+ -----BEGIN CERTIFICATE-----
3656
+ MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMwUTELMAkGA1UE
3657
+ BhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1
3658
+ cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMyNTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNV
3659
+ BAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2Vj
3660
+ dXJlU2lnbiBSb290IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5G
3661
+ dCx4wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSRZHX+AezB
3662
+ 2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
3663
+ AgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT9DAKBggqhkjOPQQDAwNoADBlAjEA2S6J
3664
+ fl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJ
3665
+ SwdLZrWeqrqgHkHZAXQ6bkU6iYAZezKYVWOr62Nuk22rGwlgMU4=
3666
+ -----END CERTIFICATE-----
data/excon.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  "README.md",
20
20
  "excon.gemspec"
21
21
  ]
22
+ s.required_ruby_version = '>= 2.7.0'
22
23
 
23
24
  s.add_development_dependency('rspec', '>= 3.5.0')
24
25
  s.add_development_dependency('activesupport')
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'ipaddr'
3
2
 
4
3
  module Excon
5
4
  class Connection
@@ -230,6 +229,13 @@ module Excon
230
229
  def request(params={}, &block)
231
230
  # @data has defaults, merge in new params to override
232
231
  datum = @data.merge(params)
232
+
233
+ # Set the deadline for the current request in order to determine when we have run out of time.
234
+ # Only set when a request timeout has been defined.
235
+ if datum[:timeout]
236
+ datum[:deadline] = Process.clock_gettime(Process::CLOCK_MONOTONIC) + datum[:timeout]
237
+ end
238
+
233
239
  datum[:headers] = @data[:headers].merge(datum[:headers] || {})
234
240
 
235
241
  validate_params(:request, params, datum[:middlewares])
@@ -1,16 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
  module Excon
3
-
4
3
  CR_NL = "\r\n"
5
4
 
6
- DEFAULT_CA_FILE = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "data", "cacert.pem"))
5
+ DEFAULT_CA_FILE = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data', 'cacert.pem'))
7
6
 
8
- DEFAULT_CHUNK_SIZE = 1048576 # 1 megabyte
7
+ DEFAULT_CHUNK_SIZE = 1_048_576 # 1 megabyte
9
8
 
10
9
  # avoid overwrite if somebody has redefined
11
- unless const_defined?(:CHUNK_SIZE)
12
- CHUNK_SIZE = DEFAULT_CHUNK_SIZE
13
- end
10
+ CHUNK_SIZE = DEFAULT_CHUNK_SIZE unless const_defined?(:CHUNK_SIZE)
14
11
 
15
12
  DEFAULT_REDIRECT_LIMIT = 10
16
13
 
@@ -20,13 +17,13 @@ module Excon
20
17
  Excon::Error::Timeout,
21
18
  Excon::Error::Socket,
22
19
  Excon::Error::HTTPStatus
23
- ]
20
+ ].freeze
24
21
 
25
22
  FORCE_ENC = CR_NL.respond_to?(:force_encoding)
26
23
 
27
24
  HTTP_1_1 = " HTTP/1.1\r\n"
28
25
 
29
- HTTP_VERBS = %w{connect delete get head options patch post put trace}
26
+ HTTP_VERBS = %w[connect delete get head options patch post put trace].freeze
30
27
 
31
28
  HTTPS = 'https'
32
29
 
@@ -40,87 +37,89 @@ module Excon
40
37
 
41
38
  VERSIONS = "#{USER_AGENT} (#{RUBY_PLATFORM}) ruby/#{RUBY_VERSION}"
42
39
 
43
- VALID_REQUEST_KEYS = [
44
- :allow_unstubbed_requests,
45
- :body,
46
- :chunk_size,
47
- :debug_request,
48
- :debug_response,
49
- :dns_timeouts,
50
- :headers,
51
- :instrumentor, # Used for setting logging within Connection
52
- :logger,
53
- :method,
54
- :middlewares,
55
- :password,
56
- :path,
57
- :persistent,
58
- :pipeline,
59
- :query,
60
- :read_timeout,
61
- :request_block,
62
- :response_block,
63
- :stubs,
64
- :user,
65
- :versions,
66
- :write_timeout
67
- ]
68
-
69
- VALID_CONNECTION_KEYS = VALID_REQUEST_KEYS + [
70
- :ciphers,
71
- :client_key,
72
- :client_key_data,
73
- :client_key_pass,
74
- :client_cert,
75
- :client_cert_data,
76
- :client_chain,
77
- :client_chain_data,
78
- :certificate,
79
- :certificate_path,
80
- :disable_proxy,
81
- :private_key,
82
- :private_key_path,
83
- :connect_timeout,
84
- :family,
85
- :keepalive,
86
- :host,
87
- :hostname,
88
- :omit_default_port,
89
- :nonblock,
90
- :reuseaddr,
91
- :port,
92
- :proxy,
93
- :scheme,
94
- :socket,
95
- :ssl_ca_file,
96
- :ssl_ca_path,
97
- :ssl_cert_store,
98
- :ssl_verify_callback,
99
- :ssl_verify_peer,
100
- :ssl_verify_peer_host,
101
- :ssl_verify_hostname,
102
- :ssl_version,
103
- :ssl_min_version,
104
- :ssl_max_version,
105
- :ssl_security_level,
106
- :ssl_proxy_headers,
107
- :ssl_uri_schemes,
108
- :tcp_nodelay,
109
- :thread_safe_sockets,
110
- :uri_parser,
40
+ VALID_REQUEST_KEYS = %i[
41
+ allow_unstubbed_requests
42
+ body
43
+ chunk_size
44
+ debug_request
45
+ debug_response
46
+ dns_timeouts
47
+ headers
48
+ instrumentor
49
+ logger
50
+ method
51
+ middlewares
52
+ password
53
+ path
54
+ persistent
55
+ pipeline
56
+ query
57
+ read_timeout
58
+ request_block
59
+ resolv_resolver
60
+ response_block
61
+ stubs
62
+ timeout
63
+ user
64
+ versions
65
+ write_timeout
66
+ ].freeze
67
+
68
+ VALID_CONNECTION_KEYS = VALID_REQUEST_KEYS + %i[
69
+ ciphers
70
+ client_key
71
+ client_key_data
72
+ client_key_pass
73
+ client_cert
74
+ client_cert_data
75
+ client_chain
76
+ client_chain_data
77
+ certificate
78
+ certificate_path
79
+ disable_proxy
80
+ private_key
81
+ private_key_path
82
+ connect_timeout
83
+ family
84
+ keepalive
85
+ host
86
+ hostname
87
+ omit_default_port
88
+ nonblock
89
+ reuseaddr
90
+ port
91
+ proxy
92
+ scheme
93
+ socket
94
+ ssl_ca_file
95
+ ssl_ca_path
96
+ ssl_cert_store
97
+ ssl_verify_callback
98
+ ssl_verify_peer
99
+ ssl_verify_peer_host
100
+ ssl_verify_hostname
101
+ ssl_version
102
+ ssl_min_version
103
+ ssl_max_version
104
+ ssl_security_level
105
+ ssl_proxy_headers
106
+ ssl_uri_schemes
107
+ tcp_nodelay
108
+ thread_safe_sockets
109
+ uri_parser
111
110
  ]
112
111
 
113
112
  DEPRECATED_VALID_REQUEST_KEYS = {
114
- :captures => 'Mock',
115
- :expects => 'Expects',
116
- :idempotent => 'Idempotent',
117
- :instrumentor_name => 'Instrumentor',
118
- :mock => 'Mock',
119
- :retries_remaining => 'Idempotent', # referenced in Instrumentor, but only relevant with Idempotent
120
- :retry_errors => 'Idempotent',
121
- :retry_interval => 'Idempotent',
122
- :retry_limit => 'Idempotent' # referenced in Instrumentor, but only relevant with Idempotent
123
- }
113
+ captures: 'Mock',
114
+ expects: 'Expects',
115
+ idempotent: 'Idempotent',
116
+ instrumentor_name: 'Instrumentor',
117
+ mock: 'Mock',
118
+ retries_remaining: 'Idempotent', # referenced in Instrumentor, but only relevant with Idempotent
119
+ retry_errors: 'Idempotent',
120
+ retry_interval: 'Idempotent',
121
+ retry_limit: 'Idempotent' # referenced in Instrumentor, but only relevant with Idempotent
122
+ }.freeze
124
123
 
125
124
  unless ::IO.const_defined?(:WaitReadable)
126
125
  class ::IO
@@ -133,45 +132,46 @@ module Excon
133
132
  module WaitWritable; end
134
133
  end
135
134
  end
135
+
136
136
  # these come last as they rely on the above
137
137
  DEFAULTS = {
138
- :chunk_size => CHUNK_SIZE || DEFAULT_CHUNK_SIZE,
138
+ chunk_size: CHUNK_SIZE || DEFAULT_CHUNK_SIZE,
139
139
  # see https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29
140
140
  # list provided then had DES related things sorted to the end
141
- :ciphers => 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:DES-CBC3-SHA:!DSS',
142
- :connect_timeout => 60,
143
- :debug_request => false,
144
- :debug_response => false,
145
- :dns_timeouts => nil,
146
- # nil allows Resolv::DNS to set its default timeouts value (see https://ruby-doc.org/3.2.2/stdlibs/resolv/Resolv/DNS.html#method-i-timeouts-3D)
147
- :headers => {
141
+ ciphers: 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:DES-CBC3-SHA:!DSS',
142
+ connect_timeout: 60,
143
+ debug_request: false,
144
+ debug_response: false,
145
+ dns_timeouts: nil, # nil allows Resolv::DNS default timeout value (see https://ruby-doc.org/3.2.2/stdlibs/resolv/Resolv/DNS.html#method-i-timeouts-3D)
146
+ headers: {
148
147
  'User-Agent' => USER_AGENT,
149
- 'Accept' => '*/*'
148
+ 'Accept' => '*/*'
150
149
  },
151
- :idempotent => false,
152
- :instrumentor_name => 'excon',
153
- :middlewares => [
150
+ idempotent: false,
151
+ instrumentor_name: 'excon',
152
+ middlewares: [
154
153
  Excon::Middleware::ResponseParser,
155
154
  Excon::Middleware::Expects,
156
155
  Excon::Middleware::Idempotent,
157
156
  Excon::Middleware::Instrumentor,
158
157
  Excon::Middleware::Mock
159
158
  ],
160
- :mock => false,
161
- :nonblock => true,
162
- :omit_default_port => false,
163
- :persistent => false,
164
- :read_timeout => 60,
165
- :retry_errors => DEFAULT_RETRY_ERRORS,
166
- :retry_limit => DEFAULT_RETRY_LIMIT,
167
- :ssl_verify_peer => true,
168
- :ssl_uri_schemes => [HTTPS],
169
- :stubs => :global,
170
- :tcp_nodelay => false,
171
- :thread_safe_sockets => true,
172
- :uri_parser => URI,
173
- :versions => VERSIONS,
174
- :write_timeout => 60
159
+ mock: false,
160
+ nonblock: true,
161
+ omit_default_port: false,
162
+ persistent: false,
163
+ read_timeout: 60,
164
+ resolv_resolver: nil,
165
+ retry_errors: DEFAULT_RETRY_ERRORS,
166
+ retry_limit: DEFAULT_RETRY_LIMIT,
167
+ ssl_verify_peer: true,
168
+ ssl_uri_schemes: [HTTPS],
169
+ stubs: :global,
170
+ tcp_nodelay: false,
171
+ thread_safe_sockets: true,
172
+ timeout: nil,
173
+ uri_parser: URI,
174
+ versions: VERSIONS,
175
+ write_timeout: 60
175
176
  }
176
-
177
177
  end
data/lib/excon/socket.rb CHANGED
@@ -25,6 +25,13 @@ module Excon
25
25
  else # Ruby <= 2.0
26
26
  [Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable]
27
27
  end
28
+ # Maps a socket operation to a timeout property.
29
+ OPERATION_TO_TIMEOUT = {
30
+ :connect_read => :connect_timeout,
31
+ :connect_write => :connect_timeout,
32
+ :read => :read_timeout,
33
+ :write => :write_timeout
34
+ }.freeze
28
35
 
29
36
  def params
30
37
  Excon.display_warning('Excon::Socket#params is deprecated use Excon::Socket#data instead.')
@@ -46,14 +53,16 @@ module Excon
46
53
  @nonblock = data[:nonblock]
47
54
  @port ||= @data[:port] || 80
48
55
  @read_buffer = String.new
56
+ @read_offset = 0
49
57
  @eof = false
50
58
  @backend_eof = false
59
+
51
60
  connect
52
61
  end
53
62
 
54
63
  def read(max_length = nil)
55
64
  if @eof
56
- return max_length ? nil : ''
65
+ max_length ? nil : ''
57
66
  elsif @nonblock
58
67
  read_nonblock(max_length)
59
68
  else
@@ -64,20 +73,22 @@ module Excon
64
73
  def readline
65
74
  if @nonblock
66
75
  result = String.new
67
- block = @read_buffer
68
- @read_buffer = String.new
76
+ block = consume_read_buffer
69
77
 
70
78
  loop do
71
79
  idx = block.index("\n")
80
+
72
81
  if idx.nil?
73
82
  result << block
74
83
  else
75
- result << block.slice!(0, idx+1)
76
- add_to_read_buffer(block)
84
+ result << block[0..idx]
85
+ rewind_read_buffer(block, idx)
77
86
  break
78
87
  end
88
+
79
89
  block = read_nonblock(@data[:chunk_size]) || raise(EOFError)
80
90
  end
91
+
81
92
  result
82
93
  else # nonblock/legacy
83
94
  begin
@@ -121,9 +132,16 @@ module Excon
121
132
  family = @data[:proxy][:family]
122
133
  end
123
134
 
124
- dns_resolver = Resolv::DNS.new
125
- dns_resolver.timeouts = @data[:dns_timeouts]
126
- resolver = Resolv.new([Resolv::Hosts.new, dns_resolver])
135
+ resolver = @data[:resolv_resolver] || Resolv::DefaultResolver
136
+
137
+ # Deprecated
138
+ if @data[:dns_timeouts]
139
+ Excon.display_warning('dns_timeouts is deprecated, use resolv_resolver instead.')
140
+ dns_resolver = Resolv::DNS.new
141
+ dns_resolver.timeouts = @data[:dns_timeouts]
142
+ resolver = Resolv.new([Resolv::Hosts.new, dns_resolver])
143
+ end
144
+
127
145
  resolver.each_address(hostname) do |ip|
128
146
  # already succeeded on previous addrinfo
129
147
  if @socket
@@ -190,20 +208,48 @@ module Excon
190
208
  end
191
209
  end
192
210
 
193
- def add_to_read_buffer(str)
194
- @read_buffer << str
211
+ # Consume any bytes remaining in the read buffer before making a system call.
212
+ def consume_read_buffer
213
+ block = @read_buffer[@read_offset..-1]
214
+
215
+ @read_offset = @read_buffer.length
216
+
217
+ block
218
+ end
219
+
220
+ # Rewind the read buffer to just after the given index.
221
+ # The offset is moved back to the start of the current chunk and then forward until just after the index.
222
+ def rewind_read_buffer(chunk, idx)
223
+ @read_offset = @read_offset - chunk.length + (idx + 1)
195
224
  @eof = false
196
225
  end
197
226
 
198
227
  def read_nonblock(max_length)
199
228
  begin
229
+ if @read_offset != 0 && @read_offset >= @read_buffer.length
230
+ # Clear the buffer so we can test for emptiness below
231
+ @read_buffer.clear
232
+ # Reset the offset so it matches the length of the buffer when empty.
233
+ @read_offset = 0
234
+ end
235
+
200
236
  if max_length
201
- until @backend_eof || @read_buffer.length >= max_length
202
- @read_buffer << @socket.read_nonblock(max_length - @read_buffer.length)
237
+ until @backend_eof || readable_bytes >= max_length
238
+ if @read_buffer.empty?
239
+ # Avoid allocating a new buffer string when the read buffer is empty
240
+ @read_buffer = @socket.read_nonblock(max_length, @read_buffer)
241
+ else
242
+ @read_buffer << @socket.read_nonblock(max_length - readable_bytes)
243
+ end
203
244
  end
204
245
  else
205
- while !@backend_eof
206
- @read_buffer << @socket.read_nonblock(@data[:chunk_size])
246
+ until @backend_eof
247
+ if @read_buffer.empty?
248
+ # Avoid allocating a new buffer string when the read buffer is empty
249
+ @read_buffer = @socket.read_nonblock(@data[:chunk_size], @read_buffer)
250
+ else
251
+ @read_buffer << @socket.read_nonblock(@data[:chunk_size])
252
+ end
207
253
  end
208
254
  end
209
255
  rescue OpenSSL::SSL::SSLError => error
@@ -223,18 +269,32 @@ module Excon
223
269
  @backend_eof = true
224
270
  end
225
271
 
226
- ret = if max_length
272
+ if max_length
227
273
  if @read_buffer.empty?
228
- nil # EOF met at beginning
274
+ # EOF met at beginning
275
+ @eof = @backend_eof
276
+ nil
229
277
  else
230
- @read_buffer.slice!(0, max_length)
278
+ start = @read_offset
279
+
280
+ # Ensure that we can seek backwards when reading until a terminator string.
281
+ # The read offset must never point past the end of the read buffer.
282
+ @read_offset += max_length > readable_bytes ? readable_bytes : max_length
283
+ @read_buffer[start...@read_offset]
231
284
  end
232
285
  else
233
286
  # read until EOFError, so return everything
234
- @read_buffer.slice!(0, @read_buffer.length)
287
+ start = @read_offset
288
+
289
+ @read_offset = @read_buffer.length
290
+ @eof = @backend_eof
291
+
292
+ @read_buffer[start..-1]
235
293
  end
236
- @eof = @backend_eof && @read_buffer.empty?
237
- ret
294
+ end
295
+
296
+ def readable_bytes
297
+ @read_buffer.length - @read_offset
238
298
  end
239
299
 
240
300
  def read_block(max_length)
@@ -297,17 +357,33 @@ module Excon
297
357
  end
298
358
 
299
359
  def select_with_timeout(socket, type)
360
+ timeout_kind = type
361
+ timeout = @data[OPERATION_TO_TIMEOUT[type]]
362
+
363
+ # Check whether the request has a timeout configured.
364
+ if @data.include?(:deadline)
365
+ request_timeout = request_time_remaining
366
+
367
+ # If the time remaining until the request times out is less than the timeout for the type of select,
368
+ # use the time remaining as the timeout instead.
369
+ if request_timeout < timeout
370
+ timeout_kind = :request
371
+ timeout = request_timeout
372
+ end
373
+ end
374
+
300
375
  select = case type
301
376
  when :connect_read
302
- IO.select([socket], nil, nil, @data[:connect_timeout])
377
+ IO.select([socket], nil, nil, timeout)
303
378
  when :connect_write
304
- IO.select(nil, [socket], nil, @data[:connect_timeout])
379
+ IO.select(nil, [socket], nil, timeout)
305
380
  when :read
306
- IO.select([socket], nil, nil, @data[:read_timeout])
381
+ IO.select([socket], nil, nil, timeout)
307
382
  when :write
308
- IO.select(nil, [socket], nil, @data[:write_timeout])
383
+ IO.select(nil, [socket], nil, timeout)
309
384
  end
310
- select || raise(Excon::Errors::Timeout.new("#{type} timeout reached"))
385
+
386
+ select || raise(Excon::Errors::Timeout.new("#{timeout_kind} timeout reached"))
311
387
  end
312
388
 
313
389
  def unpacked_sockaddr
@@ -317,5 +393,16 @@ module Excon
317
393
  raise
318
394
  end
319
395
  end
396
+
397
+ # Returns the remaining time in seconds until we reach the deadline for the request timeout.
398
+ # Raises an exception if we have exceeded the request timeout's deadline.
399
+ def request_time_remaining
400
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
401
+ deadline = @data[:deadline]
402
+
403
+ raise(Excon::Errors::Timeout.new('request timeout reached')) if now >= deadline
404
+
405
+ deadline - now
406
+ end
320
407
  end
321
408
  end
data/lib/excon/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Excon
4
- VERSION = '0.103.0'
4
+ VERSION = '0.112.0'
5
5
  end
data/lib/excon.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  $:.unshift(File.dirname(__FILE__)) unless
3
4
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
4
5
 
5
6
  require 'cgi'
6
7
  require 'forwardable'
8
+ require 'ipaddr'
7
9
  require 'openssl'
8
10
  require 'rbconfig'
9
11
  require 'socket'
@@ -44,7 +46,6 @@ require 'excon/unix_socket'
44
46
  # Define defaults first so they will be available to other files
45
47
  module Excon
46
48
  class << self
47
-
48
49
  # @return [Hash] defaults for Excon connections
49
50
  def defaults
50
51
  @defaults ||= DEFAULTS
@@ -52,19 +53,15 @@ module Excon
52
53
 
53
54
  # Change defaults for Excon connections
54
55
  # @return [Hash] defaults for Excon connections
55
- def defaults=(new_defaults)
56
- @defaults = new_defaults
57
- end
56
+ attr_writer :defaults
58
57
 
59
58
  def display_warning(warning)
60
59
  # Show warning if $VERBOSE or ENV['EXCON_DEBUG'] is set
61
- if $VERBOSE || ENV['EXCON_DEBUG']
62
- $stderr.puts "[excon][WARNING] #{warning}\n#{ caller.join("\n") }"
63
- end
60
+ ($VERBOSE || ENV['EXCON_DEBUG']) && Warning.warn("[excon][WARNING] #{warning}\n#{caller.join("\n")}")
64
61
 
65
- if @raise_on_warnings
66
- raise Error::Warning.new(warning)
67
- end
62
+ return unless @raise_on_warnings
63
+
64
+ raise(Error::Warning, warning)
68
65
  end
69
66
 
70
67
  def set_raise_on_warnings!(should_raise)
@@ -119,32 +116,25 @@ module Excon
119
116
  def new(url, params = {})
120
117
  uri_parser = params[:uri_parser] || defaults[:uri_parser]
121
118
  uri = uri_parser.parse(url)
122
- if params[:path]
123
- uri_parser.parse(params[:path])
124
- end
125
- unless uri.scheme
126
- raise ArgumentError.new("Invalid URI: #{uri}")
127
- end
119
+ params[:path] && uri_parser.parse(params[:path])
120
+ raise(ArgumentError, "Invalid URI: #{uri}") unless uri.scheme
121
+
128
122
  params = {
129
- :host => uri.host,
130
- :hostname => uri.hostname,
131
- :path => uri.path,
132
- :port => uri.port,
133
- :query => uri.query,
134
- :scheme => uri.scheme
123
+ host: uri.host,
124
+ hostname: uri.hostname,
125
+ path: uri.path,
126
+ port: uri.port,
127
+ query: uri.query,
128
+ scheme: uri.scheme
135
129
  }.merge(params)
136
- if uri.password
137
- params[:password] = Utils.unescape_uri(uri.password)
138
- end
139
- if uri.user
140
- params[:user] = Utils.unescape_uri(uri.user)
141
- end
130
+ uri.password && params[:password] = Utils.unescape_uri(uri.password)
131
+ uri.user && params[:user] = Utils.unescape_uri(uri.user)
142
132
  Excon::Connection.new(params)
143
133
  end
144
134
 
145
135
  # push an additional stub onto the list to check for mock requests
146
136
  # @param request_params [Hash<Symbol, >] request params to match against, omitted params match all
147
- # @param response_params [Hash<Symbol, >] response params to return from matched request or block to call with params
137
+ # @param response_params [Hash<Symbol, >] response params to return or block to call with matched params
148
138
  def stub(request_params = {}, response_params = nil, &block)
149
139
  if (method = request_params.delete(:method))
150
140
  request_params[:method] = method.to_s.downcase.to_sym
@@ -152,19 +142,20 @@ module Excon
152
142
  if (url = request_params.delete(:url))
153
143
  uri = URI.parse(url)
154
144
  request_params = {
155
- :host => uri.host,
156
- :path => uri.path,
157
- :port => uri.port,
158
- :query => uri.query,
159
- :scheme => uri.scheme
145
+ host: uri.host,
146
+ path: uri.path,
147
+ port: uri.port,
148
+ query: uri.query,
149
+ scheme: uri.scheme
160
150
  }.merge!(request_params)
161
151
  if uri.user || uri.password
162
152
  request_params[:headers] ||= {}
163
- user, pass = Utils.unescape_form(uri.user.to_s), Utils.unescape_form(uri.password.to_s)
153
+ user = Utils.unescape_form(uri.user.to_s)
154
+ pass = Utils.unescape_form(uri.password.to_s)
164
155
  request_params[:headers]['Authorization'] ||= 'Basic ' + ["#{user}:#{pass}"].pack('m').delete(Excon::CR_NL)
165
156
  end
166
157
  end
167
- if request_params.has_key?(:headers)
158
+ if request_params.key?(:headers)
168
159
  headers = Excon::Headers.new
169
160
  request_params[:headers].each do |key, value|
170
161
  headers[key] = value
@@ -172,15 +163,13 @@ module Excon
172
163
  request_params[:headers] = headers
173
164
  end
174
165
  if block_given?
175
- if response_params
176
- raise(ArgumentError.new("stub requires either response_params OR a block"))
177
- else
178
- stub = [request_params, block]
179
- end
166
+ raise(ArgumentError, 'stub requires either response_params OR a block') if response_params
167
+
168
+ stub = [request_params, block]
180
169
  elsif response_params
181
170
  stub = [request_params, response_params]
182
171
  else
183
- raise(ArgumentError.new("stub requires either response_params OR a block"))
172
+ raise(ArgumentError, 'stub requires either response_params OR a block')
184
173
  end
185
174
  stubs.unshift(stub)
186
175
  stub
@@ -194,8 +183,8 @@ module Excon
194
183
  request_params[:method] = method.to_s.downcase.to_sym
195
184
  end
196
185
  Excon.stubs.each do |stub, response_params|
197
- captures = { :headers => {} }
198
- headers_match = !stub.has_key?(:headers) || stub[:headers].keys.all? do |key|
186
+ captures = { headers: {} }
187
+ headers_match = !stub.key?(:headers) || stub[:headers].keys.all? do |key|
199
188
  case value = stub[:headers][key]
200
189
  when Regexp
201
190
  case request_params[:headers][key]
@@ -249,9 +238,9 @@ module Excon
249
238
  # @param request_params [Hash<Symbol, >] request params to match against, omitted params match all
250
239
  # @return [Hash<Symbol, >] response params from deleted stub
251
240
  def unstub(request_params = {})
252
- if (stub = stub_for(request_params))
253
- Excon.stubs.delete_at(Excon.stubs.index(stub))
254
- end
241
+ return unless (stub = stub_for(request_params))
242
+
243
+ Excon.stubs.delete_at(Excon.stubs.index(stub))
255
244
  end
256
245
 
257
246
  # Generic non-persistent HTTP methods
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: excon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.103.0
4
+ version: 0.112.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dpiddy (Dan Peterson)
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-09-13 00:00:00.000000000 Z
13
+ date: 2024-10-01 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -244,14 +244,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
244
244
  requirements:
245
245
  - - ">="
246
246
  - !ruby/object:Gem::Version
247
- version: '0'
247
+ version: 2.7.0
248
248
  required_rubygems_version: !ruby/object:Gem::Requirement
249
249
  requirements:
250
250
  - - ">="
251
251
  - !ruby/object:Gem::Version
252
252
  version: '0'
253
253
  requirements: []
254
- rubygems_version: 3.3.26
254
+ rubygems_version: 3.5.18
255
255
  signing_key:
256
256
  specification_version: 4
257
257
  summary: speed, persistence, http(s)