Loading src/http.cpp +35 −22 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ libhttppp::HttpUrl::HttpUrl(){ _protocol=HTTP; _origProtocol=HTTP; _port=80; _path="/"; } Loading @@ -64,40 +65,39 @@ libhttppp::HttpUrl::HttpUrl(const std::string& url, bool http3) { const char* c_url = url.c_str(); const char* p = c_url; if (http3) { _protocol = HttpProtocol::HTTP3; _port = 443; // Strip scheme prefix before host parsing if (url.rfind("https://", 0) == 0) { p += 8; } else if (url.rfind("http://", 0) == 0) { p += 7; } } // Update c_url pointer based on scheme matching else if (url.rfind("https://", 0) == 0) { // Using rfind for string prefix check _protocol = HTTPS; // Detect the scheme as it actually appears in the URL string first -- // _origProtocol keeps this even when http3 below forces _protocol to // HTTP3, so fallback logic downstream can still tell https from http. if (url.rfind("https://", 0) == 0) { // Using rfind for string prefix check _origProtocol = HTTPS; _port = 443; p += 8; // Advance pointer past "https://" } else if (url.rfind("http://", 0) == 0) { _protocol = HTTP; _origProtocol = HTTP; _port = 80; p += 7; // Advance pointer past "http://" } // Note: The "https" and "http" (without ://) checks are less robust but kept for compatibility else if (url.rfind("https", 0) == 0) { _protocol = HTTPS; _origProtocol = HTTPS; _port = 443; } else if (url.rfind("http", 0) == 0) { _protocol = HTTP; _origProtocol = HTTP; _port = 80; } else { exp[HTTPException::Error] << "Httpurl: protocol not supported!"; throw exp; } if (http3) { _protocol = HttpProtocol::HTTP3; _port = 443; } else { _protocol = _origProtocol; } _path = "/"; const char* host_start = p; Loading Loading @@ -143,6 +143,7 @@ libhttppp::HttpUrl::HttpUrl(const std::string& url, bool http3) { libhttppp::HttpUrl::HttpUrl(const HttpUrl& src){ _protocol=src._protocol; _origProtocol=src._origProtocol; _host=src._host; _port=src._port; _path=src._path; Loading @@ -153,6 +154,7 @@ libhttppp::HttpUrl::~HttpUrl(){ void libhttppp::HttpUrl::clear(){ _protocol=HTTP; _origProtocol=HTTP; _host.clear(); _port=80; _path="/"; Loading Loading @@ -200,6 +202,10 @@ int libhttppp::HttpUrl::getProtocol() const{ return _protocol; } int libhttppp::HttpUrl::getOriginalProtocol() const{ return _origProtocol; } const std::string & libhttppp::HttpUrl::getHost() const{ return _host; } Loading @@ -225,8 +231,10 @@ libhttppp::HttpClient::HttpClient(const HttpUrl& desturl, int vers, int timeoutS try { if(vers == 3) { if (!tryHttp3First()) { // HTTP/3 failed: try HTTP/2 first, then HTTP/1.1. if (_url.getProtocol() == HttpUrl::HTTPS) { // HTTP/3 failed: try HTTP/2 first, then HTTP/1.1. Must check the // URL's original scheme here, not getProtocol() -- that's pinned // to HTTP3 for the lifetime of this object once requested above. if (_url.getOriginalProtocol() == HttpUrl::HTTPS) { bool h2_ok = false; try { // Internal probe mode: advertise ALPN h2 only. Loading Loading @@ -314,7 +322,10 @@ void libhttppp::HttpClient::resetConnection(){ _h2PrefaceSent = false; _h2NextStreamId = 1; _h2Decoder.reset(); if (_url.getProtocol() == HttpUrl::HTTP3) { // getProtocol() alone isn't enough: it's pinned to HTTP3 for the object's // whole lifetime once requested, even after the ctor downgrades _vers on // fallback. Only take the QUIC path when HTTP/3 is still what we want. if (_url.getProtocol() == HttpUrl::HTTP3 && _vers == 3) { auto q = std::make_unique<netplus::quic>(); q->connect(_url.getHost(), _url.getPort(), false); q->setNonBlock(); Loading @@ -335,7 +346,7 @@ void libhttppp::HttpClient::resetConnection(){ } _cltsock = std::move(q); _isH2 = false; } else if (_url.getProtocol() == HttpUrl::HTTPS) { } else if (_url.getOriginalProtocol() == HttpUrl::HTTPS) { std::map<std::string, netplus::ssl::CertificateBundle> certs; auto sslsock = std::make_unique<netplus::ssl>(certs,-1); Loading Loading @@ -411,7 +422,9 @@ void libhttppp::HttpClient::reconnect(){ _h2PrefaceSent = false; _h2NextStreamId = 1; _h2Decoder.reset(); if (_url.getProtocol() == HttpUrl::HTTP3) { // See resetConnection(): getProtocol() stays HTTP3 for this object's whole // lifetime once requested, so it must be paired with _vers == 3 here too. if (_url.getProtocol() == HttpUrl::HTTP3 && _vers == 3) { auto q = std::make_unique<netplus::quic>(); q->connect(_url.getHost(), _url.getPort(), false); q->setNonBlock(); Loading @@ -432,7 +445,7 @@ void libhttppp::HttpClient::reconnect(){ } _cltsock = std::move(q); _isH2 = false; } else if(_url.getProtocol() == HttpUrl::HTTPS) { } else if(_url.getOriginalProtocol() == HttpUrl::HTTPS) { std::map<std::string, netplus::ssl::CertificateBundle> certs; auto sslsock = std::make_unique<netplus::ssl>(certs,-1); Loading src/http.h +6 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,11 @@ namespace libhttppp { bool operator<(const HttpUrl& other) const; int getProtocol() const; // The scheme (HTTP or HTTPS) as it actually appeared in the URL string, // unaffected by the http3 ctor flag -- getProtocol() returns HTTP3 once // that flag is set, which loses the info needed to fall back correctly // when HTTP/3 isn't available. int getOriginalProtocol() const; const std::string &getHost() const; int getPort() const; const std::string &getPath() const; Loading @@ -79,6 +84,7 @@ namespace libhttppp { private: int _protocol; int _origProtocol; std::string _host; int _port; std::string _path; Loading Loading
src/http.cpp +35 −22 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ libhttppp::HttpUrl::HttpUrl(){ _protocol=HTTP; _origProtocol=HTTP; _port=80; _path="/"; } Loading @@ -64,40 +65,39 @@ libhttppp::HttpUrl::HttpUrl(const std::string& url, bool http3) { const char* c_url = url.c_str(); const char* p = c_url; if (http3) { _protocol = HttpProtocol::HTTP3; _port = 443; // Strip scheme prefix before host parsing if (url.rfind("https://", 0) == 0) { p += 8; } else if (url.rfind("http://", 0) == 0) { p += 7; } } // Update c_url pointer based on scheme matching else if (url.rfind("https://", 0) == 0) { // Using rfind for string prefix check _protocol = HTTPS; // Detect the scheme as it actually appears in the URL string first -- // _origProtocol keeps this even when http3 below forces _protocol to // HTTP3, so fallback logic downstream can still tell https from http. if (url.rfind("https://", 0) == 0) { // Using rfind for string prefix check _origProtocol = HTTPS; _port = 443; p += 8; // Advance pointer past "https://" } else if (url.rfind("http://", 0) == 0) { _protocol = HTTP; _origProtocol = HTTP; _port = 80; p += 7; // Advance pointer past "http://" } // Note: The "https" and "http" (without ://) checks are less robust but kept for compatibility else if (url.rfind("https", 0) == 0) { _protocol = HTTPS; _origProtocol = HTTPS; _port = 443; } else if (url.rfind("http", 0) == 0) { _protocol = HTTP; _origProtocol = HTTP; _port = 80; } else { exp[HTTPException::Error] << "Httpurl: protocol not supported!"; throw exp; } if (http3) { _protocol = HttpProtocol::HTTP3; _port = 443; } else { _protocol = _origProtocol; } _path = "/"; const char* host_start = p; Loading Loading @@ -143,6 +143,7 @@ libhttppp::HttpUrl::HttpUrl(const std::string& url, bool http3) { libhttppp::HttpUrl::HttpUrl(const HttpUrl& src){ _protocol=src._protocol; _origProtocol=src._origProtocol; _host=src._host; _port=src._port; _path=src._path; Loading @@ -153,6 +154,7 @@ libhttppp::HttpUrl::~HttpUrl(){ void libhttppp::HttpUrl::clear(){ _protocol=HTTP; _origProtocol=HTTP; _host.clear(); _port=80; _path="/"; Loading Loading @@ -200,6 +202,10 @@ int libhttppp::HttpUrl::getProtocol() const{ return _protocol; } int libhttppp::HttpUrl::getOriginalProtocol() const{ return _origProtocol; } const std::string & libhttppp::HttpUrl::getHost() const{ return _host; } Loading @@ -225,8 +231,10 @@ libhttppp::HttpClient::HttpClient(const HttpUrl& desturl, int vers, int timeoutS try { if(vers == 3) { if (!tryHttp3First()) { // HTTP/3 failed: try HTTP/2 first, then HTTP/1.1. if (_url.getProtocol() == HttpUrl::HTTPS) { // HTTP/3 failed: try HTTP/2 first, then HTTP/1.1. Must check the // URL's original scheme here, not getProtocol() -- that's pinned // to HTTP3 for the lifetime of this object once requested above. if (_url.getOriginalProtocol() == HttpUrl::HTTPS) { bool h2_ok = false; try { // Internal probe mode: advertise ALPN h2 only. Loading Loading @@ -314,7 +322,10 @@ void libhttppp::HttpClient::resetConnection(){ _h2PrefaceSent = false; _h2NextStreamId = 1; _h2Decoder.reset(); if (_url.getProtocol() == HttpUrl::HTTP3) { // getProtocol() alone isn't enough: it's pinned to HTTP3 for the object's // whole lifetime once requested, even after the ctor downgrades _vers on // fallback. Only take the QUIC path when HTTP/3 is still what we want. if (_url.getProtocol() == HttpUrl::HTTP3 && _vers == 3) { auto q = std::make_unique<netplus::quic>(); q->connect(_url.getHost(), _url.getPort(), false); q->setNonBlock(); Loading @@ -335,7 +346,7 @@ void libhttppp::HttpClient::resetConnection(){ } _cltsock = std::move(q); _isH2 = false; } else if (_url.getProtocol() == HttpUrl::HTTPS) { } else if (_url.getOriginalProtocol() == HttpUrl::HTTPS) { std::map<std::string, netplus::ssl::CertificateBundle> certs; auto sslsock = std::make_unique<netplus::ssl>(certs,-1); Loading Loading @@ -411,7 +422,9 @@ void libhttppp::HttpClient::reconnect(){ _h2PrefaceSent = false; _h2NextStreamId = 1; _h2Decoder.reset(); if (_url.getProtocol() == HttpUrl::HTTP3) { // See resetConnection(): getProtocol() stays HTTP3 for this object's whole // lifetime once requested, so it must be paired with _vers == 3 here too. if (_url.getProtocol() == HttpUrl::HTTP3 && _vers == 3) { auto q = std::make_unique<netplus::quic>(); q->connect(_url.getHost(), _url.getPort(), false); q->setNonBlock(); Loading @@ -432,7 +445,7 @@ void libhttppp::HttpClient::reconnect(){ } _cltsock = std::move(q); _isH2 = false; } else if(_url.getProtocol() == HttpUrl::HTTPS) { } else if(_url.getOriginalProtocol() == HttpUrl::HTTPS) { std::map<std::string, netplus::ssl::CertificateBundle> certs; auto sslsock = std::make_unique<netplus::ssl>(certs,-1); Loading
src/http.h +6 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,11 @@ namespace libhttppp { bool operator<(const HttpUrl& other) const; int getProtocol() const; // The scheme (HTTP or HTTPS) as it actually appeared in the URL string, // unaffected by the http3 ctor flag -- getProtocol() returns HTTP3 once // that flag is set, which loses the info needed to fall back correctly // when HTTP/3 isn't available. int getOriginalProtocol() const; const std::string &getHost() const; int getPort() const; const std::string &getPath() const; Loading @@ -79,6 +84,7 @@ namespace libhttppp { private: int _protocol; int _origProtocol; std::string _host; int _port; std::string _path; Loading