http.get is now operational

This commit is contained in:
2022-05-06 13:16:27 -04:00
parent c41d0522df
commit 0ee4167772
7 changed files with 174 additions and 98 deletions

View File

@@ -186,21 +186,21 @@ public:
}
};
HttpOutRequest::HttpOutRequest() {
verify_certificate_ = true;
HttpClientRequest::HttpClientRequest() {
verify_certificate_ = false;
port_ = 0;
request_id_ = 0;
place_id_ = 0;
thread_id_ = 0;
}
void HttpOutRequest::fail(string_view s) {
void HttpClientRequest::fail(string_view s) {
if (error_.empty()) {
error_ = s;
}
}
eng::string HttpOutRequest::target() const {
eng::string HttpClientRequest::target() const {
assert(check().empty());
eng::ostringstream oss;
oss << (verify_certificate_ ? "cert" : "nocert");
@@ -208,11 +208,11 @@ eng::string HttpOutRequest::target() const {
return oss.str();
}
void HttpOutRequest::set_verify_certificate(bool flag) {
void HttpClientRequest::set_verify_certificate(bool flag) {
verify_certificate_ = flag;
}
void HttpOutRequest::set_method(const eng::string &s) {
void HttpClientRequest::set_method(const eng::string &s) {
eng::string method = util::ascii_toupper(s);
if ((method != "GET") && (method != "HEAD")) {
fail(util::ss("HTTP method not implemented: ", method, ".",
@@ -226,7 +226,7 @@ void HttpOutRequest::set_method(const eng::string &s) {
method_ = method;
}
void HttpOutRequest::set_host(const eng::string &s) {
void HttpClientRequest::set_host(const eng::string &s) {
eng::string host = util::ascii_tolower(s);
if (host.empty()) {
fail(util::ss("HTTP hostname cannot be empty string."));
@@ -247,7 +247,7 @@ void HttpOutRequest::set_host(const eng::string &s) {
host_ = host;
}
void HttpOutRequest::set_port(int port) {
void HttpClientRequest::set_port(int port) {
if ((port < 1) || (port > 65535)) {
fail(util::ss("HTTP port must be between 1 and 65535: ", port));
return;
@@ -259,7 +259,7 @@ void HttpOutRequest::set_port(int port) {
port_ = port;
}
void HttpOutRequest::set_path(string_view path) {
void HttpClientRequest::set_path(string_view path) {
if (!sv::has_prefix(path, "/")) {
fail(util::ss("HTTP path must start with slash"));
return;
@@ -271,7 +271,7 @@ void HttpOutRequest::set_path(string_view path) {
path_ = path;
}
void HttpOutRequest::set_param(const eng::string &key, const eng::string &val) {
void HttpClientRequest::set_param(const eng::string &key, const eng::string &val) {
if (params_.find(key) != params_.end()) {
fail(util::ss("HTTP url parameter specified twice: ", key));
return;
@@ -283,7 +283,7 @@ void HttpOutRequest::set_param(const eng::string &key, const eng::string &val) {
params_[key] = val;
}
void HttpOutRequest::set_url(string_view url) {
void HttpClientRequest::set_url(string_view url) {
ParsedURL parsed_url(url);
if (!parsed_url.valid) {
fail(util::ss("syntactically invalid URL: ", url));
@@ -301,7 +301,7 @@ void HttpOutRequest::set_url(string_view url) {
}
}
void HttpOutRequest::set_verify_certificate(LuaStack &LS, LuaSlot val) {
void HttpClientRequest::set_verify_certificate(LuaStack &LS, LuaSlot val) {
if (!LS.isboolean(val)) {
fail(util::ss("HTTP verify_certificate must be a boolean"));
return;
@@ -309,7 +309,7 @@ void HttpOutRequest::set_verify_certificate(LuaStack &LS, LuaSlot val) {
set_verify_certificate(LS.ckboolean(val));
}
void HttpOutRequest::set_method(LuaStack &LS, LuaSlot val) {
void HttpClientRequest::set_method(LuaStack &LS, LuaSlot val) {
if (!LS.isstring(val)) {
fail(util::ss("HTTP method must be a string"));
return;
@@ -317,7 +317,7 @@ void HttpOutRequest::set_method(LuaStack &LS, LuaSlot val) {
set_method(LS.ckstring(val));
}
void HttpOutRequest::set_host(LuaStack &LS, LuaSlot val) {
void HttpClientRequest::set_host(LuaStack &LS, LuaSlot val) {
if (!LS.isstring(val)) {
fail(util::ss("HTTP host must be a string"));
return;
@@ -325,7 +325,7 @@ void HttpOutRequest::set_host(LuaStack &LS, LuaSlot val) {
set_host(LS.ckstring(val));
}
void HttpOutRequest::set_port(LuaStack &LS, LuaSlot val) {
void HttpClientRequest::set_port(LuaStack &LS, LuaSlot val) {
if (!LS.isint(val)) {
fail(util::ss("HTTP port must be an int"));
return;
@@ -333,7 +333,7 @@ void HttpOutRequest::set_port(LuaStack &LS, LuaSlot val) {
set_port(LS.ckint(val));
}
void HttpOutRequest::set_path(LuaStack &LS, LuaSlot val) {
void HttpClientRequest::set_path(LuaStack &LS, LuaSlot val) {
if (!LS.isstring(val)) {
fail(util::ss("HTTP path must be a string"));
return;
@@ -341,7 +341,7 @@ void HttpOutRequest::set_path(LuaStack &LS, LuaSlot val) {
set_path(LS.ckstring(val));
}
void HttpOutRequest::set_param(LuaStack &LS, LuaSlot key, LuaSlot val) {
void HttpClientRequest::set_param(LuaStack &LS, LuaSlot key, LuaSlot val) {
if (!LS.isstring(key)) {
fail(util::ss("HTTP url parameter key must be a string"));
return;
@@ -353,7 +353,7 @@ void HttpOutRequest::set_param(LuaStack &LS, LuaSlot key, LuaSlot val) {
set_param(LS.ckstring(key), LS.ckstring(val));
}
void HttpOutRequest::set_params(LuaStack &LS0, LuaSlot tab) {
void HttpClientRequest::set_params(LuaStack &LS0, LuaSlot tab) {
if (!LS0.istable(tab)) {
fail(util::ss("HTTP params must be a table"));
return;
@@ -366,7 +366,7 @@ void HttpOutRequest::set_params(LuaStack &LS0, LuaSlot tab) {
}
}
void HttpOutRequest::set_url(LuaStack &LS, LuaSlot val) {
void HttpClientRequest::set_url(LuaStack &LS, LuaSlot val) {
if (!LS.isstring(val)) {
fail(util::ss("HTTP url must be a string"));
return;
@@ -374,7 +374,7 @@ void HttpOutRequest::set_url(LuaStack &LS, LuaSlot val) {
set_url(LS.ckstring(val));
}
void HttpOutRequest::set_defaults() {
void HttpClientRequest::set_defaults() {
if (method_.empty()) {
method_ = "GET";
}
@@ -383,7 +383,7 @@ void HttpOutRequest::set_defaults() {
}
}
void HttpOutRequest::set_config(LuaStack &LS0, LuaSlot tab) {
void HttpClientRequest::set_config(LuaStack &LS0, LuaSlot tab) {
LuaVar key, val;
LuaStack LS(LS0.state(), key, val);
LS.set(key, LuaNil);
@@ -412,7 +412,7 @@ void HttpOutRequest::set_config(LuaStack &LS0, LuaSlot tab) {
}
}
eng::string HttpOutRequest::check() const {
eng::string HttpClientRequest::check() const {
if (!error_.empty()) {
return error_;
}
@@ -432,7 +432,7 @@ eng::string HttpOutRequest::check() const {
}
void HttpOutRequest::send_internal(StreamBuffer *sb, bool debug_string) const {
void HttpClientRequest::send_internal(StreamBuffer *sb, bool debug_string) const {
// If there's an error in the request, handle it. In debug string mode,
// we just put the error into the output. In production mode, we assert
// fail.
@@ -484,7 +484,7 @@ void HttpOutRequest::send_internal(StreamBuffer *sb, bool debug_string) const {
}
}
void HttpOutRequest::serialize(StreamBuffer *sb) const {
void HttpClientRequest::serialize(StreamBuffer *sb) const {
sb->write_int64(request_id_);
sb->write_int64(place_id_);
sb->write_int64(thread_id_);
@@ -501,7 +501,7 @@ void HttpOutRequest::serialize(StreamBuffer *sb) const {
}
}
void HttpOutRequest::deserialize(StreamBuffer *sb) {
void HttpClientRequest::deserialize(StreamBuffer *sb) {
request_id_ = sb->read_int64();
place_id_ = sb->read_int64();
thread_id_ = sb->read_int64();
@@ -520,39 +520,40 @@ void HttpOutRequest::deserialize(StreamBuffer *sb) {
}
}
eng::string HttpOutRequest::DebugString() {
eng::string HttpClientRequest::DebugString() {
StreamBuffer sb;
send_internal(&sb, true);
return eng::string(sb.view());
}
void HttpOutRequestMap::serialize(StreamBuffer *sb) const {
void HttpClientRequestMap::serialize(StreamBuffer *sb) const {
sb->write_int32(size());
for (const auto &pair : *this) {
pair.second.serialize(sb);
}
}
void HttpOutRequestMap::deserialize(StreamBuffer *sb) {
void HttpClientRequestMap::deserialize(StreamBuffer *sb) {
int32_t count = sb->read_int32();
clear();
HttpOutRequest req;
HttpClientRequest req;
for (int i = 0; i < count; i++) {
req.deserialize(sb);
(*this)[req.request_id()] = req;
}
}
HttpInResponse::HttpInResponse() {
HttpClientResponse::HttpClientResponse() {
request_id_ = 0;
status_code_ = 0;
response_length_ = 0;
mime_type_ = "";
content_length_ = -1;
}
eng::string HttpInResponse::DebugString() const {
eng::string HttpClientResponse::DebugString() const {
eng::ostringstream oss;
oss << "HttpInResponse:" << std::endl;
oss << "HttpClientResponse:" << std::endl;
oss << " status_code: " << status_code_ << std::endl;
oss << " error: " << error_ << std::endl;
oss << " content_length: " << content_length_ << std::endl;
@@ -565,7 +566,7 @@ eng::string HttpInResponse::DebugString() const {
return oss.str();
}
void HttpInResponse::fail(int code, string_view message) {
void HttpClientResponse::fail(int code, string_view message) {
status_code_ = code;
error_ = message;
mime_type_ = "";
@@ -573,7 +574,7 @@ void HttpInResponse::fail(int code, string_view message) {
content_ = "";
}
void HttpInResponse::incomplete(bool closed) {
void HttpClientResponse::incomplete(bool closed) {
if (closed) {
fail(500, "internal server error: response truncated");
} else {
@@ -581,11 +582,11 @@ void HttpInResponse::incomplete(bool closed) {
}
}
void HttpInResponse::parse_content_encoding(string_view value) {
void HttpClientResponse::parse_content_encoding(string_view value) {
content_encoding_ = util::ascii_tolower(value);
}
void HttpInResponse::parse_content_length(string_view value) {
void HttpClientResponse::parse_content_length(string_view value) {
int64_t code = sv::to_int64(value);
if ((code < 0) || (code > INT_MAX)) {
fail(500, util::ss("internal server error: unparseable content-length: ", value));
@@ -593,7 +594,7 @@ void HttpInResponse::parse_content_length(string_view value) {
content_length_ = code;
}
void HttpInResponse::parse_content_type(string_view value) {
void HttpClientResponse::parse_content_type(string_view value) {
eng::string ctype = util::ascii_tolower(value);
string_view ctview(ctype);
mime_type_ = sv::trim(sv::read_to_sep(ctview, ';'));
@@ -613,15 +614,15 @@ void HttpInResponse::parse_content_type(string_view value) {
}
}
void HttpInResponse::parse_location(string_view value) {
void HttpClientResponse::parse_location(string_view value) {
location_ = url_decode(value);
}
void HttpInResponse::parse_transfer_encoding(string_view value) {
void HttpClientResponse::parse_transfer_encoding(string_view value) {
transfer_encoding_ = util::ascii_tolower(value);
}
void HttpInResponse::parse_header(string_view header, string_view value) {
void HttpClientResponse::parse_header(string_view header, string_view value) {
if (header == "content-encoding") {
parse_content_encoding(value);
} else if (header == "content-length") {
@@ -637,7 +638,7 @@ void HttpInResponse::parse_header(string_view header, string_view value) {
}
}
bool HttpInResponse::parse_content_basic(std::string_view &view, bool closed) {
bool HttpClientResponse::parse_content_basic(std::string_view &view, bool closed) {
if (content_length_ >= 0) {
if (content_length_ > MAX_CONTENT_LENGTH) {
fail(413, util::ss("payload too large: luprex limit=", MAX_CONTENT_LENGTH));
@@ -662,7 +663,7 @@ bool HttpInResponse::parse_content_basic(std::string_view &view, bool closed) {
return true;
}
bool HttpInResponse::parse_content_chunked(std::string_view &view, bool closed) {
bool HttpClientResponse::parse_content_chunked(std::string_view &view, bool closed) {
int64_t total_size = 0;
std::vector<string_view> chunks;
while (true) {
@@ -711,7 +712,7 @@ bool HttpInResponse::parse_content_chunked(std::string_view &view, bool closed)
return true;
}
void HttpInResponse::parse(const StreamBuffer *sb, bool closed) {
void HttpClientResponse::parse(const StreamBuffer *sb, bool closed) {
// We're not going to modify the StreamBuffer at all.
// Instead, we work entirely on a view.
string_view view = sb->view();
@@ -724,19 +725,26 @@ void HttpInResponse::parse(const StreamBuffer *sb, bool closed) {
}
// Parse the status line.
string_view protoversion = sv::read_to_space(status);
if (!sv::has_prefix(protoversion, "HTTP/")) {
fail(500, util::ss("internal server error: status line appears corrupt"));
return;
}
string_view scode = sv::read_to_space(status);
int64_t code = sv::to_int64(scode, 0);
if ((code < 100) || (code > 599)) {
fail(500, util::ss("internal server error: invalid response code: ", scode));
return;
}
status_code_ = code;
// Responses outside the range 200-299 are errors,
// and therefore must store an error message.
if ((code < 200) || (code > 299)) {
error_ = status;
if (error_.empty()) {
fail(code, util::ss("error code ", code));
if (status.empty()) {
error_ = util::ss("error code ", code);
} else {
error_ = status;
}
}
@@ -829,7 +837,7 @@ void HttpInResponse::parse(const StreamBuffer *sb, bool closed) {
}
}
void HttpInResponse::store(LuaStack &LS0, LuaSlot tab) const {
void HttpClientResponse::store(LuaStack &LS0, LuaSlot tab) const {
LuaStack LS(LS0.state());
LS.newtable(tab);
@@ -860,8 +868,8 @@ void HttpInResponse::store(LuaStack &LS0, LuaSlot tab) const {
}
}
void HttpInResponse::store_fail(LuaStack &LS, LuaSlot tab, int status_code, std::string_view error) {
HttpInResponse response;
void HttpClientResponse::store_fail(LuaStack &LS, LuaSlot tab, int status_code, std::string_view error) {
HttpClientResponse response;
response.fail(status_code, error);
response.store(LS, tab);
}
@@ -912,7 +920,7 @@ LuaDefine(http_request, "request",
LuaArg tab;
LuaRet str;
LuaStack LS(L, tab, str);
HttpOutRequest req;
HttpClientRequest req;
req.set_config(LS, tab);
req.set_defaults();
eng::string error = req.check();
@@ -969,7 +977,7 @@ LuaDefine(http_response, "response",
LuaArg text;
LuaRet tab;
LuaStack LS(L, text, tab);
HttpInResponse resp;
HttpClientResponse resp;
StreamBuffer sb;
sb.write_bytes(LS.ckstring(text));
resp.parse(&sb, true);