blob: c06aa38835363eb8c4cc477d1883a1e79cf4cf5c [file] [log] [blame]
Harald Welte55e879c2021-02-19 13:16:28 +01001module HTTP_Adapter {
2
3/* HTTP Adapter component, originally part of Integration Tests for osmo-remsim-server
4 * (C) 2019 by Harald Welte <laforge@gnumonks.org>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
12 * This test suite tests osmo-remsim-server by attaching to the external interfaces
13 * such as RSPRO for simulated clients + bankds and RSRES (REST backend interface).
14 */
15
16import from HTTPmsg_Types all;
17import from HTTPmsg_PortType all;
Philipp Maier6406e6d2024-03-26 13:37:11 +010018import from Native_Functions all;
Harald Welte55e879c2021-02-19 13:16:28 +010019
20type component http_CT {
21 port HTTPmsg_PT HTTP;
Philipp Maier260f7082024-04-19 13:12:49 +020022 var HTTP_Adapter_Params g_pars;
Harald Welte55e879c2021-02-19 13:16:28 +010023};
24
Philipp Maier260f7082024-04-19 13:12:49 +020025type record HTTP_Adapter_Params {
26 charstring http_host,
27 integer http_port
28};
29
30function f_http_init(HTTP_Adapter_Params pars) runs on http_CT {
Harald Welte55e879c2021-02-19 13:16:28 +010031 map(self:HTTP, system:HTTP);
Philipp Maier260f7082024-04-19 13:12:49 +020032 g_pars := pars;
Harald Welte55e879c2021-02-19 13:16:28 +010033}
34
35template (value) Connect ts_HTTP_Connect(template (value) charstring hostname,
36 template (value) integer http_port := 80,
37 template (value) boolean use_ssl := false) := {
38 hostname := hostname,
39 portnumber := http_port,
40 use_ssl := use_ssl
41}
42template (value) Close ts_HTTP_Close := { client_id := omit };
43
Philipp Maier6406e6d2024-03-26 13:37:11 +010044/* function to add HeaderLines to a an existing set of HeaderLines. HeaderLines that are already present, are updated. */
45function f_overlay_HTTP_Header(HeaderLines hdr, HeaderLines additional_hdr) return template (value) HeaderLines
46{
47 var integer i;
48 var integer k;
49 var boolean updated;
50
51 for (i := 0; i < lengthof(additional_hdr); i := i+1) {
52 updated := false;
53 for (k := 0; k < lengthof(hdr); k := k+1) {
54 if (f_str_tolower(hdr[k].header_name) == f_str_tolower(additional_hdr[i].header_name)) {
55 hdr[k] := additional_hdr[i];
56 updated := true;
57 }
58 }
59 if (updated == false) {
60 hdr := hdr & { additional_hdr[i] };
61 }
62 }
63
64 return hdr;
65}
66
67template (value) HeaderLine ts_HeaderLine(charstring header_name, charstring header_value) := {
68 header_name := header_name,
69 header_value := header_value
70}
71
72function f_ts_HTTP_Header(template (omit) charstring body := omit,
73 template (omit) charstring host := omit,
74 HeaderLines custom_hdr := { })
75return template (value) HeaderLines {
76 var HeaderLines hdr := { };
77
78 /* Build default header */
79 if (not istemplatekind(host, "omit")) {
80 hdr := hdr & {valueof(ts_HeaderLine("Host", valueof(host)))};
81 }
82 hdr := hdr & {{ header_name := "Content-Type", header_value := "application/json" }};
83 if (not istemplatekind(body, "omit")) {
84 hdr := hdr & {valueof(ts_HeaderLine("Content-Length", int2str(lengthof(body))))};
85 }
86
87 return f_overlay_HTTP_Header(hdr, custom_hdr);
Harald Welte55e879c2021-02-19 13:16:28 +010088}
89
Philipp Maieref20fa02024-03-26 15:50:22 +010090function f_ts_body_or_empty(template (omit) charstring body) return template (value) charstring {
91 if (istemplatekind(body, "omit")) {
92 return "";
93 }
94 return body;
95}
96
Harald Welte55e879c2021-02-19 13:16:28 +010097template (value) HTTPMessage ts_HTTP_Req(charstring url,
98 charstring method := "GET",
Philipp Maieref20fa02024-03-26 15:50:22 +010099 template (omit) charstring body := omit,
Philipp Maier4a19b472024-03-25 15:08:43 +0100100 integer v_maj := 1, integer v_min := 1,
Philipp Maier6406e6d2024-03-26 13:37:11 +0100101 charstring host,
102 HeaderLines custom_hdr := { }) := {
Harald Welte55e879c2021-02-19 13:16:28 +0100103 request := {
104 client_id := omit,
105 method := method,
106 uri := url,
107 version_major := v_maj,
108 version_minor := v_min,
Philipp Maieref20fa02024-03-26 15:50:22 +0100109 header := f_ts_HTTP_Header(body, host, custom_hdr),
110 body := f_ts_body_or_empty(body)
Harald Welte55e879c2021-02-19 13:16:28 +0100111 }
112}
113
114template HTTPMessage tr_HTTP_Resp(template integer sts := ?) := {
115 response := {
116 client_id := ?,
117 version_major := ?,
118 version_minor := ?,
119 statuscode := sts,
120 statustext := ?,
121 header := ?,
122 body := ?
123 }
124};
125
126template HTTPMessage tr_HTTP_Resp2xx := tr_HTTP_Resp((200..299));
127
Philipp Maieref20fa02024-03-26 15:50:22 +0100128function f_http_tx_request(charstring url, charstring method := "GET", template charstring body := omit,
Philipp Maier6406e6d2024-03-26 13:37:11 +0100129 HeaderLines custom_hdr := { })
Harald Welte205b5372021-02-22 09:16:21 +0100130runs on http_CT {
Philipp Maier260f7082024-04-19 13:12:49 +0200131 HTTP.send(ts_HTTP_Connect(g_pars.http_host, g_pars.http_port));
Harald Welte205b5372021-02-22 09:16:21 +0100132 HTTP.receive(Connect_result:?);
Philipp Maier260f7082024-04-19 13:12:49 +0200133 HTTP.send(ts_HTTP_Req(url, method, body, host := g_pars.http_host & ":" & int2str(g_pars.http_port), custom_hdr := custom_hdr));
Harald Welte205b5372021-02-22 09:16:21 +0100134}
135
136function f_http_rx_response(template HTTPMessage exp := tr_HTTP_Resp2xx, float tout := 2.0)
Harald Welte55e879c2021-02-19 13:16:28 +0100137runs on http_CT return HTTPMessage {
138 var HTTPMessage resp;
Harald Weltead9d8362021-02-22 10:23:00 +0100139 timer T := tout;
Harald Welte55e879c2021-02-19 13:16:28 +0100140 T.start;
141 alt {
142 [] HTTP.receive(exp) -> value resp {
143 setverdict(pass);
144 }
145 [] HTTP.receive(tr_HTTP_Resp) -> value resp {
146 setverdict(fail, "Unexpected HTTP response ", resp);
147 }
148 [] T.timeout {
149 setverdict(fail, "Timeout waiting for HTTP response");
150 self.stop;
151 }
152 }
153 HTTP.send(ts_HTTP_Close);
154 return resp;
155}
156
Harald Welte205b5372021-02-22 09:16:21 +0100157/* run a HTTP request and return the response */
158function f_http_transact(charstring url, charstring method := "GET",
Philipp Maieref20fa02024-03-26 15:50:22 +0100159 template (omit) charstring body := omit, template HTTPMessage exp := tr_HTTP_Resp2xx,
Philipp Maier6406e6d2024-03-26 13:37:11 +0100160 float tout := 2.0, HeaderLines custom_hdr := { })
Harald Welte205b5372021-02-22 09:16:21 +0100161runs on http_CT return HTTPMessage {
Philipp Maier6406e6d2024-03-26 13:37:11 +0100162 f_http_tx_request(url, method, body, custom_hdr);
Harald Welte205b5372021-02-22 09:16:21 +0100163 return f_http_rx_response(exp, tout);
164}
165
Harald Welte55e879c2021-02-19 13:16:28 +0100166}