Reputation: 57
I'm trying to set headers on a Hyper Response
at runtime. In the real code, the headers come from a file so I don't know what they are at compile-time. Unfortunately, I've dug through documentation and all the examples I could find but haven't seen somebody doing this. Here's the code:
extern crate hyper;
use std::collections::HashMap;
use std::io::{Read,Write};
use hyper::server::{Handler,Server,Response,Request};
use hyper::header::*;
fn main() {
let headers = HashMap::new();
headers.insert("X-Test-Header".to_string(), "test_value".to_string());
let responder = Responder::new(headers);
Server::http("127.0.0.1:1340")
.unwrap()
.handle(responder)
.unwrap();
}
struct Responder {
headers: HashMap<String, String>
}
impl Responder {
pub fn new(headers: HashMap<String,String>) -> Self {
Responder {
headers: headers.clone()
}
}
fn respond_success(&self, mut res: Response, content: &[u8]) {
res.headers_mut()
.set(ContentLength(content.len() as u64));
for (key, val) in self.headers.iter() {
res.headers_mut()
.set_raw(key.as_str(), vec![val.into_bytes()])
}
let mut res_body = res.start().unwrap();
res_body.write_all(content).unwrap();
}
}
impl Handler for Responder {
fn handle(&self, req: Request, res: Response) {
let content = b"Hello World!";
self.respond_success(res, content);
}
}
The error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src\main.rs:31:40
|
31 | for (key, val) in self.headers.iter() {
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 28:65...
--> src\main.rs:28:66
|
28 | fn respond_success(&self, mut res: Response, content: &[u8]) {
| ^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:31:27
|
31 | for (key, val) in self.headers.iter() {
| ^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that types are compatible (expected std::convert::From<&str>, found std::convert::From<&str>)
--> src\main.rs:33:18
|
33 | .set_raw(key.as_str(), vec![val.into_bytes()])
| ^^^^^^^
It looks like set_raw
needs something static but I'm not sure what my best option for refactoring this is. Does responder
have to be static? That seems wrong.
Upvotes: 0
Views: 1119
Reputation: 430673
Review the signature for Headers::set_raw
:
fn set_raw<K>(&mut self, name: K, value: Vec<Vec<u8>>)
where
K: Into<Cow<'static, str>>
This says that name
can be any type that can be converted into a Cow<'static, str>
. That means that it can be either a &'static str
or a String
.
Next, review what types you are trying to pass:
.set_raw(key.as_str(), vec![val.into_bytes()])
String::as_str
returns a string slice that lives as long as the String
it's called on, which is not that 'static
lifetime.
Instead, you need to get an owned string.
You are calling String::into_bytes
on a &String
, but, as described in Cannot move out of borrowed content, you cannot as it takes the receiver by value.
Instead, you need to get an owned copy of the bytes.
Together, it looks like:
for (key, val) in self.headers.iter() {
res.headers_mut()
.set_raw(key.clone(), vec![val.clone().into_bytes()])
}
Upvotes: 2