2017-02-14 9 views
1

静的なHTTPファイルサーバーを作成しようとしましたが、.jpgファイルをTcpStreamに送信しようとすると固まってしまいました。TcpStream経由で.jpgをHTTPとして送信するにはどうすればいいですか?

私はバイナリとしてファイルをread場合でも、ブラウザは画像復号することができていないようです。私は、「HTTPサーバの標準ガイドブック」のいくつかの種類があることを聞いた

extern crate chunked_transfer; 
use std::net::{TcpListener, TcpStream}; 
use std::io::{Read, Write}; 
use std::thread; 
use std::fs::File; 
use chunked_transfer::Encoder; 

fn main() { 
    let listener = TcpListener::bind("127.0.0.1:9527").unwrap(); 
    println!("Listening for connections on port {}", 9527); 
    for stream in listener.incoming() { 
     match stream { 
      Ok(stream) => { 
       thread::spawn(|| handle_client(stream)); 
      } 
      Err(e) => println!("Unable to connect: {}", e), 
     } 
    } 
} 

fn get_path(mut stream: &TcpStream) -> String { 
    let mut buf = [0u8; 4096]; 
    match stream.read(&mut buf) { 
     Ok(_) => { 
      let req_str = String::from_utf8_lossy(&buf); 
      let path: Vec<&str> = req_str.lines().next().unwrap().split(" ").collect(); 
      println!("GET {}", path[1]); 
      // println!("{}", req_str); 
      path[1].to_string() 
     } 
     Err(e) => { 
      println!("Unable to read stream: {}", e); 
      "/".to_string() 
     } 
    } 
} 

fn response(path: &str, mut stream: TcpStream) { 
    let file_path: &str = &("/home/xinbg/Downloads/wallpaper".to_string() + path); 
    println!("{}", file_path); 
    let mut buf = vec![0u8]; 
    let file = File::open(file_path); 
    file.unwrap().read_to_end(&mut buf); 

    let mut encoded: Vec<u8> = vec![]; 
    { 
     let mut encoder = Encoder::with_chunks_size(&mut encoded, 8); 
     encoder.write_all(&buf); 
    } 

    let headers = 
     ["HTTP/1.1 200 OK", "Content-type: image/jpeg", "Transfer-Encoding: chunked", "\r\n"]; 
    let mut response: Vec<u8> = headers.join("\r\n") 
     .to_string() 
     .into_bytes(); 
    response.extend(encoded); 

    match stream.write(&response) { 
     Ok(_) => println!("Response sent"), 
     Err(e) => println!("Failed sending response: {}", e), 
    } 
} 

fn handle_client(stream: TcpStream) { 
    response(&get_path(&stream), stream); 
} 

をもの、それを見つけるための任意のアイデア?

答えて

5

特にコンパイラの警告は、使用していない結果に関するものを修正してください。戻り、錆プログラミング言語の章をerror handlingに再読んでください。

しかし、これはあなたの問題ではありません。 let mut buf = vec![0u8];はあなたが何を考えているのか分かりませんが、あなたはそれを望んでいません。これは、その中にちょうど1つの値、8ビットのゼロを持つベクトルを割り当てます。その後、JPEGの前にその不正なバイトを送信すると、無効なJPEGになります。それを削除すると、あなたのプログラムが動作することができます:

fn response(path: &str, mut stream: TcpStream) { 
    let file_path = format!("/tmp/images/{}", path); 

    let mut buf = Vec::new(); 
    let mut file = File::open(&file_path).unwrap(); 
    file.read_to_end(&mut buf).unwrap(); 

    let mut encoded = Vec::new(); 
    { 
     let mut encoder = Encoder::with_chunks_size(&mut encoded, 8); 
     encoder.write_all(&buf).unwrap(); 
    } 

    let headers = [ 
     "HTTP/1.1 200 OK", 
     "Content-type: image/jpeg", 
     "Transfer-Encoding: chunked", 
     "\r\n" 
    ]; 
    let mut response = headers.join("\r\n") 
     .to_string() 
     .into_bytes(); 
    response.extend(encoded); 

    match stream.write(&response) { 
     Ok(_) => println!("Response sent"), 
     Err(e) => println!("Failed sending response: {}", e), 
    } 
} 

しかし、あなたのプログラムがpath traversalとして知ら巨大なセキュリティホールを持っています。 でなければ、は貴重な情報がある場所であればどこにでも公開できます。

+0

貴重な洞察力をお寄せいただき、ありがとうございます。私はこれらの章を再読します。 '[0u8]'は馬鹿だった、私はfile.read_to_endがベクトルを消して空のものとして使うと思った。 – FrontMage

関連する問題