Comparison

mod_rest/mod_rest.lua @ 3930:d5dafd617cd6

mod_rest: Break out POST errors into a registry
author Kim Alvefur <zash@zash.se>
date Sat, 07 Mar 2020 17:34:17 +0100
parent 3929:bd687d586a8a
child 3931:2e8b284ac8b3
comparison
equal deleted inserted replaced
3929:bd687d586a8a 3930:d5dafd617cd6
113 return s:get_child_text("body") or ""; 113 return s:get_child_text("body") or "";
114 end 114 end
115 return tostring(s); 115 return tostring(s);
116 end 116 end
117 117
118 local post_errors = {
119 parse = { code = 400, condition = "not-well-formed", text = "Failed to parse payload", },
120 xmlns = { code = 422, condition = "invalid-namespace", text = "'xmlns' attribute must be empty", },
121 name = { code = 422, condition = "unsupported-stanza-type", text = "Invalid stanza, must be 'message', 'presence' or 'iq'.", },
122 to = { code = 422, condition = "improper-addressing", text = "Invalid destination JID", },
123 from = { code = 422, condition = "invalid-from", text = "Invalid source JID", },
124 post_auth = { code = 403, condition = "not-authorized", text = "Not authorized to send stanza with requested 'from'", },
125 iq_type = { code = 422, condition = "invalid-xml", text = "'iq' stanza must be of type 'get' or 'set'", },
126 iq_tags = { code = 422, condition = "bad-format", text = "'iq' stanza must have exactly one child tag", },
127 };
128
118 local function handle_post(event) 129 local function handle_post(event)
119 local request, response = event.request, event.response; 130 local request, response = event.request, event.response;
120 local from; 131 local from;
121 local origin; 132 local origin;
122 133
131 from = jid.join(origin.username, origin.host, origin.resource); 142 from = jid.join(origin.username, origin.host, origin.resource);
132 end 143 end
133 local payload, err = parse(request.headers.content_type, request.body); 144 local payload, err = parse(request.headers.content_type, request.body);
134 if not payload then 145 if not payload then
135 -- parse fail 146 -- parse fail
136 return errors.new({ code = 400, text = "Failed to parse payload" }, { error = err, type = request.headers.content_type, data = request.body }); 147 return errors.new("parse", { error = err, type = request.headers.content_type, data = request.body, }, post_errors);
137 end 148 end
138 if payload.attr.xmlns then 149 if payload.attr.xmlns then
139 return errors.new({ code = 422, text = "'xmlns' attribute must be empty" }); 150 return errors.new("xmlns", nil, post_errors);
140 elseif payload.name ~= "message" and payload.name ~= "presence" and payload.name ~= "iq" then 151 elseif payload.name ~= "message" and payload.name ~= "presence" and payload.name ~= "iq" then
141 return errors.new({ code = 422, text = "Invalid stanza, must be 'message', 'presence' or 'iq'." }); 152 return errors.new("name", nil, post_errors);
142 end 153 end
143 local to = jid.prep(payload.attr.to); 154 local to = jid.prep(payload.attr.to);
144 if not to then 155 if not to then
145 return errors.new({ code = 422, text = "Invalid destination JID" }); 156 return errors.new("to", nil, post_errors);
146 end 157 end
147 if payload.attr.from then 158 if payload.attr.from then
148 local requested_from = jid.prep(payload.attr.from); 159 local requested_from = jid.prep(payload.attr.from);
149 if not requested_from then 160 if not requested_from then
150 return errors.new({ code = 422, text = "Invalid source JID" }); 161 return errors.new("from", nil, post_errors);
151 end 162 end
152 if jid.compare(requested_from, from) then 163 if jid.compare(requested_from, from) then
153 from = requested_from; 164 from = requested_from;
154 else 165 else
155 return errors.new({ code = 403, text = "Not authorized to send from "..requested_from }); 166 return errors.new("from_auth", nil, post_errors);
156 end 167 end
157 end 168 end
158 payload.attr = { 169 payload.attr = {
159 from = from, 170 from = from,
160 to = to, 171 to = to,
167 if payload.name == "iq" then 178 if payload.name == "iq" then
168 function origin.send(stanza) 179 function origin.send(stanza)
169 module:send(stanza); 180 module:send(stanza);
170 end 181 end
171 if payload.attr.type ~= "get" and payload.attr.type ~= "set" then 182 if payload.attr.type ~= "get" and payload.attr.type ~= "set" then
172 return errors.new({ code = 422, text = "'iq' stanza must be of type 'get' or 'set'" }); 183 return errors.new("iq_type", nil, post_errors);
173 elseif #payload.tags ~= 1 then 184 elseif #payload.tags ~= 1 then
174 return errors.new({ code = 422, text = "'iq' stanza must have exactly one child tag" }); 185 return errors.new("iq_tags", nil, post_errors);
175 end 186 end
176 return module:send_iq(payload, origin):next( 187 return module:send_iq(payload, origin):next(
177 function (result) 188 function (result)
178 module:log("debug", "Sending[rest]: %s", result.stanza:top_tag()); 189 module:log("debug", "Sending[rest]: %s", result.stanza:top_tag());
179 response.headers.content_type = send_type; 190 response.headers.content_type = send_type;