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{}) + } } |