Loading src/http/HttpProxyServer.cpp +21 −9 Changes for src/http/HttpProxyServer.cpp: 21 added lines, 9 removed lines. Original line number Diff line number Diff line #include "HttpProxyServer.h" #include <iostream> #include <set> #include <netplus/socket.h> Loading Loading @@ -214,21 +215,32 @@ void HttpProxyController::RequestEvent(libhttppp::HttpRequest &curreq, const int libhttppp::HttpClient client(upstream, /*vers=*/3); libhttppp::HttpRequest outreq; outreq.setRequestURL(upstream.getPath()); // Forward every original header except: protocol pseudo-headers (":path" etc. -- // setRequestURL/setRequestType manage those for whichever protocol HttpClient // actually negotiates with the upstream), hop-by-hop headers (RFC 7230 §6.1, which // describe *this* connection, not the request), and host/content-length, which get // set explicitly below/by HttpClient itself (see _doH1Request in libhttppp/http.cpp -- // it recomputes content-length from whatever body is actually sent). static const std::set<std::string> kHopByHop = { "host", "connection", "content-length", "transfer-encoding", "keep-alive", "proxy-authenticate", "proxy-authorization", "te", "trailer", "upgrade", }; for (auto *hd = curreq.getfirstHeaderData(); hd; hd = hd->nextHeaderData()) { const std::string &key = hd->getkey(); if (key.empty() || key[0] == ':' || kHopByHop.count(key)) continue; auto *out = outreq.setHeaderData(key); for (auto *v = hd->getfirstValue(); v; v = v->nextvalue()) { out->push_back(v->getvalue()); } } outreq.setHeaderData("host")->push_back(upstream.getHost()); outreq.setHeaderData("connection")->push_back("close"); std::vector<char> body; if (method == "POST" || method == "PUT") { outreq.setRequestType(method == "POST" ? POSTREQUEST : PUTREQUEST); // Without this, the upstream receives a body with no Content-Type at all -- // anything parsing it as a form (see libhttppp::HttpForm::parse()) rejects it // outright ("Http Form Parse Error: content type") since it requires the // header, not just a guessable body shape. if (auto *ctype = curreq.getHeaderData("content-type")) { if (auto *v = ctype->getfirstValue()) { outreq.setHeaderData("content-type")->push_back(v->getvalue()); } } std::vector<char> requestBody(curreq.RecvData.begin(), curreq.RecvData.end()); body = (method == "POST") ? client.Post(outreq, requestBody) : client.Put(outreq, requestBody); Loading Loading
src/http/HttpProxyServer.cpp +21 −9 Changes for src/http/HttpProxyServer.cpp: 21 added lines, 9 removed lines. Original line number Diff line number Diff line #include "HttpProxyServer.h" #include <iostream> #include <set> #include <netplus/socket.h> Loading Loading @@ -214,21 +215,32 @@ void HttpProxyController::RequestEvent(libhttppp::HttpRequest &curreq, const int libhttppp::HttpClient client(upstream, /*vers=*/3); libhttppp::HttpRequest outreq; outreq.setRequestURL(upstream.getPath()); // Forward every original header except: protocol pseudo-headers (":path" etc. -- // setRequestURL/setRequestType manage those for whichever protocol HttpClient // actually negotiates with the upstream), hop-by-hop headers (RFC 7230 §6.1, which // describe *this* connection, not the request), and host/content-length, which get // set explicitly below/by HttpClient itself (see _doH1Request in libhttppp/http.cpp -- // it recomputes content-length from whatever body is actually sent). static const std::set<std::string> kHopByHop = { "host", "connection", "content-length", "transfer-encoding", "keep-alive", "proxy-authenticate", "proxy-authorization", "te", "trailer", "upgrade", }; for (auto *hd = curreq.getfirstHeaderData(); hd; hd = hd->nextHeaderData()) { const std::string &key = hd->getkey(); if (key.empty() || key[0] == ':' || kHopByHop.count(key)) continue; auto *out = outreq.setHeaderData(key); for (auto *v = hd->getfirstValue(); v; v = v->nextvalue()) { out->push_back(v->getvalue()); } } outreq.setHeaderData("host")->push_back(upstream.getHost()); outreq.setHeaderData("connection")->push_back("close"); std::vector<char> body; if (method == "POST" || method == "PUT") { outreq.setRequestType(method == "POST" ? POSTREQUEST : PUTREQUEST); // Without this, the upstream receives a body with no Content-Type at all -- // anything parsing it as a form (see libhttppp::HttpForm::parse()) rejects it // outright ("Http Form Parse Error: content type") since it requires the // header, not just a guessable body shape. if (auto *ctype = curreq.getHeaderData("content-type")) { if (auto *v = ctype->getfirstValue()) { outreq.setHeaderData("content-type")->push_back(v->getvalue()); } } std::vector<char> requestBody(curreq.RecvData.begin(), curreq.RecvData.end()); body = (method == "POST") ? client.Post(outreq, requestBody) : client.Put(outreq, requestBody); Loading