Skip to content
This repository
tree: ce3cf9e078
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 107 lines (88 sloc) 3.738 kb
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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
% Simple Bridge
% Copyright (c) 2008-2010 Rusty Klophaus
% See MIT-LICENSE for licensing information.

-module(yaws_response_bridge).
-behaviour (simple_bridge_response).
-include_lib ("simple_bridge.hrl").
-export ([build_response/2]).

build_response(_Arg, Res) ->
    % Get vars...
    Code = Res#response.statuscode,

    %% Assemble headers...
    Headers = assemble_headers(Res),


    case Res#response.data of
        {data, Body} ->

%% Get the content type...
ContentType = get_content_type(Res),

            % Send the yaws response...
            lists:flatten([
                           {status, Code},
                           Headers,
                           {content, ContentType, Body}
                          ]);

        {file, Path} ->
%% Note: This section should only be entered in the event that a static file is
%% requested that isn't found in the 'appmod' section of the yaws.conf file.
%% I've not found a way to "pass the buck" back to yaws and say "even though this
%% directory isn't found in the appmod, I want you to serve it anyway". This
%% means that with the current implementation, you don't want to be serving files
%% big files that aren't covered in the appmod section, primarily because this little
%% snippet loads the entire file into memory then passes it off to yaws to be served,
%% rather than streaming it. I'll need to look further into to either 1) Pass the buck
%% completely back to Yaws, or 2) how the streamcontent return types work as define in
%% yaws_server:handle_out_reply

            %% Calculate expire date far into future...
            Seconds = calendar:datetime_to_gregorian_seconds(calendar:local_time()),
            TenYears = 10 * 365 * 24 * 60 * 60,
            Seconds1 = calendar:gregorian_seconds_to_datetime(Seconds + TenYears),
            ExpireDate = httpd_util:rfc1123_date(Seconds1),

%% Docroot needed to find file in Path
Docroot = yaws_api:arg_docroot(_Arg),
FullPath = [Docroot,Path],

%% Get the content type as defined by yaws
ContentType = yaws_api:mime_type(Path),

            %% Get the file content
            FullResponse = case file:read_file(FullPath) of
{error,enoent} ->
yaws_outmod:out404(_Arg);
{ok,Bin} ->
[
{status, Code},
[{header, {"Expires", ExpireDate}} | Headers],
{content, ContentType, Bin}
]
end,
lists:flatten(FullResponse)
    end.

assemble_headers(Res) ->
    lists:flatten([
                   [{header, {X#header.name, X#header.value}} || X <- Res#response.headers],
                   [create_cookie(X) || X <- Res#response.cookies]
                  ]).
    
get_content_type(Res) ->
    coalesce([
              kvl3(content_type, Res#response.headers),
              kvl3("content-type", Res#response.headers),
              kvl3("Content-Type", Res#response.headers),
              kvl3("CONTENT-TYPE", Res#response.headers),
              "text/html"
             ]).

kvl3(Key,L) ->
    case lists:keysearch(Key,2,L) of
        {value, {_,_,Val}} -> Val;
        _ -> undefined
    end.

coalesce([]) -> undefined;
coalesce([undefined|T]) -> coalesce(T);
coalesce([H|_T]) -> H.

create_cookie(Cookie) ->
    Name = Cookie#cookie.name,
    Value = Cookie#cookie.value,
    Path = Cookie#cookie.path,
    SecondsToLive = Cookie#cookie.minutes_to_live * 60,
    Expire = to_cookie_expire(SecondsToLive),
    yaws_api:setcookie(Name, Value, Path, Expire).

to_cookie_expire(SecondsToLive) ->
    Seconds = calendar:datetime_to_gregorian_seconds(calendar:local_time()),
    DateTime = calendar:gregorian_seconds_to_datetime(Seconds + SecondsToLive),
    httpd_util:rfc1123_date(DateTime).
Something went wrong with that request. Please try again.