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;

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 };

template (value) HeaderLines ts_HTTP_Header(charstring body, charstring host) := {
	{ header_name := "Host", header_value := host },
	{ header_name := "Content-Type", header_value := "application/json" },
	{ header_name := "Content-Length", header_value := int2str(lengthof(body)) }
}

template (value) HTTPMessage ts_HTTP_Req(charstring url,
					 charstring method := "GET",
					 charstring body := "",
					 integer v_maj := 1, integer v_min := 1,
					 charstring host) := {
	request := {
		client_id := omit,
		method := method,
		uri := url,
		version_major := v_maj,
		version_minor := v_min,
		header := valueof(ts_HTTP_Header(body, host)),
		body := 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", charstring body := "")
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)));
}

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",
			 charstring body := "", template HTTPMessage exp := tr_HTTP_Resp2xx,
			 float tout := 2.0)
runs on http_CT return HTTPMessage {
	f_http_tx_request(url, method, body);
	return f_http_rx_response(exp, tout);
}

}
