From de08947fe70f5890c072b52f6329fae78fb6e59b Mon Sep 17 00:00:00 2001 From: Hubert Date: Wed, 7 Jul 2021 21:32:21 +0200 Subject: [PATCH] save --- Cargo.toml | 1 + src/main.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 73b9b0e..095a461 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,4 @@ askama = "0.10.5" askama_actix = "0.11.1" env_logger = "0.8.4" serde = "1.0.126" +futures = "0.3.15" diff --git a/src/main.rs b/src/main.rs index f212adb..29109a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ mod git; mod ite; use actix_files::Files; -use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder, Error, HttpRequest}; +use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder, Error, HttpRequest, HttpMessage}; use askama_actix::Template; use actix_session::{Session, CookieSession}; use actix_web_httpauth::headers::authorization::{Authorization, Basic}; @@ -19,8 +19,12 @@ use std::ops::Add; use std::path::{PathBuf, Path}; use serde::Deserialize; use std::process::{Command, Stdio}; -use actix_web::http::header; +use actix_web::http::{header, StatusCode}; use std::io; +use std::collections::HashMap; +use std::io::{Read, BufRead, Write}; +use futures::{StreamExt, TryStreamExt, future}; +use actix_web::web::Buf; #[derive(Template)] #[template(path = "hello.html")] @@ -119,7 +123,7 @@ async fn git_main(web::Path((owner, reponame)): web::Path<(String, String)>, web GitMainTemplate { repo, browse : browse, root : path, user_opt : Some(user)} } //#[get("/git/{owner}/{repo}.git/{path:.*}")] -async fn git_proto(web::Path((owner, reponame)): web::Path<(String, String)>, req: HttpRequest) -> impl Responder{ +async fn git_proto(payload : web::Payload, web::Path((owner, reponame)): web::Path<(String, String)>, mut req: HttpRequest) -> impl Responder{ let mut cmd = Command::new("git"); cmd.arg("http-backend"); @@ -136,14 +140,67 @@ async fn git_proto(web::Path((owner, reponame)): web::Path<(String, String)>, re ); cmd.env("REMOTE_USER", ""); //cmd.env("REMOTE_ADDR", req.remote_addr().to_string()); - cmd.env("QUERY_STRING", req.query_string().unwrap_or_default()); - //cmd.env("CONTENT_TYPE", header(req, header::CONTENT_TYPE)); + cmd.env("QUERY_STRING", req.query_string()); + cmd.env("CONTENT_TYPE", header(&req, header::CONTENT_TYPE)); cmd.stderr(Stdio::inherit()) .stdout(Stdio::piped()) .stdin(Stdio::piped()); let mut p = cmd.spawn()?; - io::copy(&mut req.body(), &mut p.stdin.take().unwrap())?; - "not yet implemented" + //p.stdin.take().unwrap().write() + payload.try_for_each(|bytes| { + p.stdin.take().unwrap().write(bytes.bytes()); + future::ready(Ok(())) + }); + //io::copy(&mut req.take_payload(), &mut p.stdin.take().unwrap())?; + // Parse the headers coming out, and the pass through the rest of the + // process back down the stack. + // + // Note that we have to be careful to not drop the process which will wait + // for the process to exit (and we haven't read stdout) + let mut rdr = io::BufReader::new(p.stdout.take().unwrap()); + + let mut headers = HashMap::new(); + for line in rdr.by_ref().lines() { + let line = line?; + if line == "" || line == "\r" { + break; + } + + let mut parts = line.splitn(2, ':'); + let key = parts.next().unwrap(); + let value = parts.next().unwrap(); + let value = &value[1..]; + headers + .entry(key.to_string()) + .or_insert_with(Vec::new) + .push(value.to_string()); + } + + let status_code : u16 = { + let line = headers.remove("Status").unwrap_or_default(); + let line = line.into_iter().next().unwrap_or_default(); + let mut parts = line.splitn(1, ' '); + parts.next().unwrap_or("").parse().unwrap_or(200) + }; + + let mut builder = HttpResponse::build(StatusCode::from_u16(status_code)?); + for (name, vec) in headers.iter() { + for value in vec { + builder = builder.header(name, value); + } + } + + let mut body = Vec::new(); + rdr.read_to_end(&mut body)?; + return Ok(builder.body(body).unwrap()); + +} + +fn header(req: &HttpRequest, name: header::HeaderName) -> &str { + req.headers() + .get(name) + .map(|value| value.to_str().unwrap_or_default()) + .unwrap_or_default() } #[post("/echo")]