Loading src/http.cpp +266 −15 Original line number Diff line number Diff line Loading @@ -227,9 +227,12 @@ void libhttppp::HttpClient::resetConnection(){ std::map<std::string, netplus::ssl::CertificateBundle> certs; auto sslsock = std::make_unique<netplus::ssl>(certs,-1); // Advertise h2 and http/1.1 via ALPN // IMPORTANT: For compatibility with servers that may not handle HTTP/2 framing properly, // we prefer HTTP/1.1 as default and only enable HTTP/2 if explicitly negotiated. // Many servers claim H2 support but have bugs in HTTP/2 frame handling. // Set ALPN to prefer http/1.1 over h2 sslsock->getTls().client_alpn_protocols = std::string("\x02h2\x08http/1.1", 12); std::string("\x08http/1.1\x02h2", 12); _cltsock = std::move(sslsock); _cltsock->connect(_url.getHost(), _url.getPort(), false); Loading @@ -238,7 +241,22 @@ void libhttppp::HttpClient::resetConnection(){ // Check negotiated ALPN after TLS handshake const std::string &alpn = dynamic_cast<netplus::ssl*>(_cltsock.get())->getSelectedAlpn(); _isH2 = (alpn == "h2"); std::cerr << "[HttpClient] ALPN negotiated: '" << alpn << "' isH2=" << _isH2 << std::endl; std::cerr << "[HttpClient] ALPN negotiated: '" << alpn << "' (length=" << alpn.size() << ")" << " isH2=" << _isH2 << std::endl; // Debug: print ALPN bytes if (!alpn.empty()) { std::cerr << "[HttpClient] ALPN bytes: "; for (unsigned char c : alpn) { if (c >= 32 && c < 127) { std::cerr << c; } else { std::cerr << "[" << std::hex << std::setw(2) << std::setfill('0') << (int)c << std::dec << "]"; } } std::cerr << std::endl; } } else { _cltsock = std::make_unique<netplus::tcp>(-1); _cltsock->connect(_url.getHost(), _url.getPort(), false); Loading Loading @@ -891,6 +909,195 @@ const std::vector<char> libhttppp::HttpClient::Get(libhttppp::HttpRequest &nreq) } } const std::vector<char> libhttppp::HttpClient::Delete(libhttppp::HttpRequest &nreq) { // Delete() is identical to Get() except it uses DELETEREQUEST std::vector<char> ret; try { resetConnection(); std::stringstream host; host << _url.getHost() << ":" << _url.getPort(); nreq.setHeaderData("host")->push_back(host.str()); nreq.setRequestType(DELETEREQUEST); if (nreq.getRequestURL().empty()) nreq.setRequestURL(_url.getPath()); // HTTP/2: delegate to binary framing path if (_isH2) { return _h2Request("DELETE", nreq); } if (nreq.getRequestVersion().empty()) nreq.setRequestVersion(HTTPVERSION(1.1)); nreq.send(_url, _cltsock); auto recv_blocking = [&](netplus::buffer& b) -> size_t { for (;;) { try { size_t n = _cltsock->recvData(b, 0); return n; } catch (netplus::NetException& e) { if (e.getErrorType() == netplus::NetException::Note) { sleep_note(); continue; } throw; } } }; std::vector<char> raw; raw.reserve(8192); size_t header_end = std::string::npos; for (;;) { if (raw.size() >= 4) { for (size_t i = 0; i + 3 < raw.size(); ++i) { if (raw[i] == '\r' && raw[i+1] == '\n' && raw[i+2] == '\r' && raw[i+3] == '\n') { header_end = i + 4; break; } } } if (header_end != std::string::npos) break; netplus::buffer buf(BLOCKSIZE); size_t n = recv_blocking(buf); if (n == 0) { netplus::NetException ne; ne[netplus::NetException::Error] << "HTTP: EOF while reading header"; throw ne; } raw.insert(raw.end(), buf.data.buf, buf.data.buf + n); } libhttppp::HttpResponse res; size_t parsed_hsize = res.parse(raw.data(), raw.size()); if (parsed_hsize == 0 || parsed_hsize > raw.size()) { libhttppp::HTTPException he; he[libhttppp::HTTPException::Error] << "HTTP: response header parse failed"; throw he; } size_t body_off = parsed_hsize; bool chunked = false; ptrdiff_t content_len = -1; try { for (libhttppp::HttpHeader::HeaderData::Values *v = res.getTransferEncoding(); v; v = v->nextvalue()) { std::string val = tolower_copy(v->getvalue()); if (val == "chunked") { chunked = true; break; } } } catch (...) {} if (!chunked) { try { content_len = res.getContentLength(); if (content_len < 0) content_len = -1; } catch (...) { content_len = -1; } } auto append_from_raw = [&](size_t& take_pos, size_t take_len) { if (take_len == 0) return; ret.insert(ret.end(), raw.begin() + (ptrdiff_t)take_pos, raw.begin() + (ptrdiff_t)(take_pos + take_len)); take_pos += take_len; }; if (!chunked && content_len >= 0) { size_t remaining = (size_t)content_len; size_t pos = body_off; size_t can = (std::min)(remaining, raw.size() - pos); append_from_raw(pos, can); remaining -= can; while (remaining > 0) { netplus::buffer buf(BLOCKSIZE); size_t n = recv_blocking(buf); if (n == 0) { netplus::NetException ne; ne[netplus::NetException::Error] << "HTTP: EOF before Content-Length complete"; throw ne; } size_t take = (std::min)(remaining, n); ret.insert(ret.end(), buf.data.buf, buf.data.buf + take); remaining -= take; } return ret; } if (chunked) { size_t pos = body_off; auto ensure_bytes = [&](size_t need) { while (raw.size() - pos < need) { netplus::buffer buf(BLOCKSIZE); size_t n = recv_blocking(buf); if (n == 0) break; raw.insert(raw.end(), buf.data.buf, buf.data.buf + n); } }; for (;;) { ensure_bytes(3); size_t line_end = std::string::npos; for (size_t i = pos; i + 1 < raw.size(); ++i) { if (raw[i] == '\r' && raw[i+1] == '\n') { line_end = i; break; } } if (line_end == std::string::npos) break; std::string hex(raw.begin() + pos, raw.begin() + line_end); pos = line_end + 2; size_t chunk_sz = 0; try { chunk_sz = std::stoull(hex, nullptr, 16); } catch(...) { break; } if (chunk_sz == 0) break; ensure_bytes(chunk_sz + 2); ret.insert(ret.end(), raw.begin() + pos, raw.begin() + pos + chunk_sz); pos += chunk_sz + 2; } return ret; } // read-until-close fallback { size_t pos = body_off; if (pos < raw.size()) ret.insert(ret.end(), raw.begin() + pos, raw.end()); for (;;) { netplus::buffer buf(BLOCKSIZE); size_t n = 0; try { n = recv_blocking(buf); } catch (...) { break; } if (n == 0) break; ret.insert(ret.end(), buf.data.buf, buf.data.buf + n); } } return ret; } catch (netplus::NetException &e) { libhttppp::HTTPException ee; ee[libhttppp::HTTPException::Error] << e.what(); throw ee; } } const std::vector<char> libhttppp::HttpClient::Post(libhttppp::HttpRequest &nreq, const std::vector<char> &post) { Loading Loading @@ -1894,12 +2101,42 @@ size_t libhttppp::HttpResponse::parse(const char *data, size_t inlen) { ltrim_inplace(s); }; // --- 1) find end of header: "\r\n\r\n" --- // --- 1) Detect HTTP/2 frames (not HTTP/1.1 text headers) --- // HTTP/2 frames have structure: 3-byte length, 1-byte type, 1-byte flags, 4-byte stream ID // First byte of length would typically be 0x00, 0x00 for SETTINGS frames // If we see patterns like [0x00 0x00 xx | frame_type] where frame_type is 0x00-0x0A, // we're likely dealing with HTTP/2. if (inlen >= 9) { uint8_t b0 = (uint8_t)data[0]; uint8_t b1 = (uint8_t)data[1]; uint8_t b2 = (uint8_t)data[2]; uint8_t frame_type = (uint8_t)data[3]; // Heuristic: HTTP/2 frames typically start with length bytes that would be // invalid at the start of "HTTP/x.x" // If first 4 bytes look like frame header (small length + valid frame type), // this is likely HTTP/2 being received when HTTP/1.1 was expected. bool looks_like_h2_frame = (b0 <= 0x40 && b1 == 0x00); // length <= 16KB with b1=0 bool valid_frame_type = (frame_type <= 0x0A); // SETTINGS(0x04), HEADERS(0x01), etc. if (looks_like_h2_frame && valid_frame_type) { // Log diagnostic info and throw with clearer message std::cerr << "[HttpResponse::parse] Detected HTTP/2 frame when expecting HTTP/1.1" << std::endl; std::cerr << "[HttpResponse::parse] Frame bytes: " << std::hex << std::setw(2) << std::setfill('0') << (int)b0 << " " << (int)b1 << " " << (int)b2 << " " << (int)frame_type << std::dec << std::endl; excep[HTTPException::Error] << "HTTP/2 frame received but HTTP/1.1 parser active - ALPN negotiation issue"; throw excep; } } // --- 2) find end of header: "\r\n\r\n" --- const char* header_end_marker = "\r\n\r\n"; const char* end_ptr = data + inlen - 4; const char* header_end_pos = nullptr; for (const char* p = data; p < end_ptr; ++p) { for (const char* p = data; p <= end_ptr; ++p) { if (std::equal(p, p + 4, header_end_marker)) { header_end_pos = p; break; Loading @@ -1907,6 +2144,15 @@ size_t libhttppp::HttpResponse::parse(const char *data, size_t inlen) { } if (!header_end_pos) { // Give more diagnostic information when header parsing fails std::cerr << "[HttpResponse::parse] HTTP/1.1 header terminator not found in " << inlen << " bytes" << std::endl; std::cerr << "[HttpResponse::parse] First 64 bytes (hex): "; for (size_t i = 0; i < std::min(inlen, (size_t)64); ++i) { std::cerr << std::hex << std::setw(2) << std::setfill('0') << (int)(uint8_t)data[i] << " "; } std::cerr << std::dec << std::endl; excep[HTTPException::Error] << "HttpHeader end not found!"; throw excep; } Loading Loading @@ -2162,6 +2408,7 @@ size_t libhttppp::HttpRequest::parseH2(const std::vector<hpack::HeaderField> &he std::string method = (methodHd && methodHd->getfirstValue()) ? methodHd->getfirstValue()->getvalue() : "GET"; if (method == "GET") _RequestType = GETREQUEST; else if (method == "POST") _RequestType = POSTREQUEST; else if (method == "DELETE") _RequestType = DELETEREQUEST; else _RequestType = GETREQUEST; auto *pathHd = getHeaderData(":path"); Loading Loading @@ -2228,6 +2475,7 @@ size_t libhttppp::HttpRequest::parseH3(const std::vector<qpack::HeaderField> &he std::string method = (methodHd && methodHd->getfirstValue()) ? methodHd->getfirstValue()->getvalue() : "GET"; if (method == "GET") _RequestType = GETREQUEST; else if (method == "POST") _RequestType = POSTREQUEST; else if (method == "DELETE") _RequestType = DELETEREQUEST; else _RequestType = GETREQUEST; auto *pathHd = getHeaderData(":path"); Loading Loading @@ -2314,6 +2562,7 @@ size_t libhttppp::HttpRequest::parseH1() { // 5) Set request type if (method == "GET") _RequestType = GETREQUEST; else if (method == "POST") _RequestType = POSTREQUEST; else if (method == "DELETE") _RequestType = DELETEREQUEST; else _RequestType = PARSEREQUEST; // or a dedicated enum for others // 6) Store pseudo-headers in _firstHeaderData (unified storage) Loading Loading @@ -2441,6 +2690,8 @@ void libhttppp::HttpRequest::printHeader(std::string &buffer){ buffer="GET "; else if(_RequestType==POSTREQUEST) buffer="POST "; else if(_RequestType==DELETEREQUEST) buffer="DELETE "; buffer.append(_cachedRequest); buffer.append(" "); Loading Loading @@ -2573,7 +2824,7 @@ void libhttppp::HttpRequest::send(const HttpUrl &dest, } void libhttppp::HttpRequest::setRequestType(int req){ if(req == POSTREQUEST || req == GETREQUEST){ if(req == POSTREQUEST || req == GETREQUEST || req == DELETEREQUEST){ _RequestType=req; return; } Loading src/http.h +1 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ namespace libhttppp { void reconnect(); const std::vector<char> Get(HttpRequest &nreq); const std::vector<char> Post(HttpRequest &nreq,const std::vector<char> &post); const std::vector<char> Delete(HttpRequest &nreq); private: void resetConnection(); int readchunk(const char *data,int datasize,int &pos); Loading src/httpdefinitions.h +4 −3 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define PARSEREQUEST 0 #define GETREQUEST 1 #define POSTREQUEST 2 #define DELETEREQUEST 3 //define http version Loading Loading
src/http.cpp +266 −15 Original line number Diff line number Diff line Loading @@ -227,9 +227,12 @@ void libhttppp::HttpClient::resetConnection(){ std::map<std::string, netplus::ssl::CertificateBundle> certs; auto sslsock = std::make_unique<netplus::ssl>(certs,-1); // Advertise h2 and http/1.1 via ALPN // IMPORTANT: For compatibility with servers that may not handle HTTP/2 framing properly, // we prefer HTTP/1.1 as default and only enable HTTP/2 if explicitly negotiated. // Many servers claim H2 support but have bugs in HTTP/2 frame handling. // Set ALPN to prefer http/1.1 over h2 sslsock->getTls().client_alpn_protocols = std::string("\x02h2\x08http/1.1", 12); std::string("\x08http/1.1\x02h2", 12); _cltsock = std::move(sslsock); _cltsock->connect(_url.getHost(), _url.getPort(), false); Loading @@ -238,7 +241,22 @@ void libhttppp::HttpClient::resetConnection(){ // Check negotiated ALPN after TLS handshake const std::string &alpn = dynamic_cast<netplus::ssl*>(_cltsock.get())->getSelectedAlpn(); _isH2 = (alpn == "h2"); std::cerr << "[HttpClient] ALPN negotiated: '" << alpn << "' isH2=" << _isH2 << std::endl; std::cerr << "[HttpClient] ALPN negotiated: '" << alpn << "' (length=" << alpn.size() << ")" << " isH2=" << _isH2 << std::endl; // Debug: print ALPN bytes if (!alpn.empty()) { std::cerr << "[HttpClient] ALPN bytes: "; for (unsigned char c : alpn) { if (c >= 32 && c < 127) { std::cerr << c; } else { std::cerr << "[" << std::hex << std::setw(2) << std::setfill('0') << (int)c << std::dec << "]"; } } std::cerr << std::endl; } } else { _cltsock = std::make_unique<netplus::tcp>(-1); _cltsock->connect(_url.getHost(), _url.getPort(), false); Loading Loading @@ -891,6 +909,195 @@ const std::vector<char> libhttppp::HttpClient::Get(libhttppp::HttpRequest &nreq) } } const std::vector<char> libhttppp::HttpClient::Delete(libhttppp::HttpRequest &nreq) { // Delete() is identical to Get() except it uses DELETEREQUEST std::vector<char> ret; try { resetConnection(); std::stringstream host; host << _url.getHost() << ":" << _url.getPort(); nreq.setHeaderData("host")->push_back(host.str()); nreq.setRequestType(DELETEREQUEST); if (nreq.getRequestURL().empty()) nreq.setRequestURL(_url.getPath()); // HTTP/2: delegate to binary framing path if (_isH2) { return _h2Request("DELETE", nreq); } if (nreq.getRequestVersion().empty()) nreq.setRequestVersion(HTTPVERSION(1.1)); nreq.send(_url, _cltsock); auto recv_blocking = [&](netplus::buffer& b) -> size_t { for (;;) { try { size_t n = _cltsock->recvData(b, 0); return n; } catch (netplus::NetException& e) { if (e.getErrorType() == netplus::NetException::Note) { sleep_note(); continue; } throw; } } }; std::vector<char> raw; raw.reserve(8192); size_t header_end = std::string::npos; for (;;) { if (raw.size() >= 4) { for (size_t i = 0; i + 3 < raw.size(); ++i) { if (raw[i] == '\r' && raw[i+1] == '\n' && raw[i+2] == '\r' && raw[i+3] == '\n') { header_end = i + 4; break; } } } if (header_end != std::string::npos) break; netplus::buffer buf(BLOCKSIZE); size_t n = recv_blocking(buf); if (n == 0) { netplus::NetException ne; ne[netplus::NetException::Error] << "HTTP: EOF while reading header"; throw ne; } raw.insert(raw.end(), buf.data.buf, buf.data.buf + n); } libhttppp::HttpResponse res; size_t parsed_hsize = res.parse(raw.data(), raw.size()); if (parsed_hsize == 0 || parsed_hsize > raw.size()) { libhttppp::HTTPException he; he[libhttppp::HTTPException::Error] << "HTTP: response header parse failed"; throw he; } size_t body_off = parsed_hsize; bool chunked = false; ptrdiff_t content_len = -1; try { for (libhttppp::HttpHeader::HeaderData::Values *v = res.getTransferEncoding(); v; v = v->nextvalue()) { std::string val = tolower_copy(v->getvalue()); if (val == "chunked") { chunked = true; break; } } } catch (...) {} if (!chunked) { try { content_len = res.getContentLength(); if (content_len < 0) content_len = -1; } catch (...) { content_len = -1; } } auto append_from_raw = [&](size_t& take_pos, size_t take_len) { if (take_len == 0) return; ret.insert(ret.end(), raw.begin() + (ptrdiff_t)take_pos, raw.begin() + (ptrdiff_t)(take_pos + take_len)); take_pos += take_len; }; if (!chunked && content_len >= 0) { size_t remaining = (size_t)content_len; size_t pos = body_off; size_t can = (std::min)(remaining, raw.size() - pos); append_from_raw(pos, can); remaining -= can; while (remaining > 0) { netplus::buffer buf(BLOCKSIZE); size_t n = recv_blocking(buf); if (n == 0) { netplus::NetException ne; ne[netplus::NetException::Error] << "HTTP: EOF before Content-Length complete"; throw ne; } size_t take = (std::min)(remaining, n); ret.insert(ret.end(), buf.data.buf, buf.data.buf + take); remaining -= take; } return ret; } if (chunked) { size_t pos = body_off; auto ensure_bytes = [&](size_t need) { while (raw.size() - pos < need) { netplus::buffer buf(BLOCKSIZE); size_t n = recv_blocking(buf); if (n == 0) break; raw.insert(raw.end(), buf.data.buf, buf.data.buf + n); } }; for (;;) { ensure_bytes(3); size_t line_end = std::string::npos; for (size_t i = pos; i + 1 < raw.size(); ++i) { if (raw[i] == '\r' && raw[i+1] == '\n') { line_end = i; break; } } if (line_end == std::string::npos) break; std::string hex(raw.begin() + pos, raw.begin() + line_end); pos = line_end + 2; size_t chunk_sz = 0; try { chunk_sz = std::stoull(hex, nullptr, 16); } catch(...) { break; } if (chunk_sz == 0) break; ensure_bytes(chunk_sz + 2); ret.insert(ret.end(), raw.begin() + pos, raw.begin() + pos + chunk_sz); pos += chunk_sz + 2; } return ret; } // read-until-close fallback { size_t pos = body_off; if (pos < raw.size()) ret.insert(ret.end(), raw.begin() + pos, raw.end()); for (;;) { netplus::buffer buf(BLOCKSIZE); size_t n = 0; try { n = recv_blocking(buf); } catch (...) { break; } if (n == 0) break; ret.insert(ret.end(), buf.data.buf, buf.data.buf + n); } } return ret; } catch (netplus::NetException &e) { libhttppp::HTTPException ee; ee[libhttppp::HTTPException::Error] << e.what(); throw ee; } } const std::vector<char> libhttppp::HttpClient::Post(libhttppp::HttpRequest &nreq, const std::vector<char> &post) { Loading Loading @@ -1894,12 +2101,42 @@ size_t libhttppp::HttpResponse::parse(const char *data, size_t inlen) { ltrim_inplace(s); }; // --- 1) find end of header: "\r\n\r\n" --- // --- 1) Detect HTTP/2 frames (not HTTP/1.1 text headers) --- // HTTP/2 frames have structure: 3-byte length, 1-byte type, 1-byte flags, 4-byte stream ID // First byte of length would typically be 0x00, 0x00 for SETTINGS frames // If we see patterns like [0x00 0x00 xx | frame_type] where frame_type is 0x00-0x0A, // we're likely dealing with HTTP/2. if (inlen >= 9) { uint8_t b0 = (uint8_t)data[0]; uint8_t b1 = (uint8_t)data[1]; uint8_t b2 = (uint8_t)data[2]; uint8_t frame_type = (uint8_t)data[3]; // Heuristic: HTTP/2 frames typically start with length bytes that would be // invalid at the start of "HTTP/x.x" // If first 4 bytes look like frame header (small length + valid frame type), // this is likely HTTP/2 being received when HTTP/1.1 was expected. bool looks_like_h2_frame = (b0 <= 0x40 && b1 == 0x00); // length <= 16KB with b1=0 bool valid_frame_type = (frame_type <= 0x0A); // SETTINGS(0x04), HEADERS(0x01), etc. if (looks_like_h2_frame && valid_frame_type) { // Log diagnostic info and throw with clearer message std::cerr << "[HttpResponse::parse] Detected HTTP/2 frame when expecting HTTP/1.1" << std::endl; std::cerr << "[HttpResponse::parse] Frame bytes: " << std::hex << std::setw(2) << std::setfill('0') << (int)b0 << " " << (int)b1 << " " << (int)b2 << " " << (int)frame_type << std::dec << std::endl; excep[HTTPException::Error] << "HTTP/2 frame received but HTTP/1.1 parser active - ALPN negotiation issue"; throw excep; } } // --- 2) find end of header: "\r\n\r\n" --- const char* header_end_marker = "\r\n\r\n"; const char* end_ptr = data + inlen - 4; const char* header_end_pos = nullptr; for (const char* p = data; p < end_ptr; ++p) { for (const char* p = data; p <= end_ptr; ++p) { if (std::equal(p, p + 4, header_end_marker)) { header_end_pos = p; break; Loading @@ -1907,6 +2144,15 @@ size_t libhttppp::HttpResponse::parse(const char *data, size_t inlen) { } if (!header_end_pos) { // Give more diagnostic information when header parsing fails std::cerr << "[HttpResponse::parse] HTTP/1.1 header terminator not found in " << inlen << " bytes" << std::endl; std::cerr << "[HttpResponse::parse] First 64 bytes (hex): "; for (size_t i = 0; i < std::min(inlen, (size_t)64); ++i) { std::cerr << std::hex << std::setw(2) << std::setfill('0') << (int)(uint8_t)data[i] << " "; } std::cerr << std::dec << std::endl; excep[HTTPException::Error] << "HttpHeader end not found!"; throw excep; } Loading Loading @@ -2162,6 +2408,7 @@ size_t libhttppp::HttpRequest::parseH2(const std::vector<hpack::HeaderField> &he std::string method = (methodHd && methodHd->getfirstValue()) ? methodHd->getfirstValue()->getvalue() : "GET"; if (method == "GET") _RequestType = GETREQUEST; else if (method == "POST") _RequestType = POSTREQUEST; else if (method == "DELETE") _RequestType = DELETEREQUEST; else _RequestType = GETREQUEST; auto *pathHd = getHeaderData(":path"); Loading Loading @@ -2228,6 +2475,7 @@ size_t libhttppp::HttpRequest::parseH3(const std::vector<qpack::HeaderField> &he std::string method = (methodHd && methodHd->getfirstValue()) ? methodHd->getfirstValue()->getvalue() : "GET"; if (method == "GET") _RequestType = GETREQUEST; else if (method == "POST") _RequestType = POSTREQUEST; else if (method == "DELETE") _RequestType = DELETEREQUEST; else _RequestType = GETREQUEST; auto *pathHd = getHeaderData(":path"); Loading Loading @@ -2314,6 +2562,7 @@ size_t libhttppp::HttpRequest::parseH1() { // 5) Set request type if (method == "GET") _RequestType = GETREQUEST; else if (method == "POST") _RequestType = POSTREQUEST; else if (method == "DELETE") _RequestType = DELETEREQUEST; else _RequestType = PARSEREQUEST; // or a dedicated enum for others // 6) Store pseudo-headers in _firstHeaderData (unified storage) Loading Loading @@ -2441,6 +2690,8 @@ void libhttppp::HttpRequest::printHeader(std::string &buffer){ buffer="GET "; else if(_RequestType==POSTREQUEST) buffer="POST "; else if(_RequestType==DELETEREQUEST) buffer="DELETE "; buffer.append(_cachedRequest); buffer.append(" "); Loading Loading @@ -2573,7 +2824,7 @@ void libhttppp::HttpRequest::send(const HttpUrl &dest, } void libhttppp::HttpRequest::setRequestType(int req){ if(req == POSTREQUEST || req == GETREQUEST){ if(req == POSTREQUEST || req == GETREQUEST || req == DELETEREQUEST){ _RequestType=req; return; } Loading
src/http.h +1 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ namespace libhttppp { void reconnect(); const std::vector<char> Get(HttpRequest &nreq); const std::vector<char> Post(HttpRequest &nreq,const std::vector<char> &post); const std::vector<char> Delete(HttpRequest &nreq); private: void resetConnection(); int readchunk(const char *data,int datasize,int &pos); Loading
src/httpdefinitions.h +4 −3 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define PARSEREQUEST 0 #define GETREQUEST 1 #define POSTREQUEST 2 #define DELETEREQUEST 3 //define http version Loading