Невозможно установить заголовки ответа Iron Framework

Я хочу установить заголовки Iron Response со следующим кодом:

extern crate iron;  // 0.3.0
extern crate hyper; // 0.8.1

use iron::prelude::*;
use iron::status;

use hyper::header::{Headers, ContentType};
use hyper::mime::{Mime, TopLevel, SubLevel};

use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

fn main() {
    fn hello_world(_: &mut Request) -> IronResult<Response> {
        let mut headers = Headers::new();
        let string = getFileAsString("./public/index.html");

        headers.set(
            ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]))
        );

        Ok(Response::with((status::Ok, string, headers)))
    }

    Iron::new(hello_world).http("localhost:3000").unwrap();
    println!("On 3000");
}

fn getFileAsString(fileStr: &str) -> String {
    let path = Path::new(fileStr);
    let display = path.display();
    let mut fileContents = String::new();

    let mut file = match File::open(&path) {
        Err(why) => panic!("couldn't open {}: {}", display, Error::description(&why)),
        Ok(file) => file,
    };

    match file.read_to_string(&mut fileContents) {
        Err(why) => panic!("couldn't read {}: {}", display, Error::description(&why)),
        Ok(_) => fileContents
    }    
}

Однако я получаю сообщение об ошибке:

error[E0277]: the trait bound `iron::Headers: iron::modifier::Modifier<iron::Response>` is not satisfied
  --> src/main.rs:24:12
   |
24 |         Ok(Response::with((status::Ok, string, headers)))
   |            ^^^^^^^^^^^^^^ the trait `iron::modifier::Modifier<iron::Response>` is not implemented for `iron::Headers`
   |
   = note: required because of the requirements on the impl of `iron::modifier::Modifier<iron::Response>` for `(hyper::status::StatusCode, std::string::String, iron::Headers)`
   = note: required by `iron::Response::with`

Почему я не могу передать заголовки в этот кортеж для изменения компоновщиком Request?


person Jacob Clark    schedule 23.05.2016    source источник


Ответы (1)


Вы можете изменить заголовки объекта Response:

fn hello_world(_: &mut Request) -> IronResult<Response> {
    let string = get_file_as_string("./public/index.html");
    let mut resp = Response::with((status::Ok, string));
    resp.headers.set(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])));
    Ok(resp)
}

Чтобы выяснить исходную ошибку, давайте проверим сообщение об ошибке:

error[E0277]: the trait bound `iron::Headers: iron::modifier::Modifier<iron::Response>` is not satisfied
  --> src/main.rs:24:12
   |
24 |         Ok(Response::with((status::Ok, string, headers)))
   |            ^^^^^^^^^^^^^^ the trait `iron::modifier::Modifier<iron::Response>` is not implemented for `iron::Headers`
   |
   = note: required because of the requirements on the impl of `iron::modifier::Modifier<iron::Response>` for `(hyper::status::StatusCode, std::string::String, iron::Headers)`
   = note: required by `iron::Response::with`

Первая строка говорит нам о непосредственной проблеме: iron::Headers не реализует трейт iron::modifier::Modifier<iron::Response>. Если мы проверим документацию для Headers, мы увидим под раздел Реализации признаков, что он действительно не реализует Modifier.

Затем мы можем взглянуть на проблему с другой стороны: что реализует Modifier? Документация для Modifier, созданная совместно с Iron, отвечает на этот вопрос. Мы можем видеть одно:

impl<H> Modifier<Response> for Header<H>
where
    H: Header + HeaderFormat,

Это приводит к альтернативной возможности:

use iron::modifiers::Header;

fn hello_world(_: &mut Request) -> IronResult<Response> {
    let string = get_file_as_string("./public/index.html");
    let content_type = Header(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])));
    Ok(Response::with((status::Ok, string, content_type)))
}

И если мы посмотрим на реализация Modifier для Header:

fn modify(self, res: &mut Response) {
    res.headers.set(self.0);
}

Он просто устанавливает заголовки, как мы делали выше.


К вашему сведению, стиль Rust snake_case для переменных и методов, а Error::description(&why) обычно записывается как why.description().

person Shepmaster    schedule 23.05.2016
comment
Спасибо, не могли бы вы объяснить, почему я не могу передать заголовки в кортеж, как я понимаю, Response::with принимает кортеж модификаторов для объекта ответа? - person Jacob Clark; 24.05.2016
comment
@JacobClark ах да, я забыл важную часть ответа! - person Shepmaster; 24.05.2016
comment
отлично, спасибо! Возможно, сейчас это выходит за рамки, но как применяется кортеж? Обычно я ожидаю увидеть форму, проходящую через каждый модификатор, но в исходном коде модификатора Iron я этого не вижу, можете ли вы указать мне, где/как применяется каждый модификатор в кортеже? - person Jacob Clark; 24.05.2016