I try to make a HTTP request from within a Rust application, but get other results as in the command line.
This works fine on the command line, giving a HTTP2 response:
$ curl -v --tls-max 1.2 'https://www.example.com/settings'
[...]
> GET /settings HTTP/2
> Host: www.example.com
> user-agent: curl/7.88.1
> accept: */*
>
< HTTP/2 200
[...]
This as well, also CLI, this time a HTTP1 response:
$ wget -S 'https://www.example.com/settings'
[...]
HTTP/1.1 200 OK
[...]
Mimicking the same with crate tinyget
fails:
use tinyget;
let request = tinyget::Request::new("https://www.example.com/settings")
.with_header("user-agent", "curl/7.88.1")
.with_header("accept", "*/*");
let response = request.send().unwrap();
println!("Response code: {}", response.status_code);
// Prints: Response code: 403 [...]
Next try using quite low level crate native-tls
:
use std::net::TcpStream;
use native_tls::TlsConnector;
use native_tls::TlsStream;
let tcp_stream = TcpStream::connect_timeout(&address, Duration::from_secs(15)).unwrap();
let connector = TlsConnector::new().unwrap();
let mut stream = connector.connect("www.example.com", tcp_stream).unwrap();
let get_message = format!("\
GET /settings HTTP/2\r\n\
Host: www.example.com\r\n\
User-Agent: curl/7.88.1\r\n\
Accept: */*\r\n\
\r\n\
");
stream.write_all(get_message.as_bytes()).unwrap();
let mut response = Vec::new();
stream.read_to_end(&mut response).unwrap();
let response = String::from_utf8_lossy(&response).to_string();
println!("response {}", response);
// Prints: response HTTP/1.1 505 HTTP Version Not Supported [...]
// (changing "HTTP/2" to "HTTP/1.0" leads to the 403 response like with `tinyget`)
(example.com is a replacement, can't reveal the actual URL)
Well, all happens on the same PC (Debian), all TCP stuff works fine, all TLS stuff works fine, yet I'm out of ideas on what might cause that server to behave so differently across these four attempts. Especially with the first and last version, it should see the exactly same request.
Any ideas on how to get CLI behavior inside Rust?