1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2005-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(http_response). 22 23-include("http_internal.hrl"). 24 25-export([headers/2, header_list/1]). 26 27%%------------------------------------------------------------------------- 28%% headers(HeaderList, #http_response_h{}) -> #http_response_h{} 29%% HeaderList - ["HeaderField:Value"] 30%% HeaderField - string() 31%% Value - string() 32%% 33%% Description: Creates a http_response_h-record used internally to 34%% handle http-headers, assumes reversed list of headers 35%% to unfold multiline headers with obs-folds 36%%------------------------------------------------------------------------- 37headers(RevLines, Headers) -> 38 fill_headers(RevLines, [], Headers). 39 40%%------------------------------------------------------------------------- 41%% headers(#http_response_h{}) -> HeaderList 42%% HeaderList - [{"HeaderField", Value"}] 43%% HeaderField - string() 44%% Value - string() 45%% 46%% Description: Creates a list of key value tuples from the #http_response_h 47%% record, to be returned to the application programmer. We 48%% do not wish to make the application programmer dependent on 49%% our records. 50%%------------------------------------------------------------------------- 51header_list(Headers) -> 52 HeaderFields = record_info(fields, http_response_h) -- [other], 53 HeaderList = lists:foldl(fun(Key, Acc) -> 54 case key_value_tuple(Key, Headers) of 55 undefined -> 56 Acc; 57 Tuple -> 58 [Tuple | Acc] 59 end 60 end, 61 [], HeaderFields), 62 lists:reverse(HeaderList) ++ Headers#http_response_h.other. 63%%%======================================================================== 64%%% Internal functions 65%%%======================================================================== 66fill_headers([], _, Headers) -> 67 Headers; 68fill_headers([[]], _, Headers) -> 69 Headers; 70fill_headers([[Ch|HeaderFold]|Tail], Folded, Headers) 71 when Ch == $\t; Ch == $\s -> 72 fill_headers(Tail, [HeaderFold|Folded], Headers); 73fill_headers([Header | Tail], Folded, Headers) -> 74 Unfolded = unfold([Header|Folded]), 75 {Key, [$: | Value]} = 76 lists:splitwith(fun($:) -> false; (_) -> true end, Unfolded), 77 fill_headers(Tail, [], headers(http_util:to_lower(string:strip(Key)), 78 string:strip(Value), Headers)). 79 80unfold([L]) -> 81 L; 82unfold(Folded) -> 83 string:join(Folded, " "). 84 85headers("cache-control", Value, Headers) -> 86 Headers#http_response_h{'cache-control'= Value}; 87headers("connection", Value, Headers) -> 88 Headers#http_response_h{connection = Value}; 89headers("date", Value, Headers) -> 90 Headers#http_response_h{date = Value}; 91headers("pragma", Value, Headers) -> 92 Headers#http_response_h{pragma = Value}; 93headers("trailer", Value, Headers) -> 94 Headers#http_response_h{trailer = Value}; 95headers("transfer-encoding", Value, Headers) -> 96 Headers#http_response_h{'transfer-encoding' = Value}; 97headers("upgrade", Value, Headers) -> 98 Headers#http_response_h{upgrade = Value}; 99headers("via", Value, Headers) -> 100 Headers#http_response_h{via = Value}; 101headers("warning", Value, Headers) -> 102 Headers#http_response_h{warning = Value}; 103headers("accept-ranges", Value, Headers) -> 104 Headers#http_response_h{'accept-ranges' = Value}; 105headers("age", Value, Headers) -> 106 Headers#http_response_h{age = Value}; 107headers("etag", Value, Headers) -> 108 Headers#http_response_h{etag = Value}; 109headers("location", Value, Headers) -> 110 Headers#http_response_h{location = Value}; 111headers("proxy-authenticate", Value, Headers) -> 112 Headers#http_response_h{'proxy-authenticate' = Value}; 113headers("retry-after", Value, Headers) -> 114 Headers#http_response_h{'retry-after' = Value}; 115headers("server", Value, Headers) -> 116 Headers#http_response_h{server = Value}; 117headers("vary", Value, Headers) -> 118 Headers#http_response_h{vary = Value}; 119headers("www-authenticate", Value, Headers) -> 120 Headers#http_response_h{'www-authenticate' = Value}; 121headers("allow", Value, Headers) -> 122 Headers#http_response_h{allow = Value}; 123headers("content-encoding", Value, Headers) -> 124 Headers#http_response_h{'content-encoding' = Value}; 125headers("content-language", Value, Headers) -> 126 Headers#http_response_h{'content-language' = Value}; 127headers("content-length", Value, Headers) -> 128 Headers#http_response_h{'content-length' = Value}; 129headers("content-location", Value, Headers) -> 130 Headers#http_response_h{'content-location' = Value}; 131headers("content-md5", Value, Headers) -> 132 Headers#http_response_h{'content-md5' = Value}; 133headers("content-range", Value, Headers) -> 134 Headers#http_response_h{'content-range' = Value}; 135headers("content-type", Value, Headers) -> 136 Headers#http_response_h{'content-type' = Value}; 137headers("expires", Value, Headers) -> 138 Headers#http_response_h{expires = Value}; 139headers("last-modified", Value, Headers) -> 140 Headers#http_response_h{'last-modified' = Value}; 141headers(Key, Value, Headers) -> 142 Headers#http_response_h{other= 143 [{Key, Value} | Headers#http_response_h.other]}. 144 145 146key_value_tuple(Key = 'cache-control', Headers) -> 147 key_value_tuple(atom_to_list(Key), 148 Headers#http_response_h.'cache-control'); 149key_value_tuple(Key = connection, Headers) -> 150 key_value_tuple(atom_to_list(Key), Headers#http_response_h.connection); 151key_value_tuple(Key = date, Headers) -> 152 key_value_tuple(atom_to_list(Key), Headers#http_response_h.date); 153key_value_tuple(Key = pragma, Headers) -> 154 key_value_tuple(atom_to_list(Key), Headers#http_response_h.pragma); 155key_value_tuple(Key = trailer, Headers) -> 156 key_value_tuple(atom_to_list(Key), Headers#http_response_h.trailer); 157key_value_tuple(Key ='transfer-encoding', Headers) -> 158 key_value_tuple(atom_to_list(Key), 159 Headers#http_response_h.'transfer-encoding'); 160key_value_tuple(Key = upgrade, Headers) -> 161 key_value_tuple(atom_to_list(Key), Headers#http_response_h.upgrade); 162key_value_tuple(Key = via, Headers) -> 163 key_value_tuple(atom_to_list(Key), Headers#http_response_h.via); 164key_value_tuple(Key = warning, Headers) -> 165 key_value_tuple(atom_to_list(Key), Headers#http_response_h.warning); 166key_value_tuple(Key = 'accept-ranges', Headers) -> 167 key_value_tuple(atom_to_list(Key), 168 Headers#http_response_h.'accept-ranges'); 169key_value_tuple(Key = age, Headers) -> 170 key_value_tuple(atom_to_list(Key), Headers#http_response_h.age); 171key_value_tuple(Key = etag, Headers) -> 172 key_value_tuple(atom_to_list(Key), Headers#http_response_h.etag); 173key_value_tuple(Key = location, Headers) -> 174 key_value_tuple(atom_to_list(Key), Headers#http_response_h.location); 175key_value_tuple(Key = 'proxy-authenticate', Headers) -> 176 key_value_tuple(atom_to_list(Key), 177 Headers#http_response_h.'proxy-authenticate'); 178key_value_tuple(Key = 'retry-after', Headers) -> 179 key_value_tuple(atom_to_list(Key), Headers#http_response_h.'retry-after'); 180key_value_tuple(Key = server, Headers) -> 181 key_value_tuple(atom_to_list(Key), Headers#http_response_h.server); 182key_value_tuple(Key = vary, Headers) -> 183 key_value_tuple(atom_to_list(Key), Headers#http_response_h.vary); 184key_value_tuple(Key = 'www-authenticate', Headers) -> 185 key_value_tuple(atom_to_list(Key), 186 Headers#http_response_h.'www-authenticate'); 187key_value_tuple(Key = allow, Headers) -> 188 key_value_tuple(atom_to_list(Key), Headers#http_response_h.allow); 189key_value_tuple(Key = 'content-encoding', Headers) -> 190 key_value_tuple(atom_to_list(Key), 191 Headers#http_response_h.'content-encoding'); 192key_value_tuple(Key = 'content-language', Headers) -> 193 key_value_tuple(atom_to_list(Key), 194 Headers#http_response_h.'content-language'); 195key_value_tuple(Key = 'content-length', Headers) -> 196 case Headers#http_response_h.'content-length' of 197 "-1" -> 198 undefined; 199 _ -> 200 key_value_tuple(atom_to_list(Key), 201 Headers#http_response_h.'content-length') 202 end; 203key_value_tuple(Key = 'content-location', Headers) -> 204 key_value_tuple(atom_to_list(Key), 205 Headers#http_response_h.'content-location'); 206key_value_tuple(Key = 'content-md5', Headers) -> 207 key_value_tuple(atom_to_list(Key), 208 Headers#http_response_h.'content-md5'); 209key_value_tuple(Key = 'content-range', Headers) -> 210 key_value_tuple(atom_to_list(Key), 211 Headers#http_response_h.'content-range'); 212key_value_tuple(Key = 'content-type', Headers) -> 213 key_value_tuple(atom_to_list(Key), 214 Headers#http_response_h.'content-type'); 215key_value_tuple(Key = expires, Headers) -> 216 key_value_tuple(atom_to_list(Key), Headers#http_response_h.expires); 217key_value_tuple(Key = 'last-modified', Headers) -> 218 key_value_tuple(atom_to_list(Key), 219 Headers#http_response_h.'last-modified'); 220key_value_tuple(_, undefined) -> 221 undefined; 222key_value_tuple(Key, Value) -> 223 {Key, Value}. 224