PageRenderTime 143ms CodeModel.GetById 61ms app.highlight 6ms RepoModel.GetById 74ms app.codeStats 0ms

/src/middleware/ewgi_deflate/ewgi_deflate.erl

http://github.com/skarab/ewgi
Erlang | 70 lines | 53 code | 8 blank | 9 comment | 0 complexity | ee9910f3fc781f7f123f2e3b09de5e1b MD5 | raw file
 1%% @author Filippo Pacini <filippo.pacini@gmail.com>
 2%% @copyright 2009 S.G. Consulting.
 3
 4%% @doc deflate ewgi middleware.
 5
 6-module(ewgi_deflate).
 7-author('Filippo Pacini <filippo.pacini@gmail.com>').
 8
 9-export([run/2]).
10
11-define(ENCODABLE, ["text/plain", "text/html", "text/xml"]).
12
13run(Ctx, []) ->
14    %% get the accept encoding header
15    AcceptEnc = ewgi_api:get_header_value("accept-encoding", Ctx),
16    Hdrs = ewgi_api:response_headers(Ctx),
17    %% check gzip/deflate
18    Ctx1 = case can_encode_response(Hdrs) of
19               true ->
20                   case parse_encoding(AcceptEnc) of
21                       false ->
22                           Ctx;
23                       gzip ->
24                           %% FIXME: does not work if response_message_body streams a file
25                           Body1 = zlib:gzip(ewgi_api:response_message_body(Ctx)),
26                           Hdrs1 = [{"Content-encoding", "gzip"}|Hdrs],
27                           ewgi_api:response_headers(
28                             Hdrs1, 
29                             ewgi_api:response_message_body(Body1, Ctx)
30                            );
31                       deflate ->
32                           %% FIXME: does not work if response_message_body streams a file
33                           Body1 = zlib:compress(ewgi_api:response_message_body(Ctx)),
34                           Hdrs1 = [{"Content-encoding", "deflate"}|Hdrs],
35                           ewgi_api:response_headers(
36                             Hdrs1, 
37                             ewgi_api:response_message_body(Body1, Ctx)
38                            )
39                   end;
40               false ->
41                   Ctx
42           end,
43    Ctx1.
44
45can_encode_response(Headers) ->
46    ContentType = proplists:get_value("Content-type", Headers),
47    ContentEnc = proplists:get_value("Content-encoding", Headers),
48    can_encode_response1(ContentType, ContentEnc).
49
50can_encode_response1(ContentType, undefined) ->
51    lists:member(ContentType, ?ENCODABLE);
52can_encode_response1(_ContentType, _ContentEncoding) ->
53    %% the response is already encoded in some way so we don't do anything
54    false.
55
56parse_encoding(undefined) ->
57    false;
58parse_encoding(Encoding) ->
59    %% FIXME: read HTTP specs to see how to do this properly (e.g. check the q=X and the order)
60    case string:str(Encoding, "gzip") of
61        X when X>0 ->
62            gzip;
63        _ ->
64            case string:str(Encoding, "deflate") of
65                Y when Y>0 ->
66                    deflate;
67                _ ->
68                    false
69            end
70    end.