excon 0.49.0 → 0.88.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +5 -5
  2. data/CONTRIBUTORS.md +33 -3
  3. data/LICENSE.md +1 -1
  4. data/README.md +77 -7
  5. data/data/cacert.pem +1279 -1940
  6. data/excon.gemspec +32 -170
  7. data/lib/excon/connection.rb +257 -154
  8. data/lib/excon/constants.rb +44 -16
  9. data/lib/excon/error.rb +229 -0
  10. data/lib/excon/extensions/uri.rb +1 -0
  11. data/lib/excon/headers.rb +5 -3
  12. data/lib/excon/instrumentors/logging_instrumentor.rb +48 -0
  13. data/lib/excon/instrumentors/standard_instrumentor.rb +21 -0
  14. data/lib/excon/middlewares/base.rb +7 -0
  15. data/lib/excon/middlewares/capture_cookies.rb +2 -1
  16. data/lib/excon/middlewares/decompress.rb +3 -2
  17. data/lib/excon/middlewares/escape_path.rb +1 -0
  18. data/lib/excon/middlewares/expects.rb +8 -1
  19. data/lib/excon/middlewares/idempotent.rb +27 -3
  20. data/lib/excon/middlewares/instrumentor.rb +9 -0
  21. data/lib/excon/middlewares/mock.rb +14 -4
  22. data/lib/excon/middlewares/redirect_follower.rb +28 -4
  23. data/lib/excon/middlewares/response_parser.rb +4 -0
  24. data/lib/excon/pretty_printer.rb +2 -8
  25. data/lib/excon/response.rb +16 -12
  26. data/lib/excon/socket.rb +56 -36
  27. data/lib/excon/ssl_socket.rb +70 -25
  28. data/lib/excon/test/plugin/server/exec.rb +26 -0
  29. data/lib/excon/test/plugin/server/puma.rb +23 -0
  30. data/lib/excon/test/plugin/server/unicorn.rb +38 -0
  31. data/lib/excon/test/plugin/server/webrick.rb +26 -0
  32. data/lib/excon/test/server.rb +106 -0
  33. data/lib/excon/unix_socket.rb +2 -0
  34. data/lib/excon/utils.rb +65 -10
  35. data/lib/excon/version.rb +4 -0
  36. data/lib/excon.rb +35 -20
  37. metadata +69 -87
  38. data/Gemfile +0 -19
  39. data/Gemfile.lock +0 -285
  40. data/Rakefile +0 -144
  41. data/benchmarks/class_vs_lambda.rb +0 -50
  42. data/benchmarks/concat_vs_insert.rb +0 -21
  43. data/benchmarks/concat_vs_interpolate.rb +0 -21
  44. data/benchmarks/cr_lf.rb +0 -21
  45. data/benchmarks/downcase-eq-eq_vs_casecmp.rb +0 -169
  46. data/benchmarks/excon.rb +0 -69
  47. data/benchmarks/excon_vs.rb +0 -165
  48. data/benchmarks/for_vs_array_each.rb +0 -27
  49. data/benchmarks/for_vs_hash_each.rb +0 -27
  50. data/benchmarks/has_key-vs-lookup.rb +0 -177
  51. data/benchmarks/headers_case_sensitivity.rb +0 -83
  52. data/benchmarks/headers_split_vs_match.rb +0 -34
  53. data/benchmarks/implicit_block-vs-explicit_block.rb +0 -98
  54. data/benchmarks/merging.rb +0 -21
  55. data/benchmarks/single_vs_double_quotes.rb +0 -21
  56. data/benchmarks/string_ranged_index.rb +0 -87
  57. data/benchmarks/strip_newline.rb +0 -115
  58. data/benchmarks/vs_stdlib.rb +0 -82
  59. data/changelog.txt +0 -959
  60. data/lib/excon/errors.rb +0 -172
  61. data/lib/excon/standard_instrumentor.rb +0 -27
  62. data/tests/authorization_header_tests.rb +0 -33
  63. data/tests/bad_tests.rb +0 -47
  64. data/tests/basic_tests.rb +0 -334
  65. data/tests/complete_responses.rb +0 -31
  66. data/tests/data/127.0.0.1.cert.crt +0 -14
  67. data/tests/data/127.0.0.1.cert.key +0 -15
  68. data/tests/data/excon.cert.crt +0 -14
  69. data/tests/data/excon.cert.key +0 -15
  70. data/tests/data/xs +0 -1
  71. data/tests/errors_tests.rb +0 -58
  72. data/tests/header_tests.rb +0 -119
  73. data/tests/middlewares/canned_response_tests.rb +0 -34
  74. data/tests/middlewares/capture_cookies_tests.rb +0 -34
  75. data/tests/middlewares/decompress_tests.rb +0 -157
  76. data/tests/middlewares/escape_path_tests.rb +0 -36
  77. data/tests/middlewares/idempotent_tests.rb +0 -131
  78. data/tests/middlewares/instrumentation_tests.rb +0 -312
  79. data/tests/middlewares/mock_tests.rb +0 -293
  80. data/tests/middlewares/redirect_follower_tests.rb +0 -80
  81. data/tests/pipeline_tests.rb +0 -40
  82. data/tests/proxy_tests.rb +0 -306
  83. data/tests/query_string_tests.rb +0 -87
  84. data/tests/rackups/basic.rb +0 -41
  85. data/tests/rackups/basic.ru +0 -3
  86. data/tests/rackups/basic_auth.ru +0 -14
  87. data/tests/rackups/deflater.ru +0 -4
  88. data/tests/rackups/proxy.ru +0 -18
  89. data/tests/rackups/query_string.ru +0 -13
  90. data/tests/rackups/redirecting.ru +0 -23
  91. data/tests/rackups/redirecting_with_cookie.ru +0 -40
  92. data/tests/rackups/request_headers.ru +0 -15
  93. data/tests/rackups/request_methods.ru +0 -21
  94. data/tests/rackups/response_header.ru +0 -18
  95. data/tests/rackups/ssl.ru +0 -16
  96. data/tests/rackups/ssl_mismatched_cn.ru +0 -15
  97. data/tests/rackups/ssl_verify_peer.ru +0 -16
  98. data/tests/rackups/streaming.ru +0 -30
  99. data/tests/rackups/thread_safety.ru +0 -17
  100. data/tests/rackups/timeout.ru +0 -14
  101. data/tests/rackups/webrick_patch.rb +0 -34
  102. data/tests/request_headers_tests.rb +0 -21
  103. data/tests/request_method_tests.rb +0 -47
  104. data/tests/request_tests.rb +0 -59
  105. data/tests/response_tests.rb +0 -197
  106. data/tests/servers/bad.rb +0 -20
  107. data/tests/servers/eof.rb +0 -17
  108. data/tests/servers/error.rb +0 -20
  109. data/tests/servers/good.rb +0 -350
  110. data/tests/test_helper.rb +0 -306
  111. data/tests/thread_safety_tests.rb +0 -39
  112. data/tests/timeout_tests.rb +0 -12
  113. data/tests/utils_tests.rb +0 -81
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 89343aee2679e6e6b180e22e1ae3c16f5680bd4c
4
- data.tar.gz: 354d695485716081f2b7732bbbb2b15964f8e738
2
+ SHA256:
3
+ metadata.gz: 4833043db3796214dc4c5e339db701b609f0664fe5e3dd24f9c0c69a4e94d3ca
4
+ data.tar.gz: 6a2cba5d185ded99cffbf4057ed141ca15993ed409a5bb8059aef83b6d26c680
5
5
  SHA512:
6
- metadata.gz: 35185514c9f9460e3409282f8da653832110c6e13813e964d1bc53424fccd4d9dfce972a4811bddae2c9929e19b81860c50326620675b4a23f9c71c59bda24bf
7
- data.tar.gz: 75d1f86fb2d5d66576d50b183c32d358c43408129ade13adb653a7333b1a2825083d4e66c61dfb476d78729fc4fcca087f14d24fbfa5d4d8dea02815e1efb7ef
6
+ metadata.gz: 5dc2124ca9454071c435b814a70dff35c2eee0ed7f7f0e90f5cbd7b5705863c7bd8c69ab40f86d626c83672cd94117a7f6b4bf581101d699034bde70be96d93e
7
+ data.tar.gz: a9048686e48a21fa494dc09394881fa11ff7a6786bb216e06ceb95530d251e3c04c331f5a2b24e04e60cb08e4a5e7003f6ece127c01dc5a4c71df27361d27a66
data/CONTRIBUTORS.md CHANGED
@@ -1,4 +1,8 @@
1
+ * Aaron Stone <aaron@serendipity.cx>
2
+ * Adam Esterline <adam@esterlines.com>
3
+ * Alexander Sandström <alexander@skovik.com>
1
4
  * Andrew Katz <andrew.katz@outright.com>
5
+ * Andy Delcambre <adelcambre@gmail.com>
2
6
  * Anshul Khandelwal <anshul@anshulkhandelwal.com>
3
7
  * Ash Wilson <smashwilson@gmail.com>
4
8
  * Ben Burkert <ben@benburkert.com>
@@ -7,12 +11,15 @@
7
11
  * Brandur <brandur@mutelight.org>
8
12
  * Brian D. Burns <iosctr@gmail.com>
9
13
  * Brian Hartsock <brian.hartsock@gmail.com>
14
+ * Bryan Paxton <starbelly@pobox.com>
10
15
  * Caio Chassot <dev@caiochassot.com>
11
16
  * Caius Durling <dev@caius.name>
12
17
  * Carl Hörberg <carl.hoerberg@gmail.com>
18
+ * Carl Hörberg <carl.hoerberg@gmail.com>
13
19
  * Carlos Sanchez <csanchez@maestrodev.com>
20
+ * Casper Thomsen <ct@clearhaus.com>
21
+ * Chris Hanks <christopher.m.hanks@gmail.com>
14
22
  * Claudio Poli <masterkain@gmail.com>
15
- * Colin Dean <colindean@us.ibm.com>
16
23
  * Damien Mathieu <damien@heroku.com>
17
24
  * Dan Hensgen <dan@methodhead.com>
18
25
  * Dan Peterson <dpiddy@gmail.com>
@@ -24,35 +31,44 @@
24
31
  * David Biehl <lazylodr@gmail.com>
25
32
  * Dimitrij Denissenko <dimitrij@blacksquaremedia.com>
26
33
  * Dominik Richter <dominik.richter@gmail.com>
34
+ * Doug McInnes <doug@dougmcinnes.com>
27
35
  * Eugene Howe <eugene@xtreme-computers.net>
28
36
  * Evan Phoenix <evan@fallingsnow.net>
29
37
  * Fabian Wiesel <fabian.wiesel@sap.com>
30
38
  * Federico Ravasio <ravasio.federico@gmail.com>
31
39
  * Glenn Pratt <glennpratt@gmail.com>
32
40
  * Graeme Nelson <graeme.nelson@gmail.com>
41
+ * Guillaume Balaine <igosuki@gmail.com>
33
42
  * Hakan Ensari <hakan.ensari@papercavalier.com>
34
43
  * Ian Neubert <ian@ianneubert.com>
35
44
  * Jacob Atzen <jacob@incremental.dk>
45
+ * James Cox <james@imaj.es>
36
46
  * James Watling <watling.james@gmail.com>
47
+ * Jean Mertz <jean@mertz.fm>
37
48
  * Jeremy Hinegardner <jeremy@copiousfreetime.org>
49
+ * Jesse Kempf <jesse.kempf@opower.com>
50
+ * Joe Rafaniello <jrafanie@redhat.com>
38
51
  * John Keiser <jkeiser@opscode.com>
39
52
  * John Leach <john@brightbox.co.uk>
40
53
  * Jonas Pfenniger <jonas@pfenniger.name>
41
54
  * Jonathan Dance <github@wuputah.com>
42
55
  * Jonathan Dance <jd@wuputah.com>
43
56
  * Jonathan Roes <jroes@jroes.net>
57
+ * Joshua B. Smith <jbsmith@us.ibm.com>
44
58
  * Joshua Gross <joshua@surfeasy.com>
45
59
  * Joshua Mckinney <joshmckin@gmail.com>
46
60
  * Joshua Napoli <jnapoli@swipely-napoli.home>
47
61
  * Joshua Napoli <jnapoli@swipely-napoli.local>
48
- * Joshua Smith <kognate@gmail.com>
62
+ * Kelly Mahan <kmahan@kmahan.com>
49
63
  * Kensuke Nagae <kyanny@gmail.com>
50
64
  * Konstantin Shabanov <etehtsea@gmail.com>
51
65
  * Kyle Rames <kyle.rames@rackspace.com>
52
66
  * Lewis Marshall <lewis@lmars.net>
53
67
  * Lincoln Stoll <me@lstoll.net>
54
68
  * Louis Sobel <sobel@mit.edu>
69
+ * Mahemoff <michael@mahemoff.com>
55
70
  * Mathias Meyer <meyer@paperplanes.de>
71
+ * Matt Gauger <matt.gauger@gmail.com>
56
72
  * Matt Sanders <matt@modal.org>
57
73
  * Matt Sanders <matt@polycot.com>
58
74
  * Matt Snyder <snyder2112@me.com>
@@ -68,16 +84,27 @@
68
84
  * Nathan Sutton <nate@zencoder.com>
69
85
  * Nick Osborn <nick.osborn@digital.cabinet-office.gov.uk>
70
86
  * Nicolas Sanguinetti <contacto@nicolassanguinetti.info>
87
+ * Paul Gideon Dann <pdgiddie@gmail.com>
88
+ * Pavel <pavel.evst@gmail.com>
71
89
  * Peter Meier <peter.meier@immerda.ch>
72
90
  * Peter Weldon <peter.weldon@null.net>
73
91
  * Peter Weldon <peter@lautus.net>
92
+ * Phil Ross <phil.ross@gmail.com>
93
+ * Richard Ramsden <richard@rramsden.ca>
94
+ * Ruslan Korolev <rs3@fastmail.com>
95
+ * Ruslan Korolev <rs41@gmx.com>
74
96
  * Ruslan Kyrychuk <ruslan.kyrychuk@gmail.com>
97
+ * Ryan Bigg <radarlistener@fastmail.fm>
75
98
  * Ryan Mohr <ryan.mohr@gmail.com>
99
+ * Sam Withrow <sam.withrow@curiousnation.org>
76
100
  * Scott Gonyea <me@aitrus.org>
77
101
  * Scott Gonyea <me@sgonyea.com>
102
+ * Scott Walkinshaw <scott.walkinshaw@gmail.com>
78
103
  * Sean Cribbs <seancribbs@gmail.com>
79
104
  * Sergio Rubio <rubiojr@frameos.org>
80
105
  * Shai Rosenfeld <shaiguitar@gmail.com>
106
+ * Stefan Merettig <stefan-merettig@nuriaproject.org>
107
+ * Stephen Chu <github@stephenchu.com>
81
108
  * Swanand Pagnis <swanandp@users.noreply.github.com>
82
109
  * Terry Howe <terrylhowe@gmail.com>
83
110
  * Thom Mahoney & Josh Lane <tmahoney@engineyard.com>
@@ -88,12 +115,14 @@
88
115
  * Tom Maher <tmaher@tursom.org>
89
116
  * Trym Skaar <trym@tryms.no>
90
117
  * Tuomas Silen <tuomas.silen@nodeta.fi>
118
+ * Victor Costan <costan@gmail.com>
91
119
  * Viven <vivien.schilis@gmail.com>
92
120
  * Wesley Beary <geemus+github@gmail.com>
93
121
  * Wesley Beary <geemus@engineyard.com>
94
122
  * Wesley Beary <geemus@gmail.com>
95
123
  * Wesley Beary <wbeary@engineyard.com>
96
124
  * Wesley Beary <wesley@heroku.com>
125
+ * Zach Anker <zanker@squareup.com>
97
126
  * chrisrhoden <carhoden@gmail.com>
98
127
  * dickeyxxx <jeff@dickeyxxx.com>
99
128
  * geemus (Wesley Beary) <wbeary@engineyard.com>
@@ -106,5 +135,6 @@
106
135
  * rinrinne <rinrin.ne@gmail.com>
107
136
  * rkyrychuk <ruslan.kyrychuk@gmail.com>
108
137
  * sshaw <skye.shaw@gmail.com>
138
+ * starbelly <starbelly@pobox.com>
109
139
  * twrodriguez <tw.rodriguez@gmail.com>
110
- * zimbatm <zimbatm@zimbatm.com>
140
+ * zimbatm <zimbatm@zimbatm.com>
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2009-2015 [CONTRIBUTORS.md](https://github.com/excon/excon/blob/master/CONTRIBUTORS.md)
3
+ Copyright (c) 2009-2019 [CONTRIBUTORS.md](https://github.com/excon/excon/blob/master/CONTRIBUTORS.md)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -4,10 +4,25 @@ 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://secure.travis-ci.org/excon/excon.svg)](http://travis-ci.org/excon/excon)
8
- [![Dependency Status](https://gemnasium.com/geemus/excon.svg)](https://gemnasium.com/geemus/excon)
9
- [![Gem Version](https://badge.fury.io/rb/excon.svg)](http://badge.fury.io/rb/excon)
10
- [![Gittip](http://img.shields.io/gittip/geemus.svg)](https://www.gittip.com/geemus/)
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)
9
+
10
+ * [Getting Started](#getting-started)
11
+ * [Options](#options)
12
+ * [Chunked Requests](#chunked-requests)
13
+ * [Pipelining Requests](#pipelining-requests)
14
+ * [Streaming Responses](#streaming-responses)
15
+ * [Proxy Support](#proxy-support)
16
+ * [Reusable ports](#reusable-ports)
17
+ * [Unix Socket Support](#unix-socket-support)
18
+ * [Stubs](#stubs)
19
+ * [Instrumentation](#instrumentation)
20
+ * [HTTPS client certificate](#https-client-certificate)
21
+ * [HTTPS/SSL Issues](#httpsssl-issues)
22
+ * [Getting Help](#getting-help)
23
+ * [Contributing](#contributing)
24
+ * [Plugins and Middlewares](#plugins-and-middlewares)
25
+ * [License](#license)
11
26
 
12
27
  ## Getting Started
13
28
 
@@ -113,12 +128,16 @@ connection.request(:method => 'GET')
113
128
  # expect one or more status codes, or raise an error
114
129
  connection.request(:expects => [200, 201], :method => :get)
115
130
 
116
- # this request can be repeated safely, so retry on errors up to 3 times
131
+ # this request can be repeated safely, so retry on errors up to 4 times
117
132
  connection.request(:idempotent => true)
118
133
 
119
134
  # this request can be repeated safely, retry up to 6 times
120
135
  connection.request(:idempotent => true, :retry_limit => 6)
121
136
 
137
+ # this request can be repeated safely, retry up to 6 times and sleep 5 seconds
138
+ # in between each retry
139
+ connection.request(:idempotent => true, :retry_limit => 6, :retry_interval => 5)
140
+
122
141
  # set longer read_timeout (default is 60 seconds)
123
142
  connection.request(:read_timeout => 360)
124
143
 
@@ -140,6 +159,9 @@ connection = Excon.new('http://geemus.com/', :nonblock => false)
140
159
 
141
160
  # use basic authentication by supplying credentials in the URL or as parameters
142
161
  connection = Excon.new('http://username:password@secure.geemus.com')
162
+ # Note: username & password is unescaped for request, so you should provide escaped values here
163
+ # i. e. instead of `password: 'pa%%word'` you should use `password: Excon::Utils.escape_uri('pa%%word')`,
164
+ # which return `pa%25%25word`
143
165
  connection = Excon.new('http://secure.geemus.com',
144
166
  :user => 'username', :password => 'password')
145
167
 
@@ -155,7 +177,7 @@ Compared to web browsers and other http client libraries, e.g. curl, Excon is a
155
177
  connection = Excon.new('http://geemus.com/', :omit_default_port => true)
156
178
 
157
179
  # accept gzip encoding
158
- connection = Excon.new('http://geemus.com/', :headers => { "Accept" => "gzip" })
180
+ connection = Excon.new('http://geemus.com/', :headers => { "Accept-Encoding" => "gzip" })
159
181
 
160
182
  # turn off peer verification (less secure)
161
183
  Excon.defaults[:ssl_verify_peer] = false
@@ -194,6 +216,13 @@ connection.requests([{:method => :get}, {:method => :get}])
194
216
  By default, each call to `requests` will use a separate persistent socket connection. To make multiple `requests` calls
195
217
  using a single persistent connection, set `:persistent => true` when establishing the connection.
196
218
 
219
+ For large numbers of simultaneous requests please consider using the `batch_requests` method. This will automatically slice up the requests into batches based on the file descriptor limit of your operating system. The results are the same as the `requests` method, but using this method can help prevent timeout errors.
220
+
221
+ ```ruby
222
+ large_array_of_requests = [{:method => :get, :path => 'some_path'}, { ... }] # Hundreds of items
223
+ connection.batch_requests(large_array_of_requests)
224
+ ```
225
+
197
226
  ## Streaming Responses
198
227
 
199
228
  You can stream responses by passing a block that will receive each chunk.
@@ -224,7 +253,7 @@ The proxy URL must be fully specified, including scheme (e.g. "http://") and por
224
253
 
225
254
  Proxy support must be set when establishing a connection object and cannot be overridden in individual requests.
226
255
 
227
- NOTE: Excon will use the environment variables `http_proxy` and `https_proxy` if they are present. If these variables are set they will take precedence over a :proxy option specified in code. If "https_proxy" is not set, the value of "http_proxy" will be used for both HTTP and HTTPS connections.
256
+ NOTE: Excon will use `HTTP_PROXY` and `HTTPS_PROXY` environment variables. If set they will take precedence over any :proxy option specified in code. If "HTTPS_PROXY" is not set, "HTTP_PROXY" will be used for both HTTP and HTTPS connections. To disable this behavior, set the `NO_PROXY` environment variable and other environment variable proxy settings will be disregarded.
228
257
 
229
258
  ## Reusable ports
230
259
 
@@ -282,6 +311,12 @@ Excon.stub({}, lambda {|request_params| {:body => request_params[:body], :status
282
311
 
283
312
  Omitted attributes are assumed to match, so this stub will match *any* request and return an Excon::Response with a body of 'body' and status of 200. You can add whatever stubs you might like this way and they will be checked against in the order they were added, if none of them match then excon will raise an `Excon::Errors::StubNotFound` error to let you know.
284
313
 
314
+ If you want to allow unstubbed requests without raising `StubNotFound`, set the `allow_unstubbed_requests` option either globally or per request.
315
+
316
+ ```ruby
317
+ connection = Excon.new('http://example.com', :mock => true, :allow_unstubbed_requests => true)
318
+ ```
319
+
285
320
  To remove a previously defined stub, or all stubs:
286
321
 
287
322
  ```ruby
@@ -390,6 +425,20 @@ connection = Excon.new('https://example.com',
390
425
 
391
426
  `client_key_pass` is optional.
392
427
 
428
+ If you already have loaded the certificate and key into memory, then pass it through like:
429
+
430
+ ```ruby
431
+ client_cert_data = File.load 'mycert.pem'
432
+ client_key_data = File.load 'mycert.key'
433
+
434
+ connection = Excon.new('https://example.com',
435
+ client_cert_data: client_cert_data,
436
+ client_key_data: client_key_data)
437
+ ```
438
+
439
+ This can be useful if your program has already loaded the assets through
440
+ another mechanism (E.g. a remote API call to a secure K:V system like Vault).
441
+
393
442
  ## HTTPS/SSL Issues
394
443
 
395
444
  By default excon will try to verify peer certificates when using HTTPS. Unfortunately on some operating systems the defaults will not work. This will likely manifest itself as something like `Excon::Errors::CertificateError: SSL_connect returned=1 ...`
@@ -417,6 +466,27 @@ Either of these should allow you to work around the socket error and continue wi
417
466
 
418
467
  Please refer to [CONTRIBUTING.md](https://github.com/excon/excon/blob/master/CONTRIBUTING.md).
419
468
 
469
+ # Plugins and Middlewares
470
+
471
+ Using Excon's [Middleware system][middleware], you can easily extend Excon's
472
+ functionality with your own. The following plugins extend Excon in their own
473
+ way:
474
+
475
+ * [excon-addressable](https://github.com/JeanMertz/excon-addressable)
476
+
477
+ Set [addressable](https://github.com/sporkmonger/addressable) as the default
478
+ URI parser, and add support for [URI templating][templating].
479
+
480
+ * [excon-hypermedia](https://github.com/JeanMertz/excon-hypermedia)
481
+
482
+ Teaches Excon to talk with [HyperMedia APIs][hypermedia]. Allowing you to use
483
+ all of Excon's functionality, while traversing APIs in an easy and
484
+ self-discovering way.
485
+
420
486
  ## License
421
487
 
422
488
  Please refer to [LICENSE.md](https://github.com/excon/excon/blob/master/LICENSE.md).
489
+
490
+ [middleware]: lib/excon/middlewares/base.rb
491
+ [hypermedia]: https://en.wikipedia.org/wiki/HATEOAS
492
+ [templating]: https://www.rfc-editor.org/rfc/rfc6570.txt