Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 236 lines (197 sloc) 9.105 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
11 -export([start_link/0,
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 %%--------------------------------------------------------------------
43 start_link() ->
44 %% We are dependent on erlsom
45 case code:ensure_loaded(erlsom) of
0be3c7e @klacke untabified all of yaws
authored
46 {error, _} ->
47 Emsg = "could not load erlsom",
48 error_logger:error_msg("~p: exiting, reason: ~s~n",
49 [?MODULE, Emsg]),
50 {error, Emsg};
51 {module, erlsom} ->
52 gen_server:start_link({local, ?SERVER}, ?MODULE, [], [])
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
53 end.
54
55 %%% To be called from yaws_rpc.erl
56 %%% Return according to yaws_rpc:eval_payload/6
57 handler(Args, Id, Payload, SessionValue) ->
58 Headers = Args#arg.headers,
59 SoapAction = yaws_soap_lib:findHeader("SOAPAction", Headers#headers.other),
0be3c7e @klacke untabified all of yaws
authored
60 case gen_server:call(?SERVER, {request, Id, Payload,
61 SessionValue, SoapAction}) of
62 {ok, XmlDoc, ResCode, undefined} ->
63 {false, XmlDoc, ResCode};
64 {ok, XmlDoc, ResCode, SessVal} ->
65 {true, 0, SessVal, XmlDoc, ResCode};
66 {error, _, _} = Error ->
67 Error;
68 false ->
69 false % soap notify
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
70 end.
71
72 %% Setup a SOAP interface according to the config file.
49cbf48 @klacke nice cleanup patch from Rickard Bucker
authored
73 setup(_ConfigFile) ->
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
74 tbd.
75
76 setup(Id, WsdlFile) when tuple(Id),size(Id)==2 ->
77 Wsdl = yaws_soap_lib:initModel(WsdlFile),
78 gen_server:call(?SERVER, {add_wsdl, Id, Wsdl}).
0be3c7e @klacke untabified all of yaws
authored
79
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
80
81 setup(Id, WsdlFile, Prefix) when tuple(Id),size(Id)==2 ->
82 Wsdl = yaws_soap_lib:initModel(WsdlFile, Prefix),
83 gen_server:call(?SERVER, {add_wsdl, Id, Wsdl}).
0be3c7e @klacke untabified all of yaws
authored
84
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
85
86
87 %%====================================================================
88 %% gen_server callbacks
89 %%====================================================================
90
91 %%--------------------------------------------------------------------
92 %% Function: init(Args) -> {ok, State} |
93 %% {ok, State, Timeout} |
94 %% ignore |
95 %% {stop, Reason}
96 %% Description: Initiates the server
97 %%--------------------------------------------------------------------
98 init([]) ->
99 {ok, #s{}}.
100
101 %%--------------------------------------------------------------------
102 %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
103 %% {reply, Reply, State, Timeout} |
104 %% {noreply, State} |
105 %% {noreply, State, Timeout} |
106 %% {stop, Reason, Reply, State} |
107 %% {stop, Reason, State}
108 %% Description: Handling call messages
109 %%--------------------------------------------------------------------
110 handle_call({add_wsdl, Id, WsdlModel}, _From, State) ->
111 NewWsdlList = uinsert({Id, WsdlModel}, State#s.wsdl_list),
112 {reply, ok, State#s{wsdl_list = NewWsdlList}};
113 %%
114 handle_call( {request, Id, Payload, SessionValue, SoapAction}, _From, State) ->
115 Reply = request(State, Id, Payload, SessionValue, SoapAction),
116 {reply, Reply, State}.
117
118 %%--------------------------------------------------------------------
119 %% Function: handle_cast(Msg, State) -> {noreply, State} |
120 %% {noreply, State, Timeout} |
121 %% {stop, Reason, State}
122 %% Description: Handling cast messages
123 %%--------------------------------------------------------------------
124 handle_cast(_Msg, State) ->
125 {noreply, State}.
126
127 %%--------------------------------------------------------------------
128 %% Function: handle_info(Info, State) -> {noreply, State} |
129 %% {noreply, State, Timeout} |
130 %% {stop, Reason, State}
131 %% Description: Handling all non call/cast messages
132 %%--------------------------------------------------------------------
133 handle_info(_Info, State) ->
134 {noreply, State}.
135
136 %%--------------------------------------------------------------------
137 %% Function: terminate(Reason, State) -> void()
138 %% Description: This function is called by a gen_server when it is about to
139 %% terminate. It should be the opposite of Module:init/1 and do any necessary
140 %% cleaning up. When it returns, the gen_server terminates with Reason.
141 %% The return value is ignored.
142 %%--------------------------------------------------------------------
143 terminate(_Reason, _State) ->
144 ok.
145
146 %%--------------------------------------------------------------------
147 %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
148 %% Description: Convert process state when code is changed
149 %%--------------------------------------------------------------------
150 code_change(_OldVsn, State, _Extra) ->
151 {ok, State}.
152
153 %%--------------------------------------------------------------------
154 %%% Internal functions
155 %%--------------------------------------------------------------------
156
157 request(State, {M,F} = Id, Payload, SessionValue, Action) ->
158 {ok, Model} = get_model(State, Id),
159 Umsg = (catch erlsom_lib:toUnicode(Payload)),
160 case catch yaws_soap_lib:parseMessage(Umsg, Model) of
0be3c7e @klacke untabified all of yaws
authored
161 {ok, Header, Body} ->
162 %% call function
163 result(Model, catch apply(M, F, [Header, Body,
164 Action, SessionValue]));
165 {error, Error} ->
166 cli_error(Error);
167 OtherError ->
168 srv_error(io_lib:format("Error parsing message: ~p", [OtherError]))
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
169 end.
170
171 %%% Analyse the result and produce some output
172 result(Model, {ok, ResHeader, ResBody, ResCode, SessVal}) ->
173 return(Model, ResHeader, ResBody, ResCode, SessVal);
174 result(Model, {ok, ResHeader, ResBody}) ->
175 return(Model, ResHeader, ResBody, ?OK_CODE, undefined);
176 result(_Model, {error, client, ClientMssg}) ->
177 cli_error(ClientMssg);
178 result(_Model, false) -> % soap notify !
179 false;
180 result(_Model, Error) ->
181 srv_error(io_lib:format("Error processing message: ~p", [Error])).
182
183 return(#wsdl{model = Model}, ResHeader, ResBody, ResCode, SessVal) ->
184 return(Model, ResHeader, ResBody, ResCode, SessVal);
185 return(Model, ResHeader, ResBody, ResCode, SessVal) when not is_list(ResBody) ->
186 return(Model, ResHeader, [ResBody], ResCode, SessVal);
187 return(Model, ResHeader, ResBody, ResCode, SessVal) ->
188 %% add envelope
189 Header2 = case ResHeader of
0be3c7e @klacke untabified all of yaws
authored
190 undefined -> undefined;
191 _ -> #'soap:Header'{choice = ResHeader}
192 end,
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
193 Envelope = #'soap:Envelope'{'Body' = #'soap:Body'{choice = ResBody},
0be3c7e @klacke untabified all of yaws
authored
194 'Header' = Header2},
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
195 case catch erlsom:write(Envelope, Model) of
0be3c7e @klacke untabified all of yaws
authored
196 {ok, XmlDoc} ->
197 {ok, XmlDoc, ResCode, SessVal};
198 {error, WriteError} ->
199 srv_error(f("Error writing XML: ~p", [WriteError]));
200 OtherWriteError ->
201 error_logger:error_msg("~p(~p): OtherWriteError=~p~n",
202 [?MODULE, ?LINE, OtherWriteError]),
203 srv_error(f("Error writing XML: ~p", [OtherWriteError]))
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
204 end.
205
206 f(S,A) -> lists:flatten(io_lib:format(S,A)).
207
208 cli_error(Error) ->
209 error_logger:error_msg("~p(~p): Cli Error: ~p~n",
0be3c7e @klacke untabified all of yaws
authored
210 [?MODULE, ?LINE, Error]),
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
211 Fault = yaws_soap_lib:makeFault("Client", "Client error"),
212 {error, Fault, ?BAD_MESSAGE_CODE}.
213
214 srv_error(Error) ->
215 error_logger:error_msg("~p(~p): Srv Error: ~p~n",
0be3c7e @klacke untabified all of yaws
authored
216 [?MODULE, ?LINE, Error]),
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
217 Fault = yaws_soap_lib:makeFault("Server", "Server error"),
218 {error, Fault, ?SERVER_ERROR_CODE}.
0be3c7e @klacke untabified all of yaws
authored
219
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
220
221
222
223 get_model(State, Id) ->
224 case lists:keysearch(Id, 1, State#s.wsdl_list) of
0be3c7e @klacke untabified all of yaws
authored
225 {value, {_, Model}} -> {ok, Model};
226 _ -> {error, "model not found"}
c332fc2 Adding SOAP processing capabilities to Yaws.
Tobbe Tornquist authored
227 end.
228
229 uinsert({K,_} = E, [{K,_}|T]) -> [E|T];
230 uinsert(E, [H|T]) -> [H|uinsert(E,T)];
231 uinsert(E, []) -> [E].
232
233
234
235
Something went wrong with that request. Please try again.