I'm trying to implement simple tcp/http server on Rust. Main feature is possibility to download files from server via url. As exapmple: localhost:port/root_storage/someFile.fileExt
Main function:
fn main() {
let tcp_listener = TcpListener::bind("127.0.0.1:7000").unwrap();
println!("Server starded!");
for stream in tcp_listener.incoming()
{
let stream = stream.unwrap();
handle_connection(stream);
}
}
I'm receiving request with tcpStream, parsing to get incoming url etc. Then I'm tryiting to send some file back to browser and download him on client side.
if http_request[0].contains("storage/10mb.pdf") {
status_line = "HTTP/1.1 200 OK";
let buf_content = fs::read("storage/10mb.pdf").unwrap();
let contents = unsafe {String::from_utf8_unchecked(buf_content)};
length = contents.len();
response = format!("{status_line}\r\n
Content-Disposition: attachment; filename=\"10mb.pdf\"\r\n
Content-Type: application/pdf\r\n
Content-Length: {length}\r\n\r\n
{contents}");
}
It works, but only with pdf format.
This code won't occure file downloading, just showing content of file in browser:
else if http_request[0].contains("storage/10mb.txt") {
status_line = "HTTP/1.1 200 OK";
let buf_content = fs::read("storage/10mb.txt").unwrap();
let contents = unsafe {String::from_utf8_unchecked(buf_content)};
length = contents.len();
response = format!("{status_line}\r\n
Content-Disposition: attachment; filename=\"10mb.txt\"\r\n
Content-Type: application/octet-stream\r\n
Content-Length: {length}\r\n\r\n
{contents}");
stream.write_all(response.as_bytes()).unwrap();
stream.flush().unwrap();
My assumption it's about in contents encoding. I don't know why - Content-Disposition and other headers doesn't work at all. If I remove Content-Disposition from pdf case. It will download file anyway.
What's wrong with my implementation? May be I encode contents in wrong way or something else?
UPD: Have this, but also no effect
if http_request[0].contains("storage/10mb.pdf") {
status_line = "HTTP/1.1 200 OK";
let buf_content = fs::read("storage/10mb.pdf").unwrap();
length = buf_content.len();
response = format!("{status_line}\r\n
Content-Disposition: attachment; filename=\"10mb.pdf\"\r\n
Content-Type: application/pdf\r\n
Content-Length: {length}\r\n\r\n");
stream.write_all(response.as_bytes()).unwrap();
stream.write_all(&buf_content).unwrap();
stream.flush().unwrap();
}
else if http_request[0].contains("storage/10mb.txt") {
status_line = "HTTP/1.1 200 OK";
let buf_content = fs::read("storage/10mb.txt").unwrap();
length = buf_content.len();
response = format!("{status_line}\r\n
Content-Disposition: attachment; filename=\"10mb.txt\"\r\n
Content-Type: text/plain\r\n
Content-Length: {length}\r\n\r\n");
stream.write_all(response.as_bytes()).unwrap();
stream.write_all(&buf_content).unwrap();
stream.flush().unwrap();
}
Content-Type: text/plaincould help... As far as I understand, this could be related to some settings in the browser.Connection: keep-alive? If not and you unconditionally close the connection after the http reply, then you should addConnection: closein the reply header.