Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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 whi…
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 whi…
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 whi…
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 whi…
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.