/* Crafter®.Network Copyright (C) 2025 Catcrafts® Catcrafts.net This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ module; #include #include #include #include #include #include #include #include #include module Crafter.Network:ClientHTTP_impl; import :ClientHTTP; import Crafter.Thread; import std; using namespace Crafter; ClientHTTP::ClientHTTP(const char* host, std::uint16_t port): client(host, port) { } ClientHTTP::ClientHTTP(std::string host, std::uint16_t port): ClientHTTP(host.c_str(), port) { } HTTPResponse ClientHTTP::Send(const char* request, std::uint32_t length) const { client.Send(request, length); std::vector buffer = client.RecieveSync(1024); HTTPResponse response; std::uint32_t i = 0; std::uint32_t statusStart = 0; for(; i < 1024; i++) { if(buffer[i] == ' ') { statusStart = i; break; } } for(; i < 1024; i++) { if(buffer[i] == '\r') { response.status.assign(buffer.data()+statusStart+1, i-statusStart-1); break; } } i+=2; while(i < 1024) { std::uint32_t headerStart = i; std::string headerName; for(; i < 1024; i++) { if(buffer[i] == ':') { headerName.assign(buffer.data()+headerStart, i-headerStart); i+=2; break; } } headerStart = i; std::string headerValue; for(; i < 1024; i++) { if(buffer[i] == '\r' && buffer[i+1] == '\n') { headerValue.assign(buffer.data()+headerStart, i-headerStart); response.headers.insert({headerName, headerValue}); if(buffer[i+2] == '\r'){ goto headersComplete; } else{ i+=2; break; } } } } headersComplete:; i+=4; std::unordered_map::iterator it = response.headers.find("Content-Length"); if(it != response.headers.end()) { const int lenght = std::stoi(it->second); response.body.resize(lenght, 0); if(i < buffer.size()){ std::memcpy(&response.body[0], buffer.data()+i, buffer.size()-i); } const int remaining = lenght-(buffer.size()-i); if(remaining > 0){ int index = buffer.size()-i; while(index < lenght) { std::vector bodyBuffer = client.RecieveSync(remaining); std::memcpy(&response.body[index], bodyBuffer.data(), bodyBuffer.size()); index+=bodyBuffer.size(); } } } else { std::unordered_map::iterator it = response.headers.find("Transfer-Encoding"); if(it != response.headers.end() && it->second == "chunked") { while(i < buffer.size()){ std::string lenght; int lenghtStart = i; for(; i < buffer.size(); i++) { if(buffer[i] == '\r') { lenght.assign(buffer.data()+lenghtStart, i-lenghtStart); break; } } i+=2; std::cout << lenght << "bro" << std::endl; int lenghtInt = stoi(lenght, 0, 8); if(lenghtInt != 0){ int oldSize = response.body.size(); response.body.resize(oldSize+lenghtInt, 0); if(buffer.size() < lenghtInt) { std::memcpy(&response.body[oldSize], buffer.data()+i, buffer.size()-i); std::vector bodyBuffer2 = client.RecieveUntilFullSync(lenghtInt-buffer.size()); std::memcpy(&response.body[oldSize+(buffer.size()-i)], buffer.data(), buffer.size()); } else { std::memcpy(&response.body[oldSize], buffer.data()+i, lenghtInt); i+=lenghtInt; } } else{ goto bodyFinished; } } std::cout << response.body << std::endl; while(true) { std::vector bodyBuffer = client.RecieveSync(); int i2 = 0; while(i2 < bodyBuffer.size()){ std::string lenght; int lenghtStart = i2; for(; i2 < bodyBuffer.size(); i2++) { if(buffer[i2] == '\r') { lenght.assign(bodyBuffer.data()+lenghtStart, i2-lenghtStart); break; } } i2+=2; int lenghtInt = stoi(lenght, 0, 8); std::cout < bodyBuffer2 = client.RecieveUntilFullSync(lenghtInt-bodyBuffer.size()); std::memcpy(&response.body[oldSize+(bodyBuffer.size()-i2)], bodyBuffer2.data(), bodyBuffer2.size()); } else { std::memcpy(&response.body[oldSize], bodyBuffer.data()+i2, lenghtInt); i2+=lenghtInt; } } else{ goto bodyFinished; } } } bodyFinished:; } else { std::vector bodyBuffer = client.RecieveUntilCloseSync(); response.body.resize((buffer.size()-i)+(bodyBuffer.size()), 0); if(i < buffer.size()){ std::memcpy(&response.body[0], buffer.data()+i, buffer.size()-i); } std::memcpy(&response.body[buffer.size()-i], bodyBuffer.data(), bodyBuffer.size()); } } return response; } HTTPResponse ClientHTTP::Send(std::string request) const { return Send(request.c_str(), request.size()); }