Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 274 lines (239 sloc) 11.134 kb
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
1 %%%-------------------------------------------------------------------
2 %%% Created : 29 Nov 2006 by Torbjorn Tornkvist <tobbe@tornkvist.org>
3 %%% Author : Willem de Jong (w.a.de.jong@gmail.com).
4 %%% Desc : A SOAP server.
5 %%%-------------------------------------------------------------------
6 -module(yaws_soap_srv).
7
8 -behaviour(gen_server).
9
10 %% API
58a4471 @ericliang get back the start_link/0 in yaws_soap_srv.
ericliang authored
11 -export([start_link/0, start_link/1,
0be3c7e @klacke untabified all of yaws
authored
12 setup/1, setup/2, setup/3,
13 handler/4
14 ]).
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
15
16 %% gen_server callbacks
17 -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
0be3c7e @klacke untabified all of yaws
authored
18 terminate/2, code_change/3]).
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
19
20 -include("../include/yaws_api.hrl").
21 -include("../include/yaws.hrl").
22 -include("../include/soap.hrl").
23
24 -define(SERVER, ?MODULE).
25
26 %% State
27 -record(s, {
0be3c7e @klacke untabified all of yaws
authored
28 wsdl_list = [] % list of {Id, WsdlModel} tuples, where Id == {M,F}
29 }).
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
30
31 -define(OK_CODE, 200).
32 -define(BAD_MESSAGE_CODE, 400).
33 %% -define(METHOD_NOT_ALLOWED_CODE, 405).
34 -define(SERVER_ERROR_CODE, 500).
35
36 %%====================================================================
37 %% API
38 %%====================================================================
39 %%--------------------------------------------------------------------
40 %% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
41 %% Description: Starts the server
42 %%--------------------------------------------------------------------
58a4471 @ericliang get back the start_link/0 in yaws_soap_srv.
ericliang authored
43 start_link() ->
6e96a14 @klacke indendation cleanup
authored
44 start_link([]).
d8df08c @ericliang add the soap_srv_mods support, which can setup soap serve modules while ...
ericliang authored
45 start_link(L) ->
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
46 %% We are dependent on erlsom
47 case code:ensure_loaded(erlsom) of
455578a @vinoski major trailing whitespace cleanup
vinoski authored
48 {error, _} ->
0be3c7e @klacke untabified all of yaws
authored
49 Emsg = "could not load erlsom",
50 error_logger:error_msg("~p: exiting, reason: ~s~n",
51 [?MODULE, Emsg]),
52 {error, Emsg};
53 {module, erlsom} ->
d8df08c @ericliang add the soap_srv_mods support, which can setup soap serve modules while ...
ericliang authored
54 gen_server:start_link({local, ?SERVER}, ?MODULE, L, [])
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
55 end.
56
57 %%% To be called from yaws_rpc.erl
58 %%% Return according to yaws_rpc:eval_payload/6
59 handler(Args, Id, Payload, SessionValue) ->
60 Headers = Args#arg.headers,
61 SoapAction = yaws_soap_lib:findHeader("SOAPAction", Headers#headers.other),
455578a @vinoski major trailing whitespace cleanup
vinoski authored
62 case gen_server:call(?SERVER, {request, Id, Payload,
aa815f2 @klacke added a set of infinity to several gen_server:calls
authored
63 SessionValue, SoapAction}, infinity) of
0be3c7e @klacke untabified all of yaws
authored
64 {ok, XmlDoc, ResCode, undefined} ->
65 {false, XmlDoc, ResCode};
66 {ok, XmlDoc, ResCode, SessVal} ->
67 {true, 0, SessVal, XmlDoc, ResCode};
68 {error, _, _} = Error ->
69 Error;
70 false ->
71 false % soap notify
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
72 end.
73
74 %% Setup a SOAP interface according to the config file.
49cbf48 @klacke nice cleanup patch from Rickard Bucker
authored
75 setup(_ConfigFile) ->
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
76 tbd.
77
f44be6a @klacke all calls to old deprecated guard tests removed
authored
78 setup(Id, WsdlFile) when is_tuple(Id),size(Id)==2 ->
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
79 Wsdl = yaws_soap_lib:initModel(WsdlFile),
aa815f2 @klacke added a set of infinity to several gen_server:calls
authored
80 gen_server:call(?SERVER, {add_wsdl, Id, Wsdl}, infinity).
0be3c7e @klacke untabified all of yaws
authored
81
7811247 @vinoski whitespace cleanup
vinoski authored
82 %% PrefixOrOptions can be either a prefix (a String) or a property
ec553ff @willemdj Allow to pass options to erlsom (fix issue #65)
willemdj authored
83 %% list. It is used to construct the options that are passed to Erlsom
7811247 @vinoski whitespace cleanup
vinoski authored
84 %% to compile the WSDL file. Passing a string ("Prefix") is equivalent
85 %% to [{prefix, "Prefix"}].
ec553ff @willemdj Allow to pass options to erlsom (fix issue #65)
willemdj authored
86 %% If a list of erlsom options is passed, and this does not contain
87 %% the {prefix, ...} option, the yaws_soap default ("p") will be used.
88 setup(Id, WsdlFile, PrefixOrOptions) when is_tuple(Id),size(Id)==2 ->
89 Wsdl = yaws_soap_lib:initModel(WsdlFile, PrefixOrOptions),
aa815f2 @klacke added a set of infinity to several gen_server:calls
authored
90 gen_server:call(?SERVER, {add_wsdl, Id, Wsdl}, infinity).
0be3c7e @klacke untabified all of yaws
authored
91
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
92
93
94 %%====================================================================
95 %% gen_server callbacks
96 %%====================================================================
97
98 %%--------------------------------------------------------------------
99 %% Function: init(Args) -> {ok, State} |
100 %% {ok, State, Timeout} |
101 %% ignore |
102 %% {stop, Reason}
103 %% Description: Initiates the server
104 %%--------------------------------------------------------------------
d8df08c @ericliang add the soap_srv_mods support, which can setup soap serve modules while ...
ericliang authored
105 init(L) -> %% [ {{Mod,Handler}, WsdlFile} ]
455578a @vinoski major trailing whitespace cleanup
vinoski authored
106 WsdlList = lists:foldl( fun( SoapSrvMod, OldList) ->
107 setup_on_init( SoapSrvMod, OldList )
6e96a14 @klacke indendation cleanup
authored
108 end,[],L),
d8df08c @ericliang add the soap_srv_mods support, which can setup soap serve modules while ...
ericliang authored
109 {ok, #s{wsdl_list = WsdlList}}.
110
6e96a14 @klacke indendation cleanup
authored
111 setup_on_init( {Id, WsdlFile}, OldList ) when is_tuple(Id),size(Id) == 2 ->
112 Wsdl = yaws_soap_lib:initModel(WsdlFile),
113 uinsert({Id, Wsdl}, OldList);
114 setup_on_init( {Id, WsdlFile, Prefix}, OldList ) when is_tuple(Id),
115 size(Id) == 2 ->
116 Wsdl = yaws_soap_lib:initModel(WsdlFile, Prefix),
117 uinsert({Id, Wsdl}, OldList).
118
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
119 %%--------------------------------------------------------------------
120 %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
121 %% {reply, Reply, State, Timeout} |
122 %% {noreply, State} |
123 %% {noreply, State, Timeout} |
124 %% {stop, Reason, Reply, State} |
125 %% {stop, Reason, State}
126 %% Description: Handling call messages
127 %%--------------------------------------------------------------------
128 handle_call({add_wsdl, Id, WsdlModel}, _From, State) ->
129 NewWsdlList = uinsert({Id, WsdlModel}, State#s.wsdl_list),
130 {reply, ok, State#s{wsdl_list = NewWsdlList}};
131 %%
132 handle_call( {request, Id, Payload, SessionValue, SoapAction}, _From, State) ->
133 Reply = request(State, Id, Payload, SessionValue, SoapAction),
134 {reply, Reply, State}.
135
136 %%--------------------------------------------------------------------
137 %% Function: handle_cast(Msg, State) -> {noreply, State} |
138 %% {noreply, State, Timeout} |
139 %% {stop, Reason, State}
140 %% Description: Handling cast messages
141 %%--------------------------------------------------------------------
142 handle_cast(_Msg, State) ->
143 {noreply, State}.
144
145 %%--------------------------------------------------------------------
146 %% Function: handle_info(Info, State) -> {noreply, State} |
147 %% {noreply, State, Timeout} |
148 %% {stop, Reason, State}
149 %% Description: Handling all non call/cast messages
150 %%--------------------------------------------------------------------
151 handle_info(_Info, State) ->
152 {noreply, State}.
153
154 %%--------------------------------------------------------------------
155 %% Function: terminate(Reason, State) -> void()
156 %% Description: This function is called by a gen_server when it is about to
157 %% terminate. It should be the opposite of Module:init/1 and do any necessary
158 %% cleaning up. When it returns, the gen_server terminates with Reason.
159 %% The return value is ignored.
160 %%--------------------------------------------------------------------
161 terminate(_Reason, _State) ->
162 ok.
163
164 %%--------------------------------------------------------------------
165 %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
166 %% Description: Convert process state when code is changed
167 %%--------------------------------------------------------------------
168 code_change(_OldVsn, State, _Extra) ->
169 {ok, State}.
170
171 %%--------------------------------------------------------------------
172 %%% Internal functions
173 %%--------------------------------------------------------------------
174
0cfaa30 @nygge Add DIME support for SOAP
nygge authored
175 request(State, {M,F} = Id, {Req, Attachments}, SessionValue, Action) ->
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
176 {ok, Model} = get_model(State, Id),
0cfaa30 @nygge Add DIME support for SOAP
nygge authored
177 %%error_logger:info_report([?MODULE, {payload, Req}]),
178 case catch yaws_soap_lib:parseMessage(Req, Model) of
455578a @vinoski major trailing whitespace cleanup
vinoski authored
179 {ok, Header, Body} ->
0cfaa30 @nygge Add DIME support for SOAP
nygge authored
180 %% call function
455578a @vinoski major trailing whitespace cleanup
vinoski authored
181 result(Model, catch apply(M, F, [Header, Body,
0cfaa30 @nygge Add DIME support for SOAP
nygge authored
182 Action, SessionValue,
183 Attachments]));
184 {error, Error} ->
185 cli_error(Error);
455578a @vinoski major trailing whitespace cleanup
vinoski authored
186 OtherError ->
0cfaa30 @nygge Add DIME support for SOAP
nygge authored
187 srv_error(io_lib:format("Error parsing message: ~p", [OtherError]))
188 end;
189 request(State, {M,F} = Id, Req, SessionValue, Action) ->
190 %%error_logger:info_report([?MODULE, {payload, Req}]),
191 {ok, Model} = get_model(State, Id),
192 Umsg = (catch erlsom_lib:toUnicode(Req)),
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
193 case catch yaws_soap_lib:parseMessage(Umsg, Model) of
455578a @vinoski major trailing whitespace cleanup
vinoski authored
194 {ok, Header, Body} ->
0be3c7e @klacke untabified all of yaws
authored
195 %% call function
455578a @vinoski major trailing whitespace cleanup
vinoski authored
196 result(Model, catch apply(M, F, [Header, Body,
0be3c7e @klacke untabified all of yaws
authored
197 Action, SessionValue]));
198 {error, Error} ->
199 cli_error(Error);
455578a @vinoski major trailing whitespace cleanup
vinoski authored
200 OtherError ->
0be3c7e @klacke untabified all of yaws
authored
201 srv_error(io_lib:format("Error parsing message: ~p", [OtherError]))
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
202 end.
203
204 %%% Analyse the result and produce some output
205 result(Model, {ok, ResHeader, ResBody, ResCode, SessVal}) ->
0cfaa30 @nygge Add DIME support for SOAP
nygge authored
206 return(Model, ResHeader, ResBody, ResCode, SessVal, undefined);
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
207 result(Model, {ok, ResHeader, ResBody}) ->
0cfaa30 @nygge Add DIME support for SOAP
nygge authored
208 return(Model, ResHeader, ResBody, ?OK_CODE, undefined, undefined);
209 result(Model, {ok, ResHeader, ResBody, Files}) ->
210 return(Model, ResHeader, ResBody, ?OK_CODE, undefined, Files);
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
211 result(_Model, {error, client, ClientMssg}) ->
212 cli_error(ClientMssg);
213 result(_Model, false) -> % soap notify !
214 false;
215 result(_Model, Error) ->
216 srv_error(io_lib:format("Error processing message: ~p", [Error])).
217
b6e60f0 @vinoski revert "remove support for SOAP DIME attachments"
vinoski authored
218 return(#wsdl{model = Model}, ResHeader, ResBody, ResCode, SessVal, Files) ->
219 return(Model, ResHeader, ResBody, ResCode, SessVal, Files);
220 return(Model, ResHeader, ResBody, ResCode, SessVal, Files)
65bf36a @vinoski remove support for SOAP DIME attachments
vinoski authored
221 when not is_list(ResBody) ->
b6e60f0 @vinoski revert "remove support for SOAP DIME attachments"
vinoski authored
222 return(Model, ResHeader, [ResBody], ResCode, SessVal, Files);
223 return(Model, ResHeader, ResBody, ResCode, SessVal, Files) ->
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
224 %% add envelope
225 Header2 = case ResHeader of
0be3c7e @klacke untabified all of yaws
authored
226 undefined -> undefined;
227 _ -> #'soap:Header'{choice = ResHeader}
228 end,
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
229 Envelope = #'soap:Envelope'{'Body' = #'soap:Body'{choice = ResBody},
0be3c7e @klacke untabified all of yaws
authored
230 'Header' = Header2},
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
231 case catch erlsom:write(Envelope, Model) of
0be3c7e @klacke untabified all of yaws
authored
232 {ok, XmlDoc} ->
b6e60f0 @vinoski revert "remove support for SOAP DIME attachments"
vinoski authored
233 case Files of
234 undefined ->
235 {ok, XmlDoc, ResCode, SessVal};
236 _ ->
237 DIME = yaws_dime:encode(XmlDoc, Files),
238 {ok, DIME, ResCode, SessVal}
239 end;
0be3c7e @klacke untabified all of yaws
authored
240 {error, WriteError} ->
241 srv_error(f("Error writing XML: ~p", [WriteError]));
242 OtherWriteError ->
455578a @vinoski major trailing whitespace cleanup
vinoski authored
243 error_logger:error_msg("~p(~p): OtherWriteError=~p~n",
0be3c7e @klacke untabified all of yaws
authored
244 [?MODULE, ?LINE, OtherWriteError]),
245 srv_error(f("Error writing XML: ~p", [OtherWriteError]))
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
246 end.
247
248 f(S,A) -> lists:flatten(io_lib:format(S,A)).
249
455578a @vinoski major trailing whitespace cleanup
vinoski authored
250 cli_error(Error) ->
251 error_logger:error_msg("~p(~p): Cli Error: ~p~n",
0be3c7e @klacke untabified all of yaws
authored
252 [?MODULE, ?LINE, Error]),
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
253 Fault = yaws_soap_lib:makeFault("Client", "Client error"),
254 {error, Fault, ?BAD_MESSAGE_CODE}.
255
455578a @vinoski major trailing whitespace cleanup
vinoski authored
256 srv_error(Error) ->
257 error_logger:error_msg("~p(~p): Srv Error: ~p~n",
0be3c7e @klacke untabified all of yaws
authored
258 [?MODULE, ?LINE, Error]),
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
259 Fault = yaws_soap_lib:makeFault("Server", "Server error"),
260 {error, Fault, ?SERVER_ERROR_CODE}.
0be3c7e @klacke untabified all of yaws
authored
261
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
262
263
264
265 get_model(State, Id) ->
266 case lists:keysearch(Id, 1, State#s.wsdl_list) of
0be3c7e @klacke untabified all of yaws
authored
267 {value, {_, Model}} -> {ok, Model};
268 _ -> {error, "model not found"}
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
269 end.
270
271 uinsert({K,_} = E, [{K,_}|T]) -> [E|T];
272 uinsert(E, [H|T]) -> [H|uinsert(E,T)];
273 uinsert(E, []) -> [E].
Something went wrong with that request. Please try again.