Can now parse HTTP responses.
This commit is contained in:
@@ -20,7 +20,9 @@
|
||||
#include "luastack.hpp"
|
||||
#include "streambuffer.hpp"
|
||||
|
||||
class HttpRequest : public eng::nevernew {
|
||||
using UrlParameters = eng::map<eng::string, eng::string>;
|
||||
|
||||
class HttpOutRequest : public eng::nevernew {
|
||||
private:
|
||||
// If the request contains an error, the error
|
||||
// message is stored here.
|
||||
@@ -40,24 +42,26 @@ private:
|
||||
// Port number.
|
||||
int port_;
|
||||
|
||||
// The path is always UTF-8. This field should not be urlencoded.
|
||||
// Instead, urlencoding is done automatically when the request
|
||||
// is sent. Should not include protocol, host, port, or parameters.
|
||||
// You may specify either path or encoded_path.
|
||||
// The path is not url-encoded, and must not include URL parameters.
|
||||
eng::string path_;
|
||||
|
||||
// If params is nonempty, then we will add URL parameters
|
||||
// to the URL. The contents of the params field should not be
|
||||
// urlencoded, the urlencoding is done automatically when the
|
||||
// request is sent.
|
||||
eng::map<eng::string, eng::string> params_;
|
||||
// request is sent. If you specify encoded_path, then the
|
||||
// params must be empty, because the encoded path already contains
|
||||
// the params.
|
||||
UrlParameters params_;
|
||||
|
||||
private:
|
||||
void send_internal(StreamBuffer *target, bool debug_string) const;
|
||||
void fail(std::string_view error);
|
||||
|
||||
void send_internal(StreamBuffer *target, bool debug_string) const;
|
||||
public:
|
||||
// Construct an empty HTTP request.
|
||||
// All of the fields have empty values.
|
||||
HttpRequest();
|
||||
HttpOutRequest();
|
||||
|
||||
// Get fields.
|
||||
const eng::string &error() const { return error_; }
|
||||
@@ -80,17 +84,19 @@ public:
|
||||
void set_method(const eng::string &method);
|
||||
void set_host(const eng::string &host);
|
||||
void set_port(int port);
|
||||
void set_url(const eng::string &url);
|
||||
void set_path(std::string_view path);
|
||||
void set_param(const eng::string &key, const eng::string &value);
|
||||
|
||||
void set_url(std::string_view url);
|
||||
|
||||
// Same as above, but using Lua values.
|
||||
void set_verify_certificate(LuaStack &LS, LuaSlot val);
|
||||
void set_method(LuaStack &LS, LuaSlot val);
|
||||
void set_host(LuaStack &LS, LuaSlot val);
|
||||
void set_port(LuaStack &LS, LuaSlot val);
|
||||
void set_url(LuaStack &LS, LuaSlot val);
|
||||
void set_path(LuaStack &LS, LuaSlot path);
|
||||
void set_param(LuaStack &LS, LuaSlot key, LuaSlot val);
|
||||
void set_params(LuaStack &LS, LuaSlot tab);
|
||||
void set_url(LuaStack &LS, LuaSlot val);
|
||||
|
||||
// Set default values for any fields that should have
|
||||
// defaults. This must be done after setting regular
|
||||
@@ -111,48 +117,94 @@ public:
|
||||
eng::string DebugString();
|
||||
};
|
||||
|
||||
class HttpResponse {
|
||||
class HttpInResponse {
|
||||
private:
|
||||
// The HTTP response code.
|
||||
int response_code_;
|
||||
|
||||
// The HTTP response status code.
|
||||
int status_code_;
|
||||
|
||||
// If the HTTP response contains an error, the
|
||||
// error message is stored here. If the HTTP response
|
||||
// is a success such as "200 OK" or "201 Created", this
|
||||
// is the empty string, not "OK" or "Created".
|
||||
eng::string error_;
|
||||
|
||||
// The length in bytes of the entire response.
|
||||
// May be zero, which means that the response
|
||||
// was so garbled that we couldn't determine the length.
|
||||
bool response_length_;
|
||||
|
||||
// Only if content-length header present, otherwise, -1.
|
||||
int64_t content_length_;
|
||||
|
||||
// If empty, it means there was no transfer-encoding header.
|
||||
eng::string transfer_encoding_;
|
||||
|
||||
// If empty, it means there was no content-encoding header.
|
||||
eng::string content_encoding_;
|
||||
|
||||
// Only if location header present.
|
||||
eng::string location_;
|
||||
|
||||
// MIME type of the content.
|
||||
eng::string mime_type_;
|
||||
|
||||
// Charset of the content. Hopefully utf-8.
|
||||
eng::string charset_;
|
||||
|
||||
// The content as string.
|
||||
eng::string content_;
|
||||
|
||||
// The length in bytes of the entire response.
|
||||
// May be zero, which means that the response
|
||||
// was so garbled that we couldn't determine the length.
|
||||
int response_length_;
|
||||
|
||||
private:
|
||||
// Store a message indicating that we haven't received enough
|
||||
// bytes yet. If the connection is closed and we still haven't
|
||||
// received enough bytes, that's a fatal error.
|
||||
void incomplete(bool closed);
|
||||
|
||||
// Parse a response header. Most headers are ignored.
|
||||
// If the header contains an error, the error is stored.
|
||||
void parse_header(std::string_view header, std::string_view value);
|
||||
|
||||
// Parse specific headers.
|
||||
// For several headers, all we do is verify that they aren't
|
||||
// invoking unsupported features.
|
||||
void parse_content_encoding(std::string_view value);
|
||||
void parse_content_length(std::string_view value);
|
||||
void parse_content_type(std::string_view value);
|
||||
void parse_location(std::string_view value);
|
||||
void parse_transfer_encoding(std::string_view value);
|
||||
|
||||
// parse the body
|
||||
bool parse_content_basic(std::string_view &view, bool closed);
|
||||
bool parse_content_chunked(std::string_view &view, bool closed);
|
||||
public:
|
||||
const int64_t MAX_CONTENT_LENGTH = 1000000;
|
||||
|
||||
// Construct a blank response.
|
||||
HttpResponse();
|
||||
HttpInResponse();
|
||||
|
||||
// Store an error message. This is used when the client detects an error,
|
||||
// Store a result code and an error message, and clear the content.
|
||||
// This is generally used when the client detects an error,
|
||||
// such as a DNS lookup fail, a connection failed, an SSL negotiation
|
||||
// failed, or the like. Clears the content, leaving only the error
|
||||
// and response code.
|
||||
void fail(int response_code, const eng::string &error);
|
||||
// failed, or the like.
|
||||
void fail(int status_code, std::string_view error);
|
||||
|
||||
// Parse the HTTP response. Note that the response is not
|
||||
// removed from the StreamBuffer, which is always unmodified.
|
||||
// If you want to remove the response from the StreamBuffer, see
|
||||
// response_length.
|
||||
void parse(const StreamBuffer *sb);
|
||||
// Parse the HTTP response. The closed flag is to be set to true if the
|
||||
// remote has closed the connection.
|
||||
//
|
||||
// If the request is incomplete, generates a 600 incomplete error. In that
|
||||
// case, loading more data from the server might improve the situation.
|
||||
//
|
||||
// Note that the response is not ever removed from the StreamBuffer, which
|
||||
// is always unmodified. If you want to remove the response from the
|
||||
// StreamBuffer, see response_length.
|
||||
//
|
||||
void parse(const StreamBuffer *sb, bool closed);
|
||||
|
||||
// Convert the HTTP response to a lua table.
|
||||
void store(LuaStack &LS, LuaSlot tab);
|
||||
|
||||
// Convert to a debug string.
|
||||
eng::string DebugString() const;
|
||||
};
|
||||
|
||||
#endif // HTTP_HPP
|
||||
|
||||
Reference in New Issue
Block a user