Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

async support #30

Open
JayceFayne opened this issue Jan 18, 2020 · 5 comments
Open

async support #30

JayceFayne opened this issue Jan 18, 2020 · 5 comments
Labels
enhancement New feature or request

Comments

@JayceFayne
Copy link

JayceFayne commented Jan 18, 2020

Are there any plans on adding async support?
Let me know if a pull request in that direction would be welcome.

@jayjamesjay jayjamesjay added the enhancement New feature or request label Jan 18, 2020
@jayjamesjay
Copy link
Owner

Yes, pull request in that direction would be welcome. But please try not to overuse dependencies, because it could make the library too heavy.

@cecton
Copy link

cecton commented Sep 7, 2021

@jayjamesjay are you expecting something with mio more like this?

tmp-h9kdub v0.1.0 (/home/cecile/.cache/cargo-temp/tmp-h9KDuB)
├── http_req v0.8.1
│   ├── native-tls v0.2.8
│   │   ├── log v0.4.14
│   │   │   └── cfg-if v1.0.0
│   │   ├── openssl v0.10.36
│   │   │   ├── bitflags v1.3.2
│   │   │   ├── cfg-if v1.0.0
│   │   │   ├── foreign-types v0.3.2
│   │   │   │   └── foreign-types-shared v0.1.1
│   │   │   ├── libc v0.2.101
│   │   │   ├── once_cell v1.8.0
│   │   │   └── openssl-sys v0.9.66
│   │   │       └── libc v0.2.101
│   │   │       [build-dependencies]
│   │   │       ├── autocfg v1.0.1
│   │   │       ├── cc v1.0.70
│   │   │       └── pkg-config v0.3.19
│   │   ├── openssl-probe v0.1.4
│   │   └── openssl-sys v0.9.66 (*)
│   └── unicase v2.6.0
│       [build-dependencies]
│       └── version_check v0.9.3
└── mio v0.7.13
    ├── libc v0.2.101
    └── log v0.4.14 (*)

POC (this code is flawed):

use std::error::Error;

use mio::net::{TcpListener, TcpStream};
use mio::{event, Events, Interest, Poll, Token};

use http_req::{request::RequestBuilder, response::StatusCode, tls, uri::Uri};
use std::convert::TryFrom;
use std::io::{Read, Write};
use std::net::{SocketAddr, ToSocketAddrs};

// Some tokens to allow us to identify which event is for which socket.
const SERVER: Token = Token(0);
const CLIENT: Token = Token(1);

fn main() -> Result<(), Box<dyn Error>> {
    let addr: Uri = Uri::try_from("http://example.org").unwrap();
    let mut writer = Vec::new();

    // Create a poll instance.
    let mut poll = Poll::new()?;
    // Create storage for events.
    let mut events = Events::with_capacity(128);

    // Setup the client socket.
    let mut client = TcpStream::connect(
        (addr.host().unwrap(), addr.corr_port())
            .to_socket_addrs()
            .unwrap()
            .next()
            .unwrap(),
    )?;
    /*
    let mut tls = tls::Config::default()
        .connect(addr.host().unwrap_or(""), &mut client)
        .unwrap();
    */
    // Register the socket.
    poll.registry()
        .register(&mut client, CLIENT, Interest::READABLE | Interest::WRITABLE)?;

    let mut response = None;

    // Start an event loop.
    'main: loop {
        // Poll Mio for events, blocking until we get an event.
        poll.poll(&mut events, None)?;

        // Process each event.
        for event in events.iter() {
            // We can use the token we previously provided to `register` to
            // determine for which socket the event is.
            match event.token() {
                CLIENT => {
                    if event.is_writable() {
                        eprintln!("##### write");
                        match RequestBuilder::new(&addr)
                            .header("Connection", "Close")
                            .send(&mut client, &mut writer)
                        {
                            Err(err) => {
                                eprintln!("{:?}", err);
                            }
                            Ok(res) => {
                                response.replace(res);
                                let _ = std::io::stdout().write_all(&writer);
                                break 'main;
                            }
                        }

                        // We can (likely) write to the socket without blocking.
                    }

                    if event.is_readable() {
                        // We can (likely) read from the socket without blocking.
                    }

                    // Since the server just shuts down the connection, let's
                    // just exit from our event loop.
                    //return Ok(());
                }
                // We don't expect any events with tokens other than those we provided.
                _ => unreachable!(),
            }
        }
    }

    if let Some(response) = response.as_ref() {
        assert_eq!(response.status_code(), StatusCode::new(200));
    }

    Ok(())
}

Then use std::futures::Future to make this async.

@jayjamesjay
Copy link
Owner

Yes, something like this.

@jayjamesjay
Copy link
Owner

At the current state of the project, many features have been implemented in a synchronous way, so I think that adding async functionality may require some major design changes. On the other hand, async environment should allow to handle timeouts in a more elegant way (based on #46)

@brandonros Thank you for raising the #68. Feel free to experiment and let me know if you find something interesting. Roadmap for a few upcoming releases primarily focuses on extending the basic functionality and implementation of minor improvements, so it will probably take some time before I get to this 😉

@brandonros
Copy link

appreciate what you do for the community, nice project. i was just having fun trying to see how far i could get off the beaten mainstream path of tokio/serde/hyper.

feel free to close if your async implementation will likely look much different. the timeout piece is interesting…

connect timeout, read timeout, write timeout

then decoupling an “async stream friendly” tls provider from an async runtime is another challenge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants