Giter Site home page Giter Site logo

reqwest's Introduction

reqwest

crates.io Documentation MIT/Apache-2 licensed CI

An ergonomic, batteries-included HTTP Client for Rust.

  • Async and blocking Clients
  • Plain bodies, JSON, urlencoded, multipart
  • Customizable redirect policy
  • HTTP Proxies
  • HTTPS via system-native TLS (or optionally, rustls)
  • Cookie Store
  • WASM

Example

This asynchronous example uses Tokio and enables some optional features, so your Cargo.toml could look like this:

[dependencies]
reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1", features = ["full"] }

And then the code:

use std::collections::HashMap;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let resp = reqwest::get("https://httpbin.org/ip")
        .await?
        .json::<HashMap<String, String>>()
        .await?;
    println!("{resp:#?}");
    Ok(())
}

Commercial Support

For private advice, support, reviews, access to the maintainer, and the like, reach out for commercial support.

Requirements

On Linux:

  • OpenSSL with headers. See https://docs.rs/openssl for supported versions and more details. Alternatively you can enable the native-tls-vendored feature to compile a copy of OpenSSL.

On Windows and macOS:

  • Nothing.

Reqwest uses rust-native-tls, which will use the operating system TLS framework if available, meaning Windows and macOS. On Linux, it will use the available OpenSSL or fail to build if not found.

License

Licensed under either of

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Sponsors

Support this project by becoming a sponsor.

reqwest's People

Contributors

alex avatar blackdex avatar budziq avatar danieleades avatar daxpedda avatar dependabot[bot] avatar ducaale avatar est31 avatar jaemk avatar jplatte avatar kamilaborowska avatar knight42 avatar little-dude avatar lucab avatar luro02 avatar messense avatar nickelc avatar nobodyxu avatar nyurik avatar paolobarbolini avatar pfernie avatar quininer avatar seanmonstar avatar tafia avatar theduke avatar tomprince avatar windsoilder avatar x1957 avatar yageek avatar yujincheng08 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reqwest's Issues

Add Response::text()?

Currently, you can run into a (somewhat) surprising condition when you read the body of a Response twice.

  • `resp.read_to_string(&mut s);
  • resp.json()

or just

  • `resp.read_to_string(&mut s);
  • `resp.read_to_string(&mut s);

While to many it will occur quickly that the problem is reading the response twice, I think this can be improved.

.json() already consumes the response, but the Read trait methods do not.

Maybe there could be a body() method which returns a Read and also consumes the response.

Support timeouts

First, thank you for this higher level crate, it's appreciated!

We're looking at switching from hyper's client to reqwest in Rusoto which will be nice to avoid openssl issues and make our code more concise. We use the set_read_timeout of hyper's client in a couple spots to avoid waiting around too long.

Are there plans for adding this to reqwest? At first glance adding it to RequestBuilder would be a good spot. I've not looked at much of the reqwest code to see how it'd be added, though.

Rusoto use of set_read_timeout is here.

Ergonomics of custom headers (header macro)

It might be nice to duplicate hyper's header! macro for sending custom headers - for lack of macro_reexport. I moved an API client from hyper to reqwest, and custom headers is now the only reason I directly depend on hyper. Alternatively, splitting out headers (a la hyperium/hyper#894) into hyper-headers or hyper-types also seems like a reasonable way to get the extra macro.

Use native-tls

Disable the default ssl feature of hyper, and instead use only rust-native-tls.

help with JSON decoding using serde derived types

I'm trying to get the following code to compile, but I'm having issues:

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate reqwest;

#[derive(Serialize, Deserialize, Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn foo<'a, T: serde::de::Deserialize<'a>>(t: T) { }

fn main() {
    let point = Point{x: 1, y: 2};
    foo(point); // <-- should prove that Point implements the serde::de::Deserialize trait


    let client = reqwest::Client::new().unwrap();
    let mut resp = client.get("http://localhost/").send().unwrap();
    let p: Point = resp.json().unwrap();
}

Here's the compile here:

error[E0277]: the trait bound `Point: serde::de::Deserialize` is not satisfied
  --> src/main.rs:23:25
   |
23 |     let p: Point = resp.json().unwrap();
   |                         ^^^^ the trait `serde::de::Deserialize` is not implemented for `Point`

Because I'm able to pass a Point to foo(), I think this proves that serde::de::Deserialize is implemented for Point. So I'm quite confused when rust tells me that Deserialzie is not implemented for Point.

It is user error? rust error? something else? Thanks!

Include the URL that could not be requested in `reqwest::Error`

There is no programmatic way to know which URL failed when making a request. The URL given to RequestBuilder is not necessarily the one that failed because of redirects, and even if RequestBuilder did expose ithe URL it was created with (it doesn't have a getter for it at the moment) it gets consumed by send() anyway. So it seems to me the Error returned by send() would be the correct place to include this URL.

It would be even better to include a Vec of URLs in case of redirects.

Support either multipart or Body::sized

Hello! I've converted a bunch of our internal production code over to reqwest in preparation for the arrival of async hyper. It's working really well, and thank you for providing this transition path.

Right now, I'm dealing with a problem with the BigML API. I'm trying to upload multi-gigabyte CSV data files as a MIME multipart form attachment. Unfortunately, BigML requires MIME multipart, and it doesn't support chunked transfer encoding. I have a workaround for the missing multipart support mentioned in #4: I create a custom Reader type that generates a simple multipart body.

Unfortunately, this doesn't quite work. I need to read the entire file into memory anyway, because reqwest's Body::sized method is unimplemented. And this is when our server code crashes.

I'd definitely be interested in preparing a PR that implements something like the following:

pub fn sized<R: Read>(reader: R, len: u64) -> Body

...or an equivalent impl<R: Read> Into<Body> for (R, u64) version.

I know that Read is a bit of a weird case in this brave new work of futures and tokio, but it's still a core Rust API for anybody not writing async code, and it might be good to support Read and sized data long term.

If that's really not interesting, I could take a look at multipart, but that's more complicated to do right (our little workaround only handles a single file attachment).

We have two short-term workarounds that will help minimize this problem in production, but we'll need to find a solution soon, even if that means switching to hyper (either the current released version or async).

Thank you for any advice and guidance you can provide!

cookie jar implementation

About a year ago I wrote a user_agent crate (not published to crates.io) for an internal project, which provides the concept of a Session wrapping a Client and does cookie handling per RFC6265. At the time, the only client I targeted was hyper::Client. I'd be interested in updating/adapting the code to reqwest, but wanted to touch base on any existing plans/work here.

First off, the library suffers some warts:

  • Perhaps not the cleanest rust, one of the first libraries I developed when first learning rust.
  • It implements its own Cookie class, which wraps/extends the existing cookie crate (providing a From implementation to handle conversion). This was to introduce some more domain objects (CookiePath, CookieDomain, etc.) to enforce/aid the implementation of some RFC6265 guidelines.
  • At the time, hyper was on a different (0.1?) version of cookie-rs, whereas I was developing against a more recent version (0.2+?), meaning the library goes through some gyrations to "convert" between the two versions by stringifying-then-parsing cookies.
  • While I wrote a fair set of tests, usage and testing was primarly geared towards my particular use case at the time, so implementation re: RFC6265 may not be complete or necessarily fully correct.

Some of these issues can be cleaned up over time, but in terms of bigger picture I have some questions/concerns:

  • The re-implementation/extension of Cookie seems un-necessary; submitting PRs against cookie-rs to bring them in line would make sense...
  • cookie-rs already provides a CookieJar, implementing hierarchical jars and jar signing. In my crate, user_agent::CookieStore is more concerned with storing/expiring/updating cookies per RFC6265, and handles storing cookies and setting outgoing cookie headers based on URLs visited during the Session, as well as serializing the current session (to .json currently, but really to anything serde will serialize to) so they can be saved/restored. So, they are in some sense orthogonal currently, but feels as though they could be merged as well.
  • As mentioned, the crate currently tries to generalize the concept of Session, although the only concrete impl is HyperSession. This was done with the vain hope of making a library for "all the webs" (curl clients, etc.), but the realities of needing to get my project done means this was (IMO) sub-optimally implemented. I'm not sure if it makes more sense to ditch the currently not very ergonomic abstraction and focus on implementing specifically towards reqwest, or to fix/maintain the abstraction and publish the crate separately as user_agent and just implement a ReqwestSession here. At a high level, the Session implementation is mainly concerned with defining how to get/set cookies into/out of Request/Response objects.

Obviously some questions would be more easily answered with some code to review; I just wanted to get a feel for the lay of the land before updating code to be suitable for a PR.

Add a json method to Response

This would allow a user to write:

let thing: Thing = res.json()?;

The implementation would need to use T: Deserialize and serde_json::from_reader:

impl Response {
    pub fn json<T: Deserialize>(&mut self) -> ::Result<T> {
        // probably should check self.headers.get::<ContentType> for application/json
        serde_json::from_reader(&mut self).map_err(::Error::from)
    }
}

Disable SSL certificate validation

Since hyper is not exposed (and I'm not sure it's even possible currently with hyper), there needs to be a way to disable certificate validation, if using a self signed certificate for example and you can't install CAs in your environment.

Something like Client::ssl_no_verify(&mut self).

Add a Request type

When building a client API based on reqwest, I would often want to modify or inspect the private fields on RequestBuilder, namely method, url, headers and body.

Since they are private, you basically have to create your own builder and convert it, which is annoying.

What do you think about either making the fields public or providing getters/setters?

Should the convenience methods be behind features?

Perhaps people don't need some parts of reqwest that are provided for convenience. Such as, maybe someone only wants to post forms, and never needs JSON support. If each were behind a feature, a user could try to reduce the amount of dependencies they need to compile that they are not using.

JSON deserializing doesn't work with other charsets

Hi,

I'm trying to write a front-end for a website which delivers json with Content-Type: application/json; charset=windows-1252, but reqwest::Response::json() fails with Err(Serialize(Syntax(InvalidUnicodeCodePoint, 34, 37))).
I guess it didn't do the conversion by itself and chokes on that charset.

Is there a way to send files?

I want to send files to a server, how can I achieve that with Reqwest like this:

curl -v -F upload=@localfilename URL

Add JSON support to RequestBuilder

Using serde/serde_json:

// on RequestBuilder
fn json<T: Serializable>(mut self, json: T) -> Self {
    // sets Content-Type to json
    // sets body to serialized json bytes
}

Would allow:

reqwest::post(url)
    .json(SomeSerializableThingy::new())
    .send()

Handle 307 and 308 redirects

These are new and are defined that if returned for a POST, the client should repeat the POST at the new location, and resend the body.

Implement default RedirectPolicy

This should replace hyper's default, to instead behave like browsers:

  1. GET and HEAD will automatically follow on 301 and 302.
  2. POST and PUT will follow on 301 and 302, but will change the method to GET.
  3. Prevent some headers from being forwarded, like Cookie, Authorization, etc.
  4. Add a Referer header when following.

The implementation will need to be done in this crate, setting the hyper::client::RedirectPolicy to FollowNone, and then doing it inside the send method.

example failed on Android for cert verification

cargo dinghy run --example simple

thread 'main' panicked at 'called Result::unwrap() on an Err value: Http(Ssl(Failure(Ssl(ErrorStack([Error { code: 336134278, library: "SSL routines", function: "ssl3_get_server_certificate", reason: "certificate verify failed", file: "s3_clnt.c", line: 1264 }])))))', /checkout/src/libcore/result.rs:859
note: Run with RUST_BACKTRACE=1 for a backtrace.

Change RequestBuilder to return a Request, instead of using send() method?

As I've been going through and refactoring the RequestBuilder struct (#22), it feels like getting it to verify that it was set up successfully, then also send itself while making sure to handling redirects properly is a lot of work for a simple builder to do.

Normally you would use the builder pattern to just configure an object, check it was set up properly, and then pass that onto something else so operations can be done with it. I've also been fighting the borrow checker a lot due to the fact that every RequestBuilder holds a reference back to its client, although that could just be because I'm doing something silly.

Instead, would it make sense to construct a request and then pass it to the client to send as two distinct steps? I'm imagining a google search might look like this:

use reqwest::{Client, Request, RequestBuilder};
use std::collections::HashMap;

fn main() {
  let url = "https://google.com/";
  let mut data = HashMap::new();
  data.insert("q", "wikipedia");

  let client = Client::New().unwrap();

  let req: Request = RequestBuilder::get(url)
      .form(data)
      .verify()
      .unwrap();

  let response = client.send(req).unwrap();
  println!("{}", response.status());
}

And for convenience you might have the top level get() and post() methods which internally create a new client, set up the request, get the client to send that request, and then return the response.

I guess the biggest change for users would be that a Request and Client are less tightly coupled, meaning you have to fight the borrow checker a lot less since your requests no longer have references to a client. It'll also make our lives a lot easier when we have to change everything to work with the asynchronous hyper release.

That said, it's a non-trivial change to the library's API so you've got to think about backwards compatibility and what is the most ergonomic for users to use. I'll look to see how other libraries have done it, but I'd be interested in seeing what everyone else's thoughts are.

cc: @seanmonstar

(Optionally?) re-export hyper's header! macro

I've found myself needing to define a custom header for a CSRF token. I was hoping this code would work, but got an error that the macro was undefined:

#[macro_use]
extern crate reqwest;

header! { (XCsrfToken, "X-CSRFToken") => [String] }

Unless I'm missing something, getting this to work will require adding hyper to Cargo.toml as well as an extern crate declaration. That feels heavyweight for this case.

I'm wondering if this would need to be optional to avoid macro name collisions for projects that separately depend on hyper; in that case, would a feature work?

Trust a public key

Would it be in or out of scope to be able to specify trusted public keys in reqwest?

Reqwest hijacks Header type from hyper without header! macro

After constructing a custom header via hyper's header! macro, I attempt to retrieve the header from the response, but get a the trait `reqwest::header::HeaderFormat` is not implemented for `MyCustomHeader` .

It also appears the header! macro is not brought into reqwest, meaning custom headers must be implemented manually.

Strange mutability error

let mut res = reqwest::get("https://api.ipify.org").unwrap();

let mut ip = String::new();
res.read_to_string(&mut ip).unwrap();

This code results in a warning, from which I'm removing line numbers because I shuffled things around to isolate the error:

warning: variable does not need to be mutable, #[warn(unused_mut)] on by default
 --> main.rs:
  |
  | 	let mut res = match reqwest::get("https://api.ipify.org") {
  | 	    ^^^^^^^

So, following the warning, I remove mut in the first line:

let res = reqwest::get("https://api.ipify.org").unwrap();

let mut ip = String::new();
res.read_to_string(&mut ip).unwrap();

Which results in a compiler error:

  --> main.rs
   |
   |     let res = reqwest::get("https://api.ipify.org").unwrap();
   |         --- use `mut res` here to make mutable
...
   | 	res.read_to_string(&mut ip).unwrap();
   |  ^^^ cannot borrow mutably

This doesn't seem like something that would be intentional. Does the implementation of read_to_string in Response affect its mutability? Or could this be a bug in Rust's immutability violation detection?

I'm using requests 0.1.0 and, as for Rust, I just started learning it and I can't seem to find a way to verify the version number of my compiler. That seems like a strange oversight.

Panic in Client::head with automatic GZIP decompression

When using reqwest::Client to make a HEAD request with GZIP decompression enabled (which is the default), a panic happens in the library.

Code to reproduce:

use reqwest::Client;
fn main() {
    let url = "https://www.google.com/";
    let client = Client::new().unwrap();
    client.head(url).send();
}

Backtrace:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { repr: Custom(Custom { kind: UnexpectedEof, error: StringError("failed to fill whole buffer") }) }', /checkout/src/libcore/result.rs:859
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
             at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::_print
             at /checkout/src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at /checkout/src/libstd/sys_common/backtrace.rs:60
             at /checkout/src/libstd/panicking.rs:355
   3: std::panicking::default_hook
             at /checkout/src/libstd/panicking.rs:371
   4: std::panicking::rust_panic_with_hook
             at /checkout/src/libstd/panicking.rs:549
   5: std::panicking::begin_panic
             at /checkout/src/libstd/panicking.rs:511
   6: std::panicking::begin_panic_fmt
             at /checkout/src/libstd/panicking.rs:495
   7: rust_begin_unwind
             at /checkout/src/libstd/panicking.rs:471
   8: core::panicking::panic_fmt
             at /checkout/src/libcore/panicking.rs:69
   9: core::result::unwrap_failed
             at /checkout/src/libcore/macros.rs:29
  10: <core::result::Result<T, E>>::unwrap
             at /checkout/src/libcore/result.rs:737
  11: reqwest::client::Decoder::from_hyper_response
             at /home/martin/.cargo/registry/src/github.com-1ecc6299db9ec823/reqwest-0.5.1/src/client.rs:458
  12: reqwest::client::RequestBuilder::send
             at /home/martin/.cargo/registry/src/github.com-1ecc6299db9ec823/reqwest-0.5.1/src/client.rs:331
  13: main::bug_repro
             at ./src/main.rs:41
  14: main::main
             at ./src/main.rs:47
  15: std::panicking::try::do_call
             at /checkout/src/libstd/panicking.rs:454
  16: __rust_maybe_catch_panic
             at /checkout/src/libpanic_unwind/lib.rs:98
  17: std::rt::lang_start
             at /checkout/src/libstd/panicking.rs:433
             at /checkout/src/libstd/panic.rs:361
             at /checkout/src/libstd/rt.rs:57
  18: main
  19: __libc_start_main
  20: _start

Here's the debug log: log.txt
When I disable automatic decompression (client.gzip(false)), it works fine.

Hangs in OSX reading certain sized responses unless specifying `Connection::close`

I'm making an authenticated GET request that succeeds, but any attempt to read_to_string or read_to_end just hangs indefinitely, but only under all the following criteria:

  • OSX (works fine on linux)
  • responses in the range of 3835-16120 bytes (~260 bytes short of the 4K/16K boundaries).
  • over SSL (works fine if I make the same request through a local http nginx proxy)

This is the debug output of an example Response object I see before it hangs during reading:

Response { inner: Response { status: Ok, headers: Headers { Date: Wed, 23 Nov 2016 03:06:35 GMT, X-Frame-Options: DENY, Strict-Transport-Security: max-age=0; includeSubDomains; preload, X-Data-Type: directory, Connection: keep-alive, Content-Length: 7452, Content-Type: application/json; charset=utf-8, }, version: Http11, url: "https://api.algorithmia.com/v1/connector/data/anowell/foo", status_raw: RawStatus(200, "OK"), message: Http11Message { is_proxied: false, method: None, stream: Wrapper { obj: Some(Reading(SizedReader(remaining=7452))) } } } }

And yet, I haven't managed to repro this with a simple test script to just reqwest::get some public URL in that size range, so I'm still missing some contributing factor. I've also tried an old build of my client which used hyper+openssl, and it had no issue.

Things on my mind to try still:

  • Read in smaller chunks to see if perhaps read_to_end is waiting on the wrong number of bytes
  • Put together the minimal repro using an API key for a shareable test account
  • Try a bit harder to find a repro outside of our API

make Error implement Send

Thank you for another great HTTP client library! I'm trying to convert some existing code, and I ran into a minor problem with the reqwest::Error type: It can't be used out-of-the-box with the error-chain crate, because it doesn't implement Send.

error: no method named `chain_err` found for type `std::result::Result<reqwest::Response, reqwest::Error>` in the current scope
  --> src/fdy/alchemist.rs:58:14
   |
58 |             .chain_err(&mkerr)?;
   |              ^^^^^^^^^
   |
   = note: the method `chain_err` exists but the following trait bounds were not satisfied: `reqwest::Error : std::marker::Send`
   = help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `chain_err`, perhaps you need to implement it:
   = help: candidate #1: `errors::ChainErr`

This is usually a pretty easy fix: It's typically caused using Box<Error> somewhere instead of Box<Error + Send + 'static>, but I haven't looked at the code yet.

Deprecate `Client` in favor of `SyncClient`

Could we move away from naming one of the clients "defacto-default"? i.e. Calling them: reqwest::AsyncClient and reqwest::Client implies that the sync client is the default and async is somehow special and warrants investigation.

Using reqwest::AsyncClient and reqwest::SyncClient would be equally ergonomic, and allocates zero preference towards either implementation.

As per our exchange on reddit, we could do the following:

#[deprecated(note = "renamed to SyncClient")]
pub type Client = SyncClient;

P.S. As long as there isn't much opposition to this idea, this change is easy enough, I'm happy to do it if needed.

Adding a file through .body() isn't working

I'm trying to send a file with Reqwest like this:

let mut data = self.client.post(&url).body(photo).send()?;

When I split it up and print the part before .send() I get:

RequestBuilder { method: Post, url: Ok("url"), headers: Headers { } }

As you can see there's no file, what's happening?

How to disable sl_verify_host and ssl_verify_peer as in cur self sign certificate

Hello,

How to disable sl_verify_host and ssl_verify_peer as in curl? easy.ssl_verify_host(false);, easy.ssl_verify_peer(false);

thread 'main' panicked at 'called Result::unwrap() on an Err value: Http(Ssl(Failure(Error { code: -9807, message: "invalid certificate chain" })))', /Users/rustbuild/src/rust-buildbot/slave/stable-dist-rustc-mac/build/src/libcore/result.rs:837
stack backtrace:
1: 0x103ae461a - std::sys::imp::backtrace::tracing::imp::write::hd3b65cdfe843284c
2: 0x103ae5e1f - std::panicking::default_hook::{{closure}}::hf2b7428652613d83
3: 0x103ae5ac7 - std::panicking::default_hook::h5da8f27db5582938
4: 0x103ae62e6 - std::panicking::rust_panic_with_hook::hcef1e67c646c6802
5: 0x103ae6184 - std::panicking::begin_panic::hc2e8ca89533cd10d
6: 0x103ae60a2 - std::panicking::begin_panic_fmt::h60990696c3c3a88d
7: 0x103ae6007 - rust_begin_unwind
8: 0x103b08e70 - core::panicking::panic_fmt::h10231c789bd0e97d
9: 0x1039e3372 - core::result::unwrap_failed::h3784e0270242ad22
10: 0x1039e25fd - <core::result::Result<T, E>>::unwrap::h43c88b7bd7ac2171
11: 0x1039e5828 - rilo::main::hcbfea6bed773d6cd
12: 0x103ae716a - __rust_maybe_catch_panic
13: 0x103ae6686 - std::rt::lang_start::h87cb84a8b6cb187e
14: 0x1039e5919 - main

Process finished with exit code 101

Thank you

Logging

Right now, if you want to provide a way to log all requests and responses on a client, you have to wrap every request yourself, log pre send, read the response, log it and then return some custom response type.

That's a bit awkward.

Any ideas for implementing logging?

Support Read for Request Body

With hyper, we can create a request body from a Read, so you can use an owned Cursor over borrowed bytes. That means you can re-use the same data over multiple requests without having to copy it multiple times.

With reqwest, we can only use an owned Vec<u8>, which means copying those bytes each time.

Is this a feature that aligns with reqwest or am I better off dropping down to hyper if that's a problem?

Fluent / Chained interface

Just an API idea. It would be nice if the Client interface were in a chained style. Right now, I need to do this:

let mut client = Client::new()?;
client.timeout(Duration::from_secs(5));
let request_builder = client.post();

If functions like timeout or gzip would return self, then the API would look like this:

let request_builder = Client::new()?
    .timeout(Duration::from_secs(5))
    .post();

Maintaining both APIs would also be possible, by adding with_timeout(self, timeout: Duration) instead of changing the current API.

Feel free to close this issue if you disagree :)

Publish a new version on crates.io?

Would it be possible to publish the current version on crates.io, even if it's just a 0.1.1? I am using this with the error-chain crate in another crate that I am building, and the 0.1.0 version doesn't work correctly with error-chain, so I have to depend on the git repo here instead of the crates.io version of reqwest. This means we can't publish crates that depend on reqwest to crates.io, which disallows git dependencies.

Really slow performance?

So I'm playing around writing a client for EVE online's ESI API (https://esi.tech.ccp.is/latest/) and while it's pretty simple, it's also extremely slow (1-2 queries per second, as opposed to ~100 that I would expect).

I don't expect anyone to be familiar with ESI, but is there anything that I'm doing clearly wrong that could account for the bad performance? Could the fact that it's HTTPS be contributing?

extern crate reqwest;

#[macro_use]
extern crate serde_derive;

#[derive(Debug, Deserialize)]
struct MarketGroup {
    description: String,
    market_group_id: u32,
    name: String,
    parent_group_id: Option<u32>,
    types: Vec<u32>,
}

fn main() {
    println!("starting");

    let ids = market_group_ids();
    for id in &ids {
        println!("{:?}", market_group(id));
    }

    println!("all done");
}

fn market_group_ids() -> Vec<u32> {
    reqwest::get("https://esi.tech.ccp.is/latest/markets/groups/")
        .unwrap()
        .json()
        .unwrap()
}

fn market_group(market_group_id: &u32) -> MarketGroup {
    let url = format!("https://esi.tech.ccp.is/latest/markets/groups/{}",
                      market_group_id);
    reqwest::get(&url).unwrap().json().unwrap()
}

How to handle sessions?

Can reqwest handle sessions?

If a request get a Set-Cookie header, can that cookie be set automatically for the next request to the same domain?

In this example, the value of the Set-Cookie BeenThere should increase for each request (can be seen from a browser, the value is increased on each re-load):

extern crate reqwest;

fn main() {
    let client = reqwest::Client::new().unwrap();
    let resp = client.get("https://api.zioup.com/").send().unwrap();
    println!("{}\n", resp.headers());
    let resp = client.get("https://api.zioup.com/").send().unwrap();
    println!("{}\n", resp.headers());
}

Allow opt-in insecure requests to HTTPS URLs

The author of a client library/tool isn't always able to stop a server from using self-signed or otherwise-invalid certificates. Is there a way to ask reqwest to ignore validation for a specific request?

(In my specific scenario, the server will only respond over HTTPS, so asking over bare HTTP isn't an option either)

Connection timeouts when Client lives a long time

We have a Client object which we persist for a long time (ideal would be "forever") which has sporadic usage over the course of a day. After a longer period of being idle, we sometimes see connections immediately replied with a TCP RST packet causing a failure. Is it possible to manually flush the connection queue, remove the Keep-Alive header on the requests, or otherwise reset the connection pool after some timeout to avoid issues?

Cc: @bradking

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.