request headers support in HTTPHandler v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Tue, 15 Mar 2022 01:47:05 +0100
branchv_0
changeset 8 3f4e60990393
parent 7 0b0374746e48
child 9 9fdbfbe24161
request headers support in HTTPHandler
src/HTTPHandler.h
--- a/src/HTTPHandler.h	Sun Mar 13 20:50:25 2022 +0100
+++ b/src/HTTPHandler.h	Tue Mar 15 01:47:05 2022 +0100
@@ -44,18 +44,29 @@
 
 class HTTPHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
 private:
+
+	class HeaderDefinition {
+	public:
+		// TODO: filters/patterns/condition
+		relpipe::common::type::StringX name;
+		relpipe::common::type::StringX value;
+	};
+
 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
 	shared_ptr<relpipe::writer::RelationalWriter> relationalWriter;
 	Configuration configuration;
+	relpipe::common::type::StringX currentRelationName;
 	std::vector<relpipe::reader::handlers::AttributeMetadata> currentReaderMetadata;
 	std::vector<relpipe::writer::AttributeMetadata> currentWriterMetadata;
+	HeaderDefinition requestHeader;
+	std::vector<HeaderDefinition> requestHeaders;
 	std::vector<relpipe::common::type::StringX> responseHeaders;
 	size_t currentAttributeIndex = 0;
 	size_t currentRecordNumber = 1;
 
 	void writeHeaders() {
 		if (responseHeaders.size()) {
-			relationalWriter->startRelation(L"response_header",{
+			relationalWriter->startRelation(L"header",{
 				// TODO: request ID instead of URL (or both)
 				{L"url", relpipe::writer::TypeId::STRING},
 				{L"name", relpipe::writer::TypeId::STRING},
@@ -77,29 +88,48 @@
 	}
 
 	void startRelation(relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
-
 		writeHeaders(); // from previous relation
 
-		relationalWriter->startRelation(name + L"_curl_info",{
-			{L"name", relpipe::writer::TypeId::STRING},
-			{L"value", relpipe::writer::TypeId::STRING}
-		}, true);
+		currentRelationName = name;
+		currentReaderMetadata = attributes;
 
-		relationalWriter->writeAttribute(L"curl version");
-		relationalWriter->writeAttribute(convertor.from_bytes(curl_version()));
+		if (currentRelationName == L"header") {
+			// TODO: analyze header attributes
+		} else if (currentRelationName == L"request") {
+			relationalWriter->startRelation(L"response",{
+				// TODO: request ID
+				// TODO: body in hexadecimal/binary format
+				{L"url", relpipe::writer::TypeId::STRING},
+				{L"body", relpipe::writer::TypeId::STRING},
+				{L"code", relpipe::writer::TypeId::INTEGER},
+			}, true);
+		}
+	}
 
-		relationalWriter->startRelation(name + L"_curl_response",{
-			// TODO: request ID
-			// TODO: body in hexadecimal/binary format
-			{L"url", relpipe::writer::TypeId::STRING},
-			{L"body", relpipe::writer::TypeId::STRING},
-			{L"response_code", relpipe::writer::TypeId::INTEGER},
-		}, true);
+	void attribute(const relpipe::common::type::StringX& value) override {
+		if (currentRelationName == L"header") headerAttribute(value);
+		else if (currentRelationName == L"request") requestAttribute(value);
+		else throw std::invalid_argument("Unsupported relation: " + convertor.to_bytes(currentRelationName));
+	}
+
+private:
+
+	void headerAttribute(const relpipe::common::type::StringX& value) {
+		if (currentReaderMetadata[currentAttributeIndex].getAttributeName() == L"name") requestHeader.name = value;
+		else if (currentReaderMetadata[currentAttributeIndex].getAttributeName() == L"value") requestHeader.value = value;
+		else throw std::invalid_argument("Unsupported attribute in the header relation: " + convertor.to_bytes(currentReaderMetadata[currentAttributeIndex].getAttributeName() + L" = " + value));
+
+		currentAttributeIndex++;
+
+		if (currentAttributeIndex % currentReaderMetadata.size() == 0) {
+			currentAttributeIndex = 0;
+			requestHeaders.push_back(requestHeader);
+			requestHeader = HeaderDefinition();
+		}
 
 	}
 
-	void attribute(const relpipe::common::type::StringX& value) override {
-
+	void requestAttribute(const relpipe::common::type::StringX& value) {
 		std::shared_ptr<HTTPClient> http(HTTPClient::open());
 
 		HTTPClient::Request request;
@@ -113,6 +143,10 @@
 		// request.headers.push_back("application/xml");
 		// request.headers.push_back("User-Agent");
 		// request.headers.push_back("curl/7.58.0");
+		for (const HeaderDefinition& h : requestHeaders) {
+			request.headers.push_back(convertor.to_bytes(h.name));
+			request.headers.push_back(convertor.to_bytes(h.value));
+		}
 
 		HTTPClient::Response response = http->exchange(request);
 		relpipe::common::type::Integer responseCode = response.responseCode;
@@ -128,6 +162,8 @@
 		}
 	}
 
+public:
+
 	void endOfPipe() {
 		writeHeaders(); // from last relation
 	}