Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

160 lines (140 sloc) 5.171 kb
%% @author Bryan Fink <bryan@basho.com>
%% @author Andy Gross <andy@basho.com>
%% @author Justin Sheehy <justin@basho.com>
%% @copyright 2008-2009 Basho Technologies, Inc.
-module(webmachine_demo_fs_resource).
-export([init/1]).
-export([allowed_methods/2,
resource_exists/2,
last_modified/2,
content_types_provided/2,
content_types_accepted/2,
delete_resource/2,
post_is_create/2,
create_path/2,
provide_content/2,
accept_content/2,
generate_etag/2]).
-record(context, {root,response_body=undefined,metadata=[]}).
-include_lib("kernel/include/file.hrl").
-include_lib("webmachine/include/webmachine.hrl").
init(ConfigProps) ->
{root, Root} = proplists:lookup(root, ConfigProps),
{ok, #context{root=Root}}.
allowed_methods(ReqData, Context) ->
{['HEAD', 'GET', 'PUT', 'DELETE', 'POST'], ReqData, Context}.
file_path(_Context, []) ->
false;
file_path(Context, Name) ->
RelName = case hd(Name) of
"/" -> tl(Name);
_ -> Name
end,
filename:join([Context#context.root, RelName]).
file_exists(Context, Name) ->
NamePath = file_path(Context, Name),
case filelib:is_regular(NamePath) of
true ->
{true, NamePath};
false ->
false
end.
resource_exists(ReqData, Context) ->
Path = wrq:disp_path(ReqData),
case file_exists(Context, Path) of
{true, _} ->
{true, ReqData, Context};
_ ->
case Path of
"p" -> {true, ReqData, Context};
_ -> {false, ReqData, Context}
end
end.
maybe_fetch_object(Context, Path) ->
% if returns {true, NewContext} then NewContext has response_body
case Context#context.response_body of
undefined ->
case file_exists(Context, Path) of
{true, FullPath} ->
{ok, Value} = file:read_file(FullPath),
{true, Context#context{response_body=Value}};
false ->
{false, Context}
end;
_Body ->
{true, Context}
end.
content_types_provided(ReqData, Context) ->
CT = webmachine_util:guess_mime(wrq:disp_path(ReqData)),
{[{CT, provide_content}], ReqData,
Context#context{metadata=[{'content-type', CT}|Context#context.metadata]}}.
content_types_accepted(ReqData, Context) ->
CT = case wrq:get_req_header("content-type", ReqData) of
undefined -> "application/octet-stream";
X -> X
end,
{MT, _Params} = webmachine_util:media_type_to_detail(CT),
{[{MT, accept_content}], ReqData,
Context#context{metadata=[{'content-type', MT}|Context#context.metadata]}}.
accept_content(ReqData, Context) ->
Path = wrq:disp_path(ReqData),
FP = file_path(Context, Path),
ok = filelib:ensure_dir(FP),
ReqData1 = case file_exists(Context, Path) of
{true, _} ->
ReqData;
_ ->
LOC = "http://" ++
wrq:get_req_header("host", ReqData) ++
"/fs/" ++ Path,
wrq:set_resp_header("Location", LOC, ReqData)
end,
Value = wrq:req_body(ReqData1),
case file:write_file(FP, Value) of
ok ->
{true, wrq:set_resp_body(Value, ReqData1), Context};
Err ->
{{error, Err}, ReqData1, Context}
end.
post_is_create(ReqData, Context) ->
{true, ReqData, Context}.
create_path(ReqData, Context) ->
case wrq:get_req_header("slug", ReqData) of
undefined -> {undefined, ReqData, Context};
Slug ->
case file_exists(Context, Slug) of
{true, _} -> {undefined, ReqData, Context};
_ -> {Slug, ReqData, Context}
end
end.
delete_resource(ReqData, Context) ->
case file:delete(file_path(
Context, wrq:disp_path(ReqData))) of
ok -> {true, ReqData, Context};
_ -> {false, ReqData, Context}
end.
provide_content(ReqData, Context) ->
case maybe_fetch_object(Context, wrq:disp_path(ReqData)) of
{true, NewContext} ->
Body = NewContext#context.response_body,
{Body, ReqData, Context};
{false, NewContext} ->
{error, ReqData, NewContext}
end.
last_modified(ReqData, Context) ->
{true, FullPath} = file_exists(Context,
wrq:disp_path(ReqData)),
LMod = filelib:last_modified(FullPath),
{LMod, ReqData, Context#context{metadata=[{'last-modified',
httpd_util:rfc1123_date(LMod)}|Context#context.metadata]}}.
hash_body(Body) -> mochihex:to_hex(binary_to_list(crypto:sha(Body))).
generate_etag(ReqData, Context) ->
case maybe_fetch_object(Context, wrq:disp_path(ReqData)) of
{true, BodyContext} ->
ETag = hash_body(BodyContext#context.response_body),
{ETag, ReqData,
BodyContext#context{metadata=[{etag,ETag}|
BodyContext#context.metadata]}};
_ ->
{undefined, ReqData, Context}
end.
Jump to Line
Something went wrong with that request. Please try again.