2017-09-14 100 views
-2

我想使用超0.11.2阅读POST JSON。在“已达到”打印后,我没有看到任何事情发生。如何阅读hyper中的请求体?

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

    match (req.method(), req.path()) { 
     (&Method::Post, "/assests") => { 
      println!("Reached ... "); //POST: 200 OK 
      //let (method, uri, _version, head 
      let mut res: Response = Response::new(); 
      if let Some(len) = req.headers().get::<ContentLength>() { 
       res.headers_mut().set(len.clone()); 
      } 

      println!("Reached xxx {:?}", req.body()); 
      res.with_body("req.body()"); 
     } 
     _ => { 
      response.set_status(StatusCode::NotFound); 
     } 
    }; 

    futures::future::ok(response) 
} 

输出:

Reached ... 
Reached xxx Body(Body { [stream of values] }) 
+1

请提供[MCVE]。事实上,我们必须猜测“Self :: Future”是什么,以及其他许多应用程序。 – Shepmaster

+0

此外,这将是很好的解释你不明白从[超文本流的例子](https://hyper.rs/guides/server/echo/),它看起来应该是一个从容易的地方开始。 – Shepmaster

回答

1

您创建了一个新的名为Responseresponse,然后创建了第二个Response称为res。然后,您修改res,然后将其丢弃,从您的函数返回response。如果您返回修改的内容,则您的服务器将返回字符串"req.body()",就像您指定的一样。

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

    match (req.method(), req.path()) { 
     (&Method::Post, "/assets") => { 
      if let Some(len) = req.headers().get::<ContentLength>() { 
       response.headers_mut().set(len.clone()); 
      } 

      response = response.with_body("req.body()"); 
     } 
     _ => { 
      response.set_status(StatusCode::NotFound); 
     } 
    }; 

    futures::future::ok(response) 
} 

我会设置内容长度为无效值 - 您返回的字符串不匹配上传数据的长度。

+0

如何在Method中提取正文或其内容:POST?我试过https://github.com/hyperium/hyper/blob/master/examples/server.rs但是如何看到req.body中的内容?块大块? – BalaB

0
Below code works, able to parse JSON on POST 


#[deny(warnings)] 

use hyper::{Post, StatusCode}; 
use hyper::header::ContentLength; 
use hyper::server::{Http, Service, Request, Response}; 
use futures::{future, Future, Stream}; 
use futures; 
use hyper; 
use serde_json; 
use std::io; 
use std::error::Error; 


pub struct Persistence; 

const SERVICE: &'static str = "Persistence Service"; 
const SUCCESS: &'static str = r#"{"status": "success"}"#; 

impl Service for Persistence { 
     type Request = Request; 
    type Response = Response; 
    type Error = hyper::Error; 
    type Future = futures::BoxFuture<Response, hyper::Error>; 

    fn call(&self, req: Request) -> Self::Future { 
     let (method, uri, _version, headers, body) = req.deconstruct(); 
     match (method, uri.path()) { 
      (Post, "/assests") => { 
       let mut res = Response::new(); 
       let vec; 
       if let Some(len) = headers.get::<ContentLength>() { 
        vec = Vec::with_capacity(**len as usize); 
        res.headers_mut().set(len.clone()); 
       } else { 
        vec = vec![]; 
       } 
       body.fold(vec, |mut acc, chunk| { 
        acc.extend_from_slice(chunk.as_ref()); 
        Ok::<_, hyper::Error>(acc) 
       }).and_then(move |value| { 
        use serde_json; 

         let v: serde_json::Value = serde_json::from_slice(&value).map_err(|e| { 
          io::Error::new(
           io::ErrorKind::Other, 
           e 
          ) 
         })?; 
        println!("value..... {:?}", &v); 
        Ok(res.with_body(SUCCESS)) 

       }).boxed() 
      }, 
      _ => future::ok(Response::new().with_status(StatusCode::NotFound)).boxed() 
     } 
    } 

} 

谢谢了@Shepmaster :)髋关节hurray!根据https://hyper.rs/guides/server/handle_post/#handling-json-and-other-data-types

和这里

+1

如果Shepmaster真的帮助了你,你会考虑给他的答案赋予一些价值吗?我没有在那里看到一个喜欢。您可能还想要解释必要的更改,以便未来的访问者不必查看所有代码即可了解所做的操作。 –

+0

https://stackoverflow.com/questions/43419974/how-do-iread-the-entire-body-of-a-tokio-based-hyper-request – Gedweb

0

是代码:

extern crate futures; 
extern crate hyper; 
extern crate serde_json; 

use futures::Future; 
use futures::{Stream}; 

use hyper::{Get, Post, StatusCode}; 
use hyper::header::{ContentLength}; 
use hyper::server::{Http, Service, Request, Response}; 

static INDEX: &'static [u8] = b"Try POST /echo"; 

struct Echo; 

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

    fn call(&self, req: Request) -> Self::Future { 
     match (req.method(), req.path()) { 
      (&Get, "/") | (&Get, "/echo") => { 
       Box::new(futures::future::ok(
        Response::new() 
         .with_header(ContentLength(INDEX.len() as u64)) 
         .with_body(INDEX))) 
      }, 
      (&Post, "/echo") => { 
     Box::new(req.body().concat2().map(|b| { 
        let bad_request: &[u8] = b"Missing field"; 
        let json: serde_json::Value = 
         if let Ok(j) = serde_json::from_slice(b.as_ref()) { 
         j 
         } else { 
          return Response::new() 
           .with_status(StatusCode::BadRequest) 
           .with_header(ContentLength(bad_request.len() as u64)) 
           .with_body(bad_request); 
        }; 

        // use json as you like 

        let body = serde_json::to_string(&json).unwrap(); 
        Response::new() 
         .with_header(ContentLength(body.len() as u64)) 
         .with_body(body) 
       })) 
      }, 
      _ => { 
       Box::new(futures::future::ok(
        Response::new().with_status(StatusCode::NotFound))) 
      } 
     } 
    } 
} 


fn main() { 
    let addr = "127.0.0.1:1337".parse().unwrap(); 

    let server = Http::new().bind(&addr, || Ok(Echo)).unwrap(); 
    println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap()); 
    server.run().unwrap(); 
}