blob: b302a80d02df31dc172ff6f73e2a34380a4c91cb [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;
22 var charstring g_http_host;
23 var integer g_http_port;
24};
25
26function f_http_init(charstring host, integer http_port) runs on http_CT {
27 map(self:HTTP, system:HTTP);
28 g_http_host := host;
29 g_http_port := http_port;
30}
31
32template (value) Connect ts_HTTP_Connect(template (value) charstring hostname,
33 template (value) integer http_port := 80,
34 template (value) boolean use_ssl := false) := {
35 hostname := hostname,
36 portnumber := http_port,
37 use_ssl := use_ssl
38}
39template (value) Close ts_HTTP_Close := { client_id := omit };
40
Philipp Maier6406e6d2024-03-26 13:37:11 +010041/* function to add HeaderLines to a an existing set of HeaderLines. HeaderLines that are already present, are updated. */
42function f_overlay_HTTP_Header(HeaderLines hdr, HeaderLines additional_hdr) return template (value) HeaderLines
43{
44 var integer i;
45 var integer k;
46 var boolean updated;
47
48 for (i := 0; i < lengthof(additional_hdr); i := i+1) {
49 updated := false;
50 for (k := 0; k < lengthof(hdr); k := k+1) {
51 if (f_str_tolower(hdr[k].header_name) == f_str_tolower(additional_hdr[i].header_name)) {
52 hdr[k] := additional_hdr[i];
53 updated := true;
54 }
55 }
56 if (updated == false) {
57 hdr := hdr & { additional_hdr[i] };
58 }
59 }
60
61 return hdr;
62}
63
64template (value) HeaderLine ts_HeaderLine(charstring header_name, charstring header_value) := {
65 header_name := header_name,
66 header_value := header_value
67}
68
69function f_ts_HTTP_Header(template (omit) charstring body := omit,
70 template (omit) charstring host := omit,
71 HeaderLines custom_hdr := { })
72return template (value) HeaderLines {
73 var HeaderLines hdr := { };
74
75 /* Build default header */
76 if (not istemplatekind(host, "omit")) {
77 hdr := hdr & {valueof(ts_HeaderLine("Host", valueof(host)))};
78 }
79 hdr := hdr & {{ header_name := "Content-Type", header_value := "application/json" }};
80 if (not istemplatekind(body, "omit")) {
81 hdr := hdr & {valueof(ts_HeaderLine("Content-Length", int2str(lengthof(body))))};
82 }
83
84 return f_overlay_HTTP_Header(hdr, custom_hdr);
Harald Welte55e879c2021-02-19 13:16:28 +010085}
86
87template (value) HTTPMessage ts_HTTP_Req(charstring url,
88 charstring method := "GET",
89 charstring body := "",
Philipp Maier4a19b472024-03-25 15:08:43 +010090 integer v_maj := 1, integer v_min := 1,
Philipp Maier6406e6d2024-03-26 13:37:11 +010091 charstring host,
92 HeaderLines custom_hdr := { }) := {
Harald Welte55e879c2021-02-19 13:16:28 +010093 request := {
94 client_id := omit,
95 method := method,
96 uri := url,
97 version_major := v_maj,
98 version_minor := v_min,
Philipp Maier6406e6d2024-03-26 13:37:11 +010099 header := valueof(f_ts_HTTP_Header(body, host, custom_hdr)),
Harald Welte55e879c2021-02-19 13:16:28 +0100100 body := body
101 }
102}
103
104template HTTPMessage tr_HTTP_Resp(template integer sts := ?) := {
105 response := {
106 client_id := ?,
107 version_major := ?,
108 version_minor := ?,
109 statuscode := sts,
110 statustext := ?,
111 header := ?,
112 body := ?
113 }
114};
115
116template HTTPMessage tr_HTTP_Resp2xx := tr_HTTP_Resp((200..299));
117
Philipp Maier6406e6d2024-03-26 13:37:11 +0100118function f_http_tx_request(charstring url, charstring method := "GET", charstring body := "",
119 HeaderLines custom_hdr := { })
Harald Welte205b5372021-02-22 09:16:21 +0100120runs on http_CT {
121 HTTP.send(ts_HTTP_Connect(g_http_host, g_http_port));
122 HTTP.receive(Connect_result:?);
Philipp Maier6406e6d2024-03-26 13:37:11 +0100123 HTTP.send(ts_HTTP_Req(url, method, body, host := g_http_host & ":" & int2str(g_http_port), custom_hdr := custom_hdr));
Harald Welte205b5372021-02-22 09:16:21 +0100124}
125
126function f_http_rx_response(template HTTPMessage exp := tr_HTTP_Resp2xx, float tout := 2.0)
Harald Welte55e879c2021-02-19 13:16:28 +0100127runs on http_CT return HTTPMessage {
128 var HTTPMessage resp;
Harald Weltead9d8362021-02-22 10:23:00 +0100129 timer T := tout;
Harald Welte55e879c2021-02-19 13:16:28 +0100130 T.start;
131 alt {
132 [] HTTP.receive(exp) -> value resp {
133 setverdict(pass);
134 }
135 [] HTTP.receive(tr_HTTP_Resp) -> value resp {
136 setverdict(fail, "Unexpected HTTP response ", resp);
137 }
138 [] T.timeout {
139 setverdict(fail, "Timeout waiting for HTTP response");
140 self.stop;
141 }
142 }
143 HTTP.send(ts_HTTP_Close);
144 return resp;
145}
146
Harald Welte205b5372021-02-22 09:16:21 +0100147/* run a HTTP request and return the response */
148function f_http_transact(charstring url, charstring method := "GET",
149 charstring body := "", template HTTPMessage exp := tr_HTTP_Resp2xx,
Philipp Maier6406e6d2024-03-26 13:37:11 +0100150 float tout := 2.0, HeaderLines custom_hdr := { })
Harald Welte205b5372021-02-22 09:16:21 +0100151runs on http_CT return HTTPMessage {
Philipp Maier6406e6d2024-03-26 13:37:11 +0100152 f_http_tx_request(url, method, body, custom_hdr);
Harald Welte205b5372021-02-22 09:16:21 +0100153 return f_http_rx_response(exp, tout);
154}
155
Harald Welte55e879c2021-02-19 13:16:28 +0100156}