Commit f6fb006d authored by jan.koester's avatar jan.koester
Browse files

test

parent dfe552e6
Loading
Loading
Loading
Loading
+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>

@@ -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);