#include "ehs/io/socket/Request.h" #include "ehs/Base64.h" namespace ehs { Request::Request() : verb(Verb::GET), cType(ContentType::NONE) { } Request::Request(const Verb verb, const Str_8& rsrc) : verb(verb), rsrc(rsrc), cType(ContentType::NONE) { } Request::Request(const char* data, const UInt_64 size) : verb(Verb::POST), cType(ContentType::NONE) { ReadData(Str_8(data, size)); } Request::Request(const Str_8& data) : verb(Verb::POST), cType(ContentType::NONE) { ReadData(data); } Request& Request::operator=(const Request &req) { if (this == &req) return *this; verb = req.verb; rsrc = req.rsrc; queries = req.queries; header = req.header; cType = req.cType; body = req.body; return* this; } Verb Request::GetVerb() const { return verb; } void Request::SetContentType(const ContentType cType) { if (body.Size()) body.Resize(0); this->cType = cType; } ContentType Request::GetContentType() const { return cType; } void Request::SetResource(const Str_8& rsrc) { this->rsrc = rsrc; } Str_8 Request::GetResource() const { return rsrc; } void Request::AddQuery(const Str_8& var, const Str_8& value) { queries.Push(var + "=" + value); } Str_8 Request::GetQuery(const Str_8& var) { for (UInt_64 i = 0; i < queries.Size(); ++i) { Vector data = queries[i].Split("="); if (data[0] == var) return data[1]; } return ""; } Vector Request::GetQueries() const { return queries; } void Request::BasicAuth(const Str_8& id, const Str_8& secret) { AddToHeader("Authorization", Str_8("Basic ") + Base64::Encode(id + ":" + secret)); } void Request::BearerAuth(const Str_8& token) { AddToHeader("Authorization", "Bearer " + token); } void Request::BearerAuth(const Str_8& token, const Str_8& clientId) { AddToHeader("Authorization", "Bearer " + token); AddToHeader("Client-Id", clientId); } void Request::BotAuth(const Str_8& token) { AddToHeader("Authorization", "Bot " + token); } void Request::AddToHeader(const Str_8& var, const Str_8& value) { header.Push(var + ": " + value); } Str_8 Request::GetHeader(const Str_8& var) const { for (UInt_64 i = 0; i < header.Size(); ++i) { Vector data = header[i].Split(": "); if (data[0] == var) return data[1]; } return ""; } Vector Request::GetHeader() const { return header; } void Request::AddToBody(const Str_8& var, const Str_8& value) { if (body.Size()) { if (cType == ContentType::APP_FORMURLENCODED) body.Push('&'); } body += var; if (cType == ContentType::APP_FORMURLENCODED) body += "="; body += value; } void Request::AddToBody(const Str_8& data) { if (body.Size()) { if (cType == ContentType::APP_FORMURLENCODED) body.Push('&'); } body += data; } void Request::SetBody(const Str_8& body) { this->body = body; } Str_8 Request::GetVar(const Str_8& var) const { Vector vars; if (cType == ContentType::APP_FORMURLENCODED) vars = body.Split("&"); for (UInt_64 i = 0; i < vars.Size(); ++i) { Vector data = vars[i].Split("="); if (data[0] == var) return data[1]; } return ""; } Str_8 Request::GetBody() const { return body; } Json Request::GetJson() const { return {body, 5}; } Str_8 Request::FormResult() const { Str_8 result = VerbToStr(verb) + " " + rsrc; if (queries.Size()) result += "?" + queries[0]; for (UInt_64 i = 1; i < queries.Size(); ++i) result += "&" + queries[i]; result += " HTTP/1.1\r\n"; for (UInt_64 i = 0; i < header.Size(); ++i) { result += header[i] + "\r\n"; } result += "Content-Type: " + ContentTypeToStr(cType) + "\r\n"; if (verb == Verb::GET) result += "\r\n"; else result += "Content-Length: " + Str_8::FromNum(body.Size()) + "\r\n\r\n" + body; return result; } bool Request::IsValid() const { return rsrc.Size() || queries.Size() || header.Size() || body.Size(); } Str_8 Request::VerbToStr(const Verb verb) { switch (verb) { case Verb::POST: return "POST"; case Verb::GET: return "GET"; case Verb::PUT: return "PUT"; case Verb::DEL: return "DELETE"; default: return ""; } } Str_8 Request::ContentTypeToStr(const ContentType cType) { switch (cType) { case ContentType::APP_MULTIPART_FORMDATA: return "multipart/form-data"; case ContentType::APP_FORMURLENCODED: return "application/x-www-form-urlencoded"; case ContentType::APP_JAVASCRIPT: return "application/javascript"; case ContentType::APP_JSON: return "application/json"; case ContentType::APP_XML: return "application/xml"; case ContentType::TEXT_PLAIN: return "text/plain"; case ContentType::TEXT_HTML: return "text/html"; case ContentType::TEXT_XML: return "text/xml"; default: return ""; } } ContentType Request::StrToContentType(const Str_8& value) { if (value == "multipart/form-data") return ContentType::APP_MULTIPART_FORMDATA; else if (value == "application/x-www-form-urlencoded") return ContentType::APP_FORMURLENCODED; else if (value == "application/javascript") return ContentType::APP_JAVASCRIPT; else if (value == "application/json") return ContentType::APP_JSON; else if (value == "application/xml") return ContentType::APP_XML; else if (value == "text/plain") return ContentType::TEXT_PLAIN; else if (value == "text/html") return ContentType::TEXT_HTML; else if (value == "text/xml") return ContentType::TEXT_XML; else return ContentType::NONE; } void Request::ReadData(const Str_8& data) { Vector lines = data.Split("\r\n"); Vector meta = lines[0].Split(" "); if (meta[0] == "POST") verb = Verb::POST; else if (meta[0] == "GET") verb = Verb::GET; else if (meta[0] == "PUT") verb = Verb::PUT; UInt_64 queryIndex = 0; if (meta[1].Find("?", &queryIndex)) { rsrc = meta[1].Sub(0, queryIndex); cType = ContentType::APP_FORMURLENCODED; queries = meta[1].Sub(queryIndex + 1).Split("&"); } else { rsrc = meta[1]; } for (UInt_64 i = 1; i < lines.Size(); ++i) { if (!lines[i].Size()) break; Vector var = lines[i].Split(": "); if (var[0] == "Content-Type") { cType = StrToContentType(var[1]); continue; } if (var[0] == "Content-Length") continue; header.Push(lines[i]); } } }