blob: 9ad1e4abfe6f94ee97dac849dd93a8760a8afffb [file] [log] [blame]
module HTTP_Adapter {
/* HTTP Adapter component, originally part of Integration Tests for osmo-remsim-server
* (C) 2019 by Harald Welte <laforge@gnumonks.org>
* All rights reserved.
*
* Released under the terms of GNU General Public License, Version 2 or
* (at your option) any later version.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This test suite tests osmo-remsim-server by attaching to the external interfaces
* such as RSPRO for simulated clients + bankds and RSRES (REST backend interface).
*/
import from HTTPmsg_Types all;
import from HTTPmsg_PortType all;
import from Native_Functions all;
type component http_CT {
port HTTPmsg_PT HTTP;
var charstring g_http_host;
var integer g_http_port;
};
function f_http_init(charstring host, integer http_port) runs on http_CT {
map(self:HTTP, system:HTTP);
g_http_host := host;
g_http_port := http_port;
}
template (value) Connect ts_HTTP_Connect(template (value) charstring hostname,
template (value) integer http_port := 80,
template (value) boolean use_ssl := false) := {
hostname := hostname,
portnumber := http_port,
use_ssl := use_ssl
}
template (value) Close ts_HTTP_Close := { client_id := omit };
/* function to add HeaderLines to a an existing set of HeaderLines. HeaderLines that are already present, are updated. */
function f_overlay_HTTP_Header(HeaderLines hdr, HeaderLines additional_hdr) return template (value) HeaderLines
{
var integer i;
var integer k;
var boolean updated;
for (i := 0; i < lengthof(additional_hdr); i := i+1) {
updated := false;
for (k := 0; k < lengthof(hdr); k := k+1) {
if (f_str_tolower(hdr[k].header_name) == f_str_tolower(additional_hdr[i].header_name)) {
hdr[k] := additional_hdr[i];
updated := true;
}
}
if (updated == false) {
hdr := hdr & { additional_hdr[i] };
}
}
return hdr;
}
template (value) HeaderLine ts_HeaderLine(charstring header_name, charstring header_value) := {
header_name := header_name,
header_value := header_value
}
function f_ts_HTTP_Header(template (omit) charstring body := omit,
template (omit) charstring host := omit,
HeaderLines custom_hdr := { })
return template (value) HeaderLines {
var HeaderLines hdr := { };
/* Build default header */
if (not istemplatekind(host, "omit")) {
hdr := hdr & {valueof(ts_HeaderLine("Host", valueof(host)))};
}
hdr := hdr & {{ header_name := "Content-Type", header_value := "application/json" }};
if (not istemplatekind(body, "omit")) {
hdr := hdr & {valueof(ts_HeaderLine("Content-Length", int2str(lengthof(body))))};
}
return f_overlay_HTTP_Header(hdr, custom_hdr);
}
function f_ts_body_or_empty(template (omit) charstring body) return template (value) charstring {
if (istemplatekind(body, "omit")) {
return "";
}
return body;
}
template (value) HTTPMessage ts_HTTP_Req(charstring url,
charstring method := "GET",
template (omit) charstring body := omit,
integer v_maj := 1, integer v_min := 1,
charstring host,
HeaderLines custom_hdr := { }) := {
request := {
client_id := omit,
method := method,
uri := url,
version_major := v_maj,
version_minor := v_min,
header := f_ts_HTTP_Header(body, host, custom_hdr),
body := f_ts_body_or_empty(body)
}
}
template HTTPMessage tr_HTTP_Resp(template integer sts := ?) := {
response := {
client_id := ?,
version_major := ?,
version_minor := ?,
statuscode := sts,
statustext := ?,
header := ?,
body := ?
}
};
template HTTPMessage tr_HTTP_Resp2xx := tr_HTTP_Resp((200..299));
function f_http_tx_request(charstring url, charstring method := "GET", template charstring body := omit,
HeaderLines custom_hdr := { })
runs on http_CT {
HTTP.send(ts_HTTP_Connect(g_http_host, g_http_port));
HTTP.receive(Connect_result:?);
HTTP.send(ts_HTTP_Req(url, method, body, host := g_http_host & ":" & int2str(g_http_port), custom_hdr := custom_hdr));
}
function f_http_rx_response(template HTTPMessage exp := tr_HTTP_Resp2xx, float tout := 2.0)
runs on http_CT return HTTPMessage {
var HTTPMessage resp;
timer T := tout;
T.start;
alt {
[] HTTP.receive(exp) -> value resp {
setverdict(pass);
}
[] HTTP.receive(tr_HTTP_Resp) -> value resp {
setverdict(fail, "Unexpected HTTP response ", resp);
}
[] T.timeout {
setverdict(fail, "Timeout waiting for HTTP response");
self.stop;
}
}
HTTP.send(ts_HTTP_Close);
return resp;
}
/* run a HTTP request and return the response */
function f_http_transact(charstring url, charstring method := "GET",
template (omit) charstring body := omit, template HTTPMessage exp := tr_HTTP_Resp2xx,
float tout := 2.0, HeaderLines custom_hdr := { })
runs on http_CT return HTTPMessage {
f_http_tx_request(url, method, body, custom_hdr);
return f_http_rx_response(exp, tout);
}
}