1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1997-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(mod_get). 22 23-export([do/1]). 24 25-include("httpd.hrl"). 26-include("httpd_internal.hrl"). 27-include("inets_internal.hrl"). 28 29-define(VMODULE,"GET"). 30 31 32%% do 33 34do(Info) -> 35 case Info#mod.method of 36 "GET" -> 37 case proplists:get_value(status, Info#mod.data) of 38 %% A status code has been generated! 39 {_StatusCode, _PhraseArgs, _Reason} -> 40 {proceed,Info#mod.data}; 41 %% No status code has been generated! 42 undefined -> 43 case proplists:get_value(response, Info#mod.data) of 44 %% No response has been generated! 45 undefined -> 46 do_get(Info); 47 %% A response has been generated or sent! 48 _Response -> 49 {proceed,Info#mod.data} 50 end 51 end; 52 %% Not a GET method! 53 _ -> 54 {proceed,Info#mod.data} 55 end. 56 57 58do_get(Info) -> 59 Path = mod_alias:path(Info#mod.data, Info#mod.config_db, 60 Info#mod.request_uri), 61 62 send_response(Info#mod.socket,Info#mod.socket_type, Path, Info). 63 64 65%% The common case when no range is specified 66send_response(_Socket, _SocketType, Path, Info)-> 67 %% Send the file! 68 %% Find the modification date of the file 69 case file:open(Path,[raw,binary]) of 70 {ok, FileDescriptor} -> 71 {FileInfo, LastModified} = get_modification_date(Path), 72 Suffix = httpd_util:suffix(Path), 73 MimeType = httpd_util:lookup_mime_default(Info#mod.config_db, 74 Suffix,"text/plain"), 75 %% FileInfo = file:read_file_info(Path), 76 Size = integer_to_list(FileInfo#file_info.size), 77 Headers = case Info#mod.http_version of 78 "HTTP/1.1" -> 79 [{content_type, MimeType}, 80 {etag, httpd_util:create_etag(FileInfo)}, 81 {content_length, Size}|LastModified]; 82 %% OTP-4935 83 _ -> 84 %% i.e http/1.0 and http/0.9 85 [{content_type, MimeType}, 86 {content_length, Size}|LastModified] 87 end, 88 send(Info, 200, Headers, FileDescriptor), 89 file:close(FileDescriptor), 90 {proceed,[{response,{already_sent,200, 91 FileInfo#file_info.size}}, 92 {mime_type,MimeType} | Info#mod.data]}; 93 {error, Reason} -> 94 Status = httpd_file:handle_error(Reason, "open", Info, Path), 95 {proceed, [{status, Status} | Info#mod.data]} 96 end. 97 98%% send 99 100send(#mod{socket = Socket, socket_type = SocketType} = Info, 101 StatusCode, Headers, FileDescriptor) -> 102 httpd_response:send_header(Info, StatusCode, Headers), 103 send_body(SocketType,Socket,FileDescriptor). 104 105 106send_body(SocketType,Socket,FileDescriptor) -> 107 case file:read(FileDescriptor,?FILE_CHUNK_SIZE) of 108 {ok,Binary} -> 109 case httpd_socket:deliver(SocketType,Socket,Binary) of 110 socket_closed -> 111 socket_close; 112 _ -> 113 send_body(SocketType,Socket,FileDescriptor) 114 end; 115 eof -> 116 eof 117 end. 118 119get_modification_date(Path)-> 120 {ok, FileInfo0} = file:read_file_info(Path), 121 LastModified = 122 case catch httpd_util:rfc1123_date(FileInfo0#file_info.mtime) of 123 Date when is_list(Date) -> [{last_modified, Date}]; 124 _ -> [] 125 end, 126 {FileInfo0, LastModified}. 127