Commit Graph

124 Commits

Author SHA1 Message Date
Jacob Hoffman-Andrews
f14fc45179 Buffer short responses (2) (#531)
* Response: build reader at construction time

* Remove unwrapping/rewrapping DeadlineStream

* Let into_reader() provide Sync + 'static

* Prebuffer Vec use known capacity

Co-authored-by: Martin Algesten <martin@algesten.se>
2022-07-10 11:12:50 +02:00
Jacob Hoffman-Andrews
9908c446d6 Simplify ReadWrite interface (#530)
Previously, ReadWrite had methods `is_poolable` and `written_bytes`, which
were solely for the use of unittests.

This replaces `written_bytes` and `TestStream` with a `struct Recorder`
that implements `ReadWrite` and allows unittests to access its recorded
bytes via an `Arc<Mutex<Vec<u8>>>`. It eliminates `is_poolable`; it's fine
to pool a Stream of any kind.

The new `Recorder` also has some convenience methods that abstract away
boilerplate code from many of our unittests.

I got rid of `Stream::from_vec` and `Stream::from_vec_poolable` because
they depended on `TestStream`. They've been replaced by `NoopStream` for
the pool.rs tests, and `ReadOnlyStream` for constructing `Response`s from
`&str` and some test cases.
2022-07-09 10:13:44 -07:00
Jacob Hoffman-Andrews
0cf1f8dbb9 Add Sync traits to ReadWrite trait (#528)
This allows us to get rid of a Mutex (and not take a dependency on
sync_wrapper).
2022-07-05 01:52:25 -07:00
Jacob Hoffman-Andrews
4bb6d3a4db DeadlineStream: read from Stream's buffer first (#508)
This fixes an issue where requests with a deadline would do a syscall
on every read, rather than pulling from the buffer. Fixes a problem
reported in #506 where `resp.into_json()` was unnecessarily slow.
2022-05-09 10:31:59 -07:00
Martin Algesten
4675d748e9 Remove Sync bound from TlsConnector io arg 2022-05-07 14:39:59 +02:00
Martin Algesten
049b5a5acd Fixes after feedback 2022-05-07 14:39:59 +02:00
Martin Algesten
65371c966c Box<dyn ReadWrite> for TlsConnector::connect 2022-05-07 14:39:59 +02:00
Jacob Hoffman-Andrews
101467f13f Return stream to pool on exact read (#509)
If the user reads exactly the number of bytes in the response, then
drops the Read object, streams will never get returned to the pool since
the user never triggered a read past the end of the LimitedRead.

This fixes that by making PoolReturnRead aware of the level below it, so
it can ask if a stream is "done" without actually doing a read.

Also, a refactorign:

Previously, Response contained an Option<Box<Unit>> because the testing
method `from_str()` would construct a Response with no associated Unit.
However, this increased code complexity with no corresponding test
benefit. Instead, construct a fake Unit in from_str().

Also, instead of taking an `Option<Box<Unit>>`, PoolReturnRead now takes
a URL (to figure out host and port for the PoolKey) and an &Agent where
it will return the stream. This cuts interconnectedness somewhat:
PoolReturnRead doesn't need to know about Unit anymore.
2022-04-30 17:22:27 -07:00
Martin Algesten
2c29cc230c Remove Sync requirement of ReadWrite trait
3rd party TLS connections are currently required to provide a Sync
guarantee. Since ureq will only ever use the connection on a single
thread, this is not necessary.

The reason we end up with this bound is because we want Response and
Error to be Sync, in which case Rust's automatic inferral of Sync
fails.

This change "masks" the Stream in a wrapper making it Sync.

Close #474
2022-01-30 21:50:11 +01:00
Martin Algesten
219b5edf9e Rename test function as_write_vec -> into_written_bytes
Tests use `Response::as_write_vec` to inspect the outgoing HTTP/1.1
request line and headers. The current version has two problems:

1. Called `as_write_vec` when it actually returns a `&[u8]`.
2. Inspects/uses the `Response::stream` without consuming `Response`.

The first problem is trivial, but the second is subtle. Currently all
calls on `Response` that works with the internal `Response::stream`
consumes `self` (`into_string`, `into_reader`).

`Response` is by itself `Send + Sync`, and must be so because the
nested Stream is `Read + Write + Send + Sync`. However for
implementors of `TLSStream`, it would be nice to relax the `Sync`
requirement.

Assumption: If all fields in Response are `Sync` except
`Response::stream`, but any access to `stream` consumes `Response`, we
can consider the entire `Response` `Sync`.

This assumption can help us relax the `TlsStream` `Sync` requirement
in a later PR.
2022-01-29 17:32:18 +01:00
Martin Algesten
6e5041044b Rename trait HttpsStream -> ReadWrite and make it public
Also provide an example of how to use it.
2022-01-22 10:41:22 +01:00
Daniel
140aa5901f Add tcp no_delay option (#465)
* Add tcp no_delay option
2022-01-06 23:22:33 +01:00
Martin Algesten
75f6be8ff8 Format error message like suggested in review 2021-12-19 21:17:26 +01:00
Martin Algesten
f3857eed00 Ensure we provide a Transport::message() when we can 2021-12-19 21:17:26 +01:00
Jacob Hoffman-Andrews
56276c3742 Add support for alternate TLs implementations. 2021-12-17 17:47:30 +01:00
Malloc Voidstar
1c1dfaa691 Bump rustls to 0.20.1; add src to rustls error (#438) 2021-12-17 00:32:00 -08:00
Martin Algesten
a6d1750f14 Fix native-certs and add to test matrix
Close #239
2021-11-28 22:45:16 +01:00
Malloc Voidstar
31dd67380e Return error for InvalidDnsNameError, don't panic (#436)
Can't provide src for the error as rustls 0.20 didn't implement stdlib Error for it; it's on main and targeted for 0.20.1.
2021-11-12 17:15:39 -08:00
Jacob Hoffman-Andrews
3bc7d8336b Fix lint 2021-10-21 07:38:59 +02:00
Jacob Hoffman-Andrews
5fa912c4d3 Update to rustls 0.20, webpki 0.22 2021-10-21 07:38:59 +02:00
Keijia
2869a80130 oh, use None != proto instead of proto.is_some() 2021-08-23 20:46:44 +02:00
Keijia
c7292919e5 fix build fails 2021-08-23 20:46:44 +02:00
Keijia
12b49e59f4 whoops, fix HTTPConnect proxies 2021-08-23 20:46:44 +02:00
Keijia
bdaa9fc68c add support for socks4 and socks4a 2021-08-23 20:46:44 +02:00
Martin Algesten
526eb7b9e0 Fix clippy lints 2021-08-23 20:45:33 +02:00
Niketh Murali
4665b0aa5a Fix clippy warnings
Fix linter warning from clippy about unnecessary borrows - "This expression borrows a reference ... that is immediately dereferenced by the compiler"
2021-08-13 09:26:04 +02:00
Martin Algesten
989995d1ba Fix clippy lints (#387) 2021-05-11 18:05:17 -07:00
Jacob Hoffman-Andrews
50d9ccff8c Don't reuse conns with bytes pending from server (#372)
This makes us less likely to try and reuse a closed connection, which
produces problems in particular for requests that can't be retried.

Fixes #361
Fixes #124
2021-04-18 10:46:20 -07:00
Martin Algesten
b42e9afd71 Fix clippy warnings 2021-03-24 20:29:43 +01:00
Jacob Hoffman-Andrews
a34d450657 Remove specialized error message for complete_io. (#349)
This was triggering for errors like InvalidCertificate and giving the
message "Sometimes this means the host doesn't support any of the same
ciphersuites as rustls, or doesn't support TLS 1.2 and above," which is
confusing in that situation.

For now, offer no specialized error. I'd like to come back when I find
more time and restore this, but only for the error cases where it's
useful.
2021-03-23 17:00:09 -07:00
trevyn
1e5307cbca Fix typo: "patform" -> "platform" (#332) 2021-02-22 10:34:46 -08:00
Jacob Hoffman-Andrews
413e8bf4aa Fix imports 2021-02-21 13:32:42 -08:00
Jacob Hoffman-Andrews
671f24ab49 Offer separate error during handshakes.
It's useful to know that an error was specific to the TLS handshake,
versus the TCP connect, or a later stage of a request.
2021-02-21 13:20:38 -08:00
Jacob Hoffman-Andrews
6c9378ce37 De-redundantize Error kinds. (#259)
Change "Bad" to "Invalid" in error names, mimicking io::Error::ErrorKind.

Change InvalidProxyCreds to ProxyUnauthorized.

Change DnsFailed to just Dns (the fact that there was a failure is implicit
in the fact that this was an error).
2020-12-05 12:05:29 -08:00
Jacob Hoffman-Andrews
35c03521b9 Add debug logs for stream pooling. 2020-12-05 15:05:20 +01:00
Jacob Hoffman-Andrews
36b307423c Fix non-tls case correctly. 2020-11-29 00:02:37 -08:00
Jacob Hoffman-Andrews
6b6a59f215 Fix non-tls case. 2020-11-28 23:57:02 -08:00
Jacob Hoffman-Andrews
a286a7a22d Make DeadlineStream Read use the BufRead. 2020-11-28 23:33:28 -08:00
Jacob Hoffman-Andrews
6a22c54ba2 Small cleanups. 2020-11-28 22:34:32 -08:00
Jacob Hoffman-Andrews
50cb5cecd1 Fix buffered DeadlineStream 2020-11-28 17:47:17 -08:00
Jacob Hoffman-Andrews
131a0264d1 Move BufReader up the stack in Stream.
Stream now has an `Inner` enum, and wraps an instance of that enum in a
BufReader. This allows Stream itself to implement BufRead trivially, and
simplify some of the match dispatching. Having Stream implement BufRead
means we can make use of `read_line` instead of our own `read_next_line`
(not done in this PR yet).

Also, removes the `Cursor` variant of the Inner enum in favor of using
the `Test` variant everywhere, since it's strictly more powerful.
2020-11-28 12:04:28 -08:00
Jacob Hoffman-Andrews
fade03b54e Rewrite the Error type. (#234)
This adds a source field to keep track of upstream errors and allow
backtraces, plus a URL field to indicate what URL an error was
associated with.

The enum variants we used to use for Error are now part of a new
ErrorKind type. For convenience within ureq, ErrorKinds can be turned
into an Error with `.new()` or `.msg("some additional information")`.

Error acts as a builder, so additional information can be added after
initial construction. For instance, we return a DnsFailed error when
name resolution fails. When that error bubbles up to Request's
`do_call`, Request adds the URL.

Fixes #232.
2020-11-21 16:14:44 -08:00
Jacob Hoffman-Andrews
ec8dace1af Turn Unit into a built Request (#223)
This involved removing the Request reference from Unit, and adding an
Agent, a method, and headers.

Also, move is_retryable to Unit.
2020-11-14 01:12:01 -08:00
Jacob Hoffman-Andrews
920eccf37a Remove proxy method on request (#220) 2020-11-12 23:25:05 -08:00
Jacob Hoffman-Andrews
a52c6021cf Merge branch 'master' into release-2.0 2020-10-25 14:07:32 -07:00
Martin Algesten
1369c32351 API changes for 2.0
* Remove Request::build
* All mutations on Request follow builder pattern

The previous `build()` on request was necessary because mutating
functions did not follow a proper builder pattern (taking `&mut self`
instead of `mut self`). With a proper builder pattern, the need for
`.build()` goes away.

* All Request body and call methods consume self

Anything which "executes" the request will now consume the `Request`
to produce a `Result<Response>`.

* Move all config from request to agent builder

Timeouts, redirect config, proxy settings and TLS config are now on
`AgentBuilder`.

* Rename max_pool_connections -> max_idle_connections
* Rename max_pool_connections_per_host ->  max_idle_connections_per_host

Consistent internal and external naming.

* Introduce new AgentConfig for static config created by builder.

`Agent` can be seen as having two parts. Static config and a mutable
shared state between all states. The static config goes into
`AgentConfig` and the mutable shared state into `AgentState`.

* Replace all use of `Default` for `new`.

Deriving or implementing `Default` makes for a secondary instantiation
API.  It is useful in some cases, but gets very confusing when there
is both `new` _and_ a `Default`. It's especially devious for derived
values where a reasonable default is not `0`, `false` or `None`.

* Remove feature native_tls, we want only native rustls.

This feature made for very clunky handling throughout the code. From a
security point of view, it's better to stick with one single TLS API.
Rustls recently got an official audit (very positive).

https://github.com/ctz/rustls/tree/master/audit

Rustls deliberately omits support for older, insecure TLS such as TLS
1.1 or RC4. This might be a problem for a user of ureq, but on balance
not considered important enough to keep native_tls.

* Remove auth and support for basic auth.

The API just wasn't enough. A future reintroduction should at least
also provide a `Bearer` mechanism and possibly more.

* Rename jar -> cookie_store
* Rename jar -> cookie_tin

Just make some field names sync up with the type.

* Drop "cookies" as default feature

The need for handling cookies is probably rare, let's not enable it by
default.

* Change all feature checks for "cookie" to "cookies"

The outward facing feature is "cookies" and I think it's better form
that the code uses the official feature name instead of the optional
library "cookies".

* Keep `set` on Agent level as well as AgentBuilder.

The idea is that an auth exchange might result in a header that need
to be set _after_ the agent has been built.
2020-10-25 11:47:38 +01:00
Jacob Hoffman-Andrews
22e3839340 Review feedback. 2020-10-24 12:12:07 +02:00
Jacob Hoffman-Andrews
2bf9362eff Reinstate read timeouts on body.
This feature was broken in #67, which reset timeouts on the
stream before passing it to set_stream.

As part of this change, refactor the internal storage of
timeouts on the Request object to use Option<Duration>.

Remove the deadline field on Response. It wasn't used. The
deadline field on unit was used instead.

Add a unittest.
2020-10-24 12:12:07 +02:00
Jacob Hoffman-Andrews
e36c1c2aa1 Switch to Result-based API. (#132)
Gets rid of synthetic_error, and makes the various send_* methods return `Result<Response, Error>`.
Introduces a new error type "HTTP", which represents an error due to status codes 4xx or 5xx.
The HTTP error type contains a boxed Response, so users can read the actual response if they want.
Adds an `error_for_status` setting to disable the functionality of treating 4xx and 5xx as errors.
Adds .unwrap() to a lot of tests.

Fixes #128.
2020-10-17 00:40:48 -07:00
Jacob Hoffman-Andrews
257d4e54dd Switch timeout APIs to use Duration. 2020-10-17 09:23:01 +02:00