diff options
| author | Teddy Wing | 2020-06-27 17:15:10 +0200 | 
|---|---|---|
| committer | Teddy Wing | 2020-06-27 17:15:10 +0200 | 
| commit | a99b8b984180d7089006ef9f92259984be4f74ef (patch) | |
| tree | 11b75d991a6d2759c611ff36f70d440e0cc68cc1 | |
| parent | 23f23e7ee0540c1078db038c3b3cad93b312200a (diff) | |
| download | fastcgi-conduit-a99b8b984180d7089006ef9f92259984be4f74ef.tar.bz2 | |
Create a wrapper struct for `fastcgi::Request`
Trying out the Conduit API, as it seems like nice interface that I can
plug the FastCGI server into.
To do this, I need a server type, and some way to convert a
`fastcgi::Request` into a `conduit::Request`. Doing this with a new
local type that I can use to implement `conduit::RequestExt`.
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | src/lib.rs | 133 | 
2 files changed, 76 insertions, 61 deletions
| @@ -1,9 +1,11 @@  [package] -name = "fcgi" +name = "fastcgi-conduit"  version = "0.0.1"  edition = "2018"  [dependencies] +conduit = "0.9.0-alpha.2"  fastcgi = "1.0.0"  http = "0.2.1"  Inflector = "0.11.4" +snafu = "0.6.8" @@ -1,84 +1,97 @@ +extern crate conduit;  extern crate fastcgi;  extern crate http; +use std::io;  use std::io::{BufReader, Write}; -use http::{Request, Response}; -use http::request; +use conduit::Handler; +  use inflector::cases::traincase::to_train_case; +use snafu::{ResultExt, Snafu}; -pub fn run<F, T>(handler: F) -where F: Fn(Request<()>) -> Response<T> + Send + Sync + 'static -{ -    fastcgi::run(move |mut req| { -        let r: http::request::Builder = From::from(&req); -        handler(r.body(()).unwrap()); +#[derive(Debug, Snafu)] +pub enum RequestError { +    #[snafu(display("{}", source))] +    InvalidMethod { source: http::method::InvalidMethod }, +} -        let params = req.params() -            .map(|(k, v)| k + ": " + &v) -            .collect::<Vec<String>>() -            .join("\n"); +pub type RequestResult<T, E = RequestError> = std::result::Result<T, E>; -        write!( -            &mut req.stdout(), -            "Content-Type: text/plain\n\n{}", -            params -        ) -            .unwrap_or(()); -    }); -} -trait From<T>: Sized { -    fn from(_: T) -> Self; +struct FastCgiRequest<'a> { +    request: &'a fastcgi::Request, +    method: conduit::Method,  } -impl From<&fastcgi::Request> for http::request::Builder { -    fn from(request: &fastcgi::Request) -> Self { -        let method = request.param("REQUEST_METHOD") -            .unwrap_or("".to_owned()); - -        let uri = format!( -            "{}://{}{}", -            request.param("REQUEST_SCHEME").unwrap_or("".to_owned()), -            request.param("HTTP_HOST").unwrap_or("".to_owned()), -            request.param("REQUEST_URI").unwrap_or("".to_owned()), -        ); +impl<'a> FastCgiRequest<'a> { +    pub fn new(request: &'a fastcgi::Request) -> RequestResult<Self> { +        let method = Self::method(request) +            .context(InvalidMethod)?; -        let mut http_request = http::request::Builder::new() -            .method(&*method) -            .uri(&uri); +        let r = Self { +            request: request, +            method: method, +        }; -        let headers = headers_from_params(request.params()); -        for (k, v) in headers { -            http_request = http_request.header(&k, &v); -        } +        r.parse(); -        // TODO: Add request body +        Ok(r) +    } -        http_request +    fn parse(&self) { +        let headers = Self::headers_from_params(self.request.params()); +    } -        // let body = BufReader::new(request.stdin()); -        // -        // http_request.body(body) +    fn method( +        request: &'a fastcgi::Request +    ) -> Result<conduit::Method, http::method::InvalidMethod> { +        conduit::Method::from_bytes( +            request.param("REQUEST_METHOD") +                .unwrap_or_default() +                .as_bytes() +        ) +    } -        // HTTP_* params become headers +    fn headers_from_params(params: fastcgi::Params) -> Vec<(String, String)> { +        return params +            .filter(|(key, _)| key.starts_with("HTTP_")) +            .map(|(key, value)| { +                let key = key.get(5..).unwrap_or_default(); +                let key = &key.replace("_", "-"); +                let key = &to_train_case(&key); + +                (key.to_owned(), value) +            }) +            .collect()      }  } -fn headers_from_params(params: fastcgi::Params) -> Vec<(String, String)> { -    return params -        .filter(|(key, _)| key.starts_with("HTTP_")) -        .map(|(key, value)| { -            let mut key = key.get(5..).unwrap_or("").to_owned(); -            key = key.replace("_", "-"); -            key = to_train_case(&key); - -            // Change _ to - -            // Uppercase each word - -            (key, value) -        }) -        .collect() +// impl<'a> conduit::RequestExt for FastCgiRequest { +//    fn http_version(&self) -> conduit::Version { todo!() } +//    fn method(&self) -> &conduit::Method { +//        self.method +//    } +//    fn scheme(&self) -> conduit::Scheme { todo!() } +//    fn host(&'a self) -> conduit::Host<'a> { todo!() } +//    fn virtual_root(&'a self) -> std::option::Option<&'a str> { todo!() } +//    fn path(&'a self) -> &'a str { todo!() } +//    fn query_string(&'a self) -> std::option::Option<&'a str> { todo!() } +//    fn remote_addr(&self) -> std::net::SocketAddr { todo!() } +//    fn content_length(&self) -> std::option::Option<u64> { todo!() } +//    fn headers(&self) -> &conduit::HeaderMap { todo!() } +//    fn body(&'a mut self) -> &'a mut (dyn std::io::Read + 'a) { todo!() } +//    fn extensions(&'a self) -> &'a conduit::TypeMap { todo!() } +//    fn mut_extensions(&'a mut self) -> &'a mut conduit::TypeMap { todo!() } +// } + + +struct Server; + +impl Server { +    pub fn start<H: Handler + 'static + Sync>(handler: H) -> io::Result<Server> { +        Ok(Server{}) +    }  } | 
