3

I'm trying to create a simple web server in Rust using Hyper, and I'm getting stuck trying to convert the request.body() Stream to a String.

I'm running rustc 1.21.0-nightly

So far I have this:

extern crate futures;
extern crate hyper;
extern crate unicase;

use hyper::server::{Http, Request, Response, Service};
use hyper::Body;
use hyper::Chunk;
use futures::Stream;
use futures::future::*;
use futures::stream::Map;
use std::ascii::AsciiExt;
use unicase::Ascii;

struct WebService;

impl Service for WebService {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = Box<futures::Future<Item = Self::Response, Error = Self::Error>>;

    fn call(&self, req: Request) -> Self::Future {
        let mut response = Response::new();

        let body = req.body()
            .fold(Vec::new(), |mut acc, chunk| {
                acc.extend_from_slice(&*chunk);
                futures::future::ok::<_, Self::Error>(acc)
            })
            .and_then(|v| String::from_utf8(v));
        println!("Body: \n{}", body.wait().unwrap());

        let future = futures::future::ok(response);
        Box::new(future)
    }
}

fn main() {
    let addr = "0.0.0.0:3000".parse().unwrap();
    let server = Http::new().bind(&addr, || Ok(WebService)).unwrap();
    server.run().unwrap();
}

This results in the following error messages:

error[E0271]: type mismatch resolving `<std::result::Result<std::string::String, std::string::FromUtf8Error> as futures::IntoFuture>::Error == hyper::Error`
  --> src/main.rs:30:14
   |
30 |             .and_then(|v| String::from_utf8(v));
   |              ^^^^^^^^ expected struct `std::string::FromUtf8Error`, found enum `hyper::Error`
   |
   = note: expected type `std::string::FromUtf8Error`
              found type `hyper::Error`

error[E0599]: no method named `wait` found for type `futures::AndThen<futures::stream::Fold<hyper::Body, [closure@src/main.rs:26:31: 29:14], futures::FutureResult<std::vec::Vec<u8>, hyper::Error>, std::vec::Vec<u8>>, std::result::Result<std::string::String, std::string::FromUtf8Error>, [closure@src/main.rs:30:23: 30:47]>` in the current scope
  --> src/main.rs:31:37
   |
31 |         println!("Body: \n{}", body.wait().unwrap());
   |                                     ^^^^
   |
   = note: the method `wait` exists but the following trait bounds were not satisfied:
           `futures::AndThen<futures::stream::Fold<hyper::Body, [closure@src/main.rs:26:31: 29:14], futures::FutureResult<std::vec::Vec<u8>, hyper::Error>, std::vec::Vec<u8>>, std::result::Result<std::string::String, std::string::FromUtf8Error>, [closure@src/main.rs:30:23: 30:47]> : futures::Stream`
           `futures::AndThen<futures::stream::Fold<hyper::Body, [closure@src/main.rs:26:31: 29:14], futures::FutureResult<std::vec::Vec<u8>, hyper::Error>, std::vec::Vec<u8>>, std::result::Result<std::string::String, std::string::FromUtf8Error>, [closure@src/main.rs:30:23: 30:47]> : futures::Future`

I think that I'm returning a future from the the fold method, the result of which is being piped into the and_then method, which I'm hoping will assign a String version of the request.body to the body variable.

I'm pretty new to Rust, but to me the error seems to suggest that the and_then connector is only receiving the Error value of the future, and not the Ok value...

Is this a correct interpretation? How would I resolve this error?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
chrxr
  • 1,374
  • 1
  • 10
  • 21
  • Thanks @Shepmaster. I have updated with as minimal a version of the whole script as possible. I have also included the whole error message block. My understanding of the error is limited, so I'm not sure how best to create a more minimal representation. – chrxr Sep 04 '17 at 12:49
  • You've said that your error type is one type (`type Error = hyper::Error`) but then tried to return a different error type (`std::string::FromUtf8Error`). Unify them. – Shepmaster Sep 04 '17 at 14:42
  • Thanks @Shepmaster I've got around the error, returning `Ok::<_, Self::Error>(stringify)` from the `and_then` connector. However, I'm now just returning an empty string. I've added a couple of print statements in to see if anything is there. But the print statement in the `.fold` method doesn't seem to trigger. Here's the current script https://gist.github.com/chrxr/045e54d5135ea9b427912ea4783b291b. Do you think this warrants a new, separate question? – chrxr Sep 04 '17 at 16:05
  • FYI I know the `request.Body()` has contents. I'm sending a string from an HTML form, and I have managed to return that string to the client using the basic Hyper Echo server tutorial. – chrxr Sep 04 '17 at 16:06

0 Answers0