aboutsummaryrefslogtreecommitdiffstats
path: root/components/net/fetch/response.rs
blob: 584e6e7fe409b4953f06544af88108a07fb10837 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use hyper::header::Headers;
use hyper::status::StatusCode;
use net_traits::{Response, ResponseBody, ResponseType};
use std::ascii::AsciiExt;
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::mpsc::Receiver;
use url::Url;

pub trait ResponseMethods {
    fn new() -> Response;
    fn to_filtered(self, ResponseType) -> Response;
}

impl ResponseMethods for Response {
    fn new() -> Response {
        Response {
            response_type: ResponseType::Default,
            termination_reason: None,
            url: None,
            url_list: Vec::new(),
            status: Some(StatusCode::Ok),
            headers: Headers::new(),
            body: ResponseBody::Empty,
            internal_response: None
        }
    }

    /// Convert to a filtered response, of type `filter_type`.
    /// Do not use with type Error or Default
    fn to_filtered(self, filter_type: ResponseType) -> Response {
        assert!(filter_type != ResponseType::Error);
        assert!(filter_type != ResponseType::Default);
        if self.is_network_error() {
            return self;
        }
        let old_headers = self.headers.clone();
        let mut response = self.clone();
        response.internal_response = Some(Rc::new(RefCell::new(self)));
        match filter_type {
            ResponseType::Default | ResponseType::Error => unreachable!(),
            ResponseType::Basic => {
                let headers = old_headers.iter().filter(|header| {
                    match &*header.name().to_ascii_lowercase() {
                        "set-cookie" | "set-cookie2" => false,
                        _ => true
                    }
                }).collect();
                response.headers = headers;
                response.response_type = filter_type;
            },
            ResponseType::CORS => {
                let headers = old_headers.iter().filter(|header| {
                    match &*header.name().to_ascii_lowercase() {
                        "cache-control" | "content-language" |
                        "content-type" | "expires" | "last-modified" | "Pragma" => false,
                        // XXXManishearth handle Access-Control-Expose-Headers
                        _ => true
                    }
                }).collect();
                response.headers = headers;
                response.response_type = filter_type;
            },
            ResponseType::Opaque |
            ResponseType::OpaqueRedirect => {
                response.headers = Headers::new();
                response.status = None;
                response.body = ResponseBody::Empty;
            }
        }
        response
    }
}