src/HTTPHandler.h
branchv_0
changeset 8 3f4e60990393
parent 7 0b0374746e48
child 9 9fdbfbe24161
equal deleted inserted replaced
7:0b0374746e48 8:3f4e60990393
    42 namespace tr {
    42 namespace tr {
    43 namespace http {
    43 namespace http {
    44 
    44 
    45 class HTTPHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
    45 class HTTPHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
    46 private:
    46 private:
       
    47 
       
    48 	class HeaderDefinition {
       
    49 	public:
       
    50 		// TODO: filters/patterns/condition
       
    51 		relpipe::common::type::StringX name;
       
    52 		relpipe::common::type::StringX value;
       
    53 	};
       
    54 
    47 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
    55 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
    48 	shared_ptr<relpipe::writer::RelationalWriter> relationalWriter;
    56 	shared_ptr<relpipe::writer::RelationalWriter> relationalWriter;
    49 	Configuration configuration;
    57 	Configuration configuration;
       
    58 	relpipe::common::type::StringX currentRelationName;
    50 	std::vector<relpipe::reader::handlers::AttributeMetadata> currentReaderMetadata;
    59 	std::vector<relpipe::reader::handlers::AttributeMetadata> currentReaderMetadata;
    51 	std::vector<relpipe::writer::AttributeMetadata> currentWriterMetadata;
    60 	std::vector<relpipe::writer::AttributeMetadata> currentWriterMetadata;
       
    61 	HeaderDefinition requestHeader;
       
    62 	std::vector<HeaderDefinition> requestHeaders;
    52 	std::vector<relpipe::common::type::StringX> responseHeaders;
    63 	std::vector<relpipe::common::type::StringX> responseHeaders;
    53 	size_t currentAttributeIndex = 0;
    64 	size_t currentAttributeIndex = 0;
    54 	size_t currentRecordNumber = 1;
    65 	size_t currentRecordNumber = 1;
    55 
    66 
    56 	void writeHeaders() {
    67 	void writeHeaders() {
    57 		if (responseHeaders.size()) {
    68 		if (responseHeaders.size()) {
    58 			relationalWriter->startRelation(L"response_header",{
    69 			relationalWriter->startRelation(L"header",{
    59 				// TODO: request ID instead of URL (or both)
    70 				// TODO: request ID instead of URL (or both)
    60 				{L"url", relpipe::writer::TypeId::STRING},
    71 				{L"url", relpipe::writer::TypeId::STRING},
    61 				{L"name", relpipe::writer::TypeId::STRING},
    72 				{L"name", relpipe::writer::TypeId::STRING},
    62 				{L"value", relpipe::writer::TypeId::STRING},
    73 				{L"value", relpipe::writer::TypeId::STRING},
    63 			}, true);
    74 			}, true);
    75 
    86 
    76 	virtual ~HTTPHandler() {
    87 	virtual ~HTTPHandler() {
    77 	}
    88 	}
    78 
    89 
    79 	void startRelation(relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
    90 	void startRelation(relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
    80 
       
    81 		writeHeaders(); // from previous relation
    91 		writeHeaders(); // from previous relation
    82 
    92 
    83 		relationalWriter->startRelation(name + L"_curl_info",{
    93 		currentRelationName = name;
    84 			{L"name", relpipe::writer::TypeId::STRING},
    94 		currentReaderMetadata = attributes;
    85 			{L"value", relpipe::writer::TypeId::STRING}
       
    86 		}, true);
       
    87 
    95 
    88 		relationalWriter->writeAttribute(L"curl version");
    96 		if (currentRelationName == L"header") {
    89 		relationalWriter->writeAttribute(convertor.from_bytes(curl_version()));
    97 			// TODO: analyze header attributes
       
    98 		} else if (currentRelationName == L"request") {
       
    99 			relationalWriter->startRelation(L"response",{
       
   100 				// TODO: request ID
       
   101 				// TODO: body in hexadecimal/binary format
       
   102 				{L"url", relpipe::writer::TypeId::STRING},
       
   103 				{L"body", relpipe::writer::TypeId::STRING},
       
   104 				{L"code", relpipe::writer::TypeId::INTEGER},
       
   105 			}, true);
       
   106 		}
       
   107 	}
    90 
   108 
    91 		relationalWriter->startRelation(name + L"_curl_response",{
   109 	void attribute(const relpipe::common::type::StringX& value) override {
    92 			// TODO: request ID
   110 		if (currentRelationName == L"header") headerAttribute(value);
    93 			// TODO: body in hexadecimal/binary format
   111 		else if (currentRelationName == L"request") requestAttribute(value);
    94 			{L"url", relpipe::writer::TypeId::STRING},
   112 		else throw std::invalid_argument("Unsupported relation: " + convertor.to_bytes(currentRelationName));
    95 			{L"body", relpipe::writer::TypeId::STRING},
   113 	}
    96 			{L"response_code", relpipe::writer::TypeId::INTEGER},
   114 
    97 		}, true);
   115 private:
       
   116 
       
   117 	void headerAttribute(const relpipe::common::type::StringX& value) {
       
   118 		if (currentReaderMetadata[currentAttributeIndex].getAttributeName() == L"name") requestHeader.name = value;
       
   119 		else if (currentReaderMetadata[currentAttributeIndex].getAttributeName() == L"value") requestHeader.value = value;
       
   120 		else throw std::invalid_argument("Unsupported attribute in the header relation: " + convertor.to_bytes(currentReaderMetadata[currentAttributeIndex].getAttributeName() + L" = " + value));
       
   121 
       
   122 		currentAttributeIndex++;
       
   123 
       
   124 		if (currentAttributeIndex % currentReaderMetadata.size() == 0) {
       
   125 			currentAttributeIndex = 0;
       
   126 			requestHeaders.push_back(requestHeader);
       
   127 			requestHeader = HeaderDefinition();
       
   128 		}
    98 
   129 
    99 	}
   130 	}
   100 
   131 
   101 	void attribute(const relpipe::common::type::StringX& value) override {
   132 	void requestAttribute(const relpipe::common::type::StringX& value) {
   102 
       
   103 		std::shared_ptr<HTTPClient> http(HTTPClient::open());
   133 		std::shared_ptr<HTTPClient> http(HTTPClient::open());
   104 
   134 
   105 		HTTPClient::Request request;
   135 		HTTPClient::Request request;
   106 		request.method = HTTPClient::Method::GET;
   136 		request.method = HTTPClient::Method::GET;
   107 		request.url = convertor.to_bytes(value);
   137 		request.url = convertor.to_bytes(value);
   111 		// request.headers.push_back("Basic YWhvajpoZXNsbw==");
   141 		// request.headers.push_back("Basic YWhvajpoZXNsbw==");
   112 		// request.headers.push_back("Accept");
   142 		// request.headers.push_back("Accept");
   113 		// request.headers.push_back("application/xml");
   143 		// request.headers.push_back("application/xml");
   114 		// request.headers.push_back("User-Agent");
   144 		// request.headers.push_back("User-Agent");
   115 		// request.headers.push_back("curl/7.58.0");
   145 		// request.headers.push_back("curl/7.58.0");
       
   146 		for (const HeaderDefinition& h : requestHeaders) {
       
   147 			request.headers.push_back(convertor.to_bytes(h.name));
       
   148 			request.headers.push_back(convertor.to_bytes(h.value));
       
   149 		}
   116 
   150 
   117 		HTTPClient::Response response = http->exchange(request);
   151 		HTTPClient::Response response = http->exchange(request);
   118 		relpipe::common::type::Integer responseCode = response.responseCode;
   152 		relpipe::common::type::Integer responseCode = response.responseCode;
   119 
   153 
   120 		relationalWriter->writeAttribute(value);
   154 		relationalWriter->writeAttribute(value);
   126 			responseHeaders.push_back(convertor.from_bytes(response.headers[i]));
   160 			responseHeaders.push_back(convertor.from_bytes(response.headers[i]));
   127 			responseHeaders.push_back(convertor.from_bytes(response.headers[i + 1]));
   161 			responseHeaders.push_back(convertor.from_bytes(response.headers[i + 1]));
   128 		}
   162 		}
   129 	}
   163 	}
   130 
   164 
       
   165 public:
       
   166 
   131 	void endOfPipe() {
   167 	void endOfPipe() {
   132 		writeHeaders(); // from last relation
   168 		writeHeaders(); // from last relation
   133 	}
   169 	}
   134 
   170 
   135 };
   171 };