-
Notifications
You must be signed in to change notification settings - Fork 42
/
mod_ocs_rest_put.erl
127 lines (119 loc) · 4.41 KB
/
mod_ocs_rest_put.erl
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
%%% mod_ocs_rest_put.erl
%%% vim: ts=3
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% @copyright 2017 SigScale Global Inc.
%%% @end
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
%%% You may obtain a copy of the License at
%%%
%%% http://www.apache.org/licenses/LICENSE-2.0
%%%
%%% Unless required by applicable law or agreed to in writing, software
%%% distributed under the License is distributed on an "AS IS" BASIS,
%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% See the License for the specific language governing permissions and
%%% limitations under the License.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
-module(mod_ocs_rest_put).
-copyright('Copyright (c) 2017 SigScale Global Inc.').
-export([do/1]).
-include_lib("inets/include/httpd.hrl").
-spec do(ModData) -> Result when
ModData :: #mod{},
Result :: {proceed, OldData} | {proceed, NewData} | {break, NewData} | done,
OldData :: list(),
NewData :: [{response,{StatusCode,Body}}] | [{response,{response,Head,Body}}]
| [{response,{already_sent,StatusCode,Size}}],
StatusCode :: integer(),
Body :: iolist() | nobody | {Fun, Arg},
Head :: [HeaderOption],
HeaderOption :: {Option, Value} | {code, StatusCode},
Option :: accept_ranges | allow
| cache_control | content_MD5
| content_encoding | content_language
| content_length | content_location
| content_range | content_type | date
| etag | expires | last_modified
| location | pragma | retry_after
| server | trailer | transfer_encoding,
Value :: string(),
Size :: term(),
Fun :: fun((Arg) -> sent| close | Body),
Arg :: [term()].
%% @doc Erlang web server API callback function.
do(#mod{method = Method, parsed_header = Headers, request_uri = Uri,
entity_body = Body, data = Data} = ModData) ->
case Method of
"PUT" ->
case proplists:get_value(status, Data) of
{_StatusCode, _PhraseArgs, _Reason} ->
{proceed, Data};
undefined ->
case proplists:get_value(response, Data) of
undefined ->
{_, Resource} = lists:keyfind(resource, 1, Data),
content_type_available(Headers, Body, Uri, Resource, ModData);
_Response ->
{proceed, Data}
end
end;
_ ->
{proceed, Data}
end.
%% @hidden
content_type_available(Headers, Body, Uri, Resource, ModData) ->
case lists:keyfind("accept", 1, Headers) of
{_, RequestingType} ->
AvailableTypes = Resource:content_types_provided(),
case lists:member(RequestingType, AvailableTypes) of
true ->
Etag = get_etag(Headers),
do_put(Body, Resource, ModData, Etag, string:tokens(Uri, "/"));
false ->
Response = "<h2>HTTP Error 415 - Unsupported Media Type</h2>",
{break, [{response, {415, Response}}]}
end;
_ ->
do_put(Uri, Body, Resource, undefined, ModData)
end.
%%
%% @hidden
get_etag(Headers) ->
case lists:keyfind("if-match", 1, Headers) of
{_, Etag} ->
Etag;
false ->
undefined
end.
%% @hidden
do_put(Body, Resource, ModData, Etag, ["partyManagement", "v1", "individual", Identity]) ->
do_response(ModData, Resource:put_user(Identity, Etag, Body));
do_put(_Body, _Resource, _ModData, _, _) ->
Response = "<h2>HTTP Error 404 - Not Found</h2>",
{break, [{response, {404, Response}}]}.
%% @hidden
do_response(#mod{data = Data} = ModData, {ok, Headers, ResponseBody}) ->
Size = integer_to_list(iolist_size(ResponseBody)),
Accept = proplists:get_value(accept, Data),
NewHeaders = Headers ++ [{content_length, Size}, {content_type, Accept}],
send(ModData, 200, NewHeaders, ResponseBody),
{proceed,[{response,{already_sent,201, Size}}]};
do_response(_ModData, {error, 400}) ->
Response = "<h2>HTTP Error 400 - Bad Request</h2>",
{break, [{response, {400, Response}}]};
do_response(_ModData, {error, 404}) ->
Response = "<h2>HTTP Error 404 - Not Found</h2>",
{break, [{response, {404, Response}}]};
do_response(_ModData, {error, 412}) ->
Response = "<h2>HTTP Error 412 - Precondition Failed</h2>",
{break, [{response, {412, Response}}]};
do_response(_ModData, {error, 500}) ->
Response = "<h2>HTTP Error 500 - Server Error</h2>",
{break, [{response, {500, Response}}]}.
%% @hidden
send(#mod{socket = Socket, socket_type = SocketType} = Info,
StatusCode, Headers, ResponseBody) ->
httpd_response:send_header(Info, StatusCode, Headers),
httpd_socket:deliver(SocketType, Socket, ResponseBody).