PageRenderTime 29ms CodeModel.GetById 13ms app.highlight 13ms RepoModel.GetById 2ms app.codeStats 0ms

/deps/webmachine/demo/src/demo_fs_resource.erl

https://code.google.com/p/zotonic/
Erlang | 157 lines | 133 code | 19 blank | 5 comment | 0 complexity | ca4eba93dec0d8b24fe74653885b1621 MD5 | raw file
  1%% @author Bryan Fink <bryan@basho.com>
  2%% @author Andy Gross <andy@basho.com>
  3%% @author Justin Sheehy <justin@basho.com>
  4%% @copyright 2008-2009 Basho Technologies, Inc.
  5
  6-module(demo_fs_resource).
  7-export([init/1]).
  8-export([allowed_methods/2,
  9	 resource_exists/2,
 10	 last_modified/2,
 11	 content_types_provided/2,
 12	 content_types_accepted/2,
 13         delete_resource/2,
 14         post_is_create/2,
 15         create_path/2,
 16	 provide_content/2,
 17	 accept_content/2,
 18	 generate_etag/2]).
 19
 20-record(context, {root,response_body=undefined,metadata=[]}).
 21
 22-include_lib("kernel/include/file.hrl").
 23-include_lib("webmachine/include/webmachine.hrl").
 24
 25init(ConfigProps) ->
 26    {root, Root} = proplists:lookup(root, ConfigProps),
 27    {ok, #context{root=Root}}.
 28    
 29allowed_methods(ReqData, Context) ->
 30    {['HEAD', 'GET', 'PUT', 'DELETE', 'POST'], ReqData, Context}.
 31
 32file_path(Context, Name) ->
 33    RelName = case hd(Name) of
 34        "/" -> tl(Name);
 35        _ -> Name
 36    end,
 37    filename:join([Context#context.root, RelName]).
 38
 39file_exists(Context, Name) ->
 40    NamePath = file_path(Context, Name),
 41    case filelib:is_regular(NamePath) of 
 42	true ->
 43	    {true, NamePath};
 44	false ->
 45	    false
 46    end.
 47
 48resource_exists(ReqData, Context) ->
 49    Path = wrq:disp_path(ReqData),
 50    case file_exists(Context, Path) of 
 51	{true, _} ->
 52	    {true, ReqData, Context};
 53	_ ->
 54            case Path of
 55                "p" -> {true, ReqData, Context};
 56                _ -> {false, ReqData, Context}
 57            end
 58    end.
 59
 60maybe_fetch_object(Context, Path) ->
 61    % if returns {true, NewContext} then NewContext has response_body
 62    case Context#context.response_body of
 63	undefined ->
 64	    case file_exists(Context, Path) of 
 65		{true, FullPath} ->
 66		    {ok, Value} = file:read_file(FullPath),
 67		    {true, Context#context{response_body=Value}};
 68		false ->
 69		    {false, Context}
 70	    end;
 71	_Body ->
 72	    {true, Context}
 73    end.
 74
 75content_types_provided(ReqData, Context) ->
 76    CT = webmachine_util:guess_mime(wrq:disp_path(ReqData)),
 77    {[{CT, provide_content}], ReqData,
 78     Context#context{metadata=[{'content-type', CT}|Context#context.metadata]}}.
 79
 80content_types_accepted(ReqData, Context) ->
 81    CT = case wrq:get_req_header_lc("content-type", ReqData) of
 82             undefined -> "application/octet-stream";
 83             X -> X
 84         end,
 85    {MT, _Params} = webmachine_util:media_type_to_detail(CT),
 86    {[{MT, accept_content}], ReqData,
 87     Context#context{metadata=[{'content-type', MT}|Context#context.metadata]}}.
 88
 89accept_content(ReqData, Context) ->
 90    Path = wrq:disp_path(ReqData),
 91    FP = file_path(Context, Path),
 92    ok = filelib:ensure_dir(filename:dirname(FP)),
 93    ReqData1 = case file_exists(Context, Path) of 
 94	{true, _} ->
 95            ReqData;
 96	_ ->
 97            LOC = "http://" ++
 98                   wrq:get_req_header_lc("host", ReqData) ++
 99                   "/fs/" ++ Path,
100            wrq:set_resp_header("Location", LOC, ReqData)
101    end,
102    Value = wrq:req_body(ReqData1),
103    case file:write_file(FP, Value) of
104        ok ->
105            {true, wrq:set_resp_body(Value, ReqData1), Context};
106        Err ->
107            {{error, Err}, ReqData1, Context}
108    end.    
109
110post_is_create(ReqData, Context) ->
111    {true, ReqData, Context}.
112
113create_path(ReqData, Context) ->
114    case wrq:get_req_header_lc("slug", ReqData) of
115        undefined -> {undefined, ReqData, Context};
116        Slug ->
117            case file_exists(Context, Slug) of
118                {true, _} -> {undefined, ReqData, Context};
119                _ -> {Slug, ReqData, Context}
120            end
121    end.
122
123delete_resource(ReqData, Context) ->
124    case file:delete(file_path(
125                       Context, wrq:disp_path(ReqData))) of
126        ok -> {true, ReqData, Context};
127        _ -> {false, ReqData, Context}
128    end.
129
130provide_content(ReqData, Context) ->
131    case maybe_fetch_object(Context, wrq:disp_path(ReqData)) of 
132	{true, NewContext} ->
133	    Body = NewContext#context.response_body,
134	    {Body, ReqData, Context};
135	{false, NewContext} ->
136	    {error, ReqData, NewContext}
137    end.
138
139last_modified(ReqData, Context) ->
140    {true, FullPath} = file_exists(Context,
141                                   wrq:disp_path(ReqData)),
142    LMod = filelib:last_modified(FullPath),
143    {LMod, ReqData, Context#context{metadata=[{'last-modified',
144                    httpd_util:rfc1123_date(LMod)}|Context#context.metadata]}}.
145
146hash_body(Body) -> mochihex:to_hex(binary_to_list(crypto:sha(Body))).
147
148generate_etag(ReqData, Context) ->
149    case maybe_fetch_object(Context, wrq:disp_path(ReqData)) of
150        {true, BodyContext} ->
151            ETag = hash_body(BodyContext#context.response_body),
152            {ETag, ReqData,
153             BodyContext#context{metadata=[{etag,ETag}|
154                                           BodyContext#context.metadata]}};
155        _ ->
156            {undefined, ReqData, Context}
157    end.