HTTP cleanup & better defaults

This commit is contained in:
mhilbrunner
2017-12-12 20:02:25 +01:00
parent 55962ce28f
commit 966c054fc9
5 changed files with 131 additions and 132 deletions

View File

@ -30,27 +30,53 @@
#include "http_client.h"
#include "io/stream_peer_ssl.h"
const char *HTTPClient::_methods[METHOD_MAX] = {
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"OPTIONS",
"TRACE",
"CONNECT",
"PATCH"
};
#ifndef JAVASCRIPT_ENABLED
Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, bool p_verify_host) {
close();
conn_port = p_port;
conn_host = p_host;
if (conn_host.begins_with("http://")) {
ssl = p_ssl;
ssl_verify_host = p_verify_host;
String host_lower = conn_host.to_lower();
if (host_lower.begins_with("http://")) {
conn_host = conn_host.replace_first("http://", "");
} else if (conn_host.begins_with("https://")) {
//use https
} else if (host_lower.begins_with("https://")) {
ssl = true;
conn_host = conn_host.replace_first("https://", "");
}
ssl = p_ssl;
ssl_verify_host = p_verify_host;
ERR_FAIL_COND_V(conn_host.length() < HOST_MIN_LEN, ERR_INVALID_PARAMETER);
if (conn_port < 0) {
if (ssl) {
conn_port = PORT_HTTPS;
} else {
conn_port = PORT_HTTP;
}
}
connection = tcp_connection;
if (conn_host.is_valid_ip_address()) {
//is ip
// Host contains valid IP
Error err = tcp_connection->connect_to_host(IP_Address(conn_host), p_port);
if (err) {
status = STATUS_CANT_CONNECT;
@ -59,7 +85,7 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl,
status = STATUS_CONNECTING;
} else {
//is hostname
// Host contains hostname and needs to be resolved to IP
resolving = IP::get_singleton()->resolve_hostname_queue_item(conn_host);
status = STATUS_RESOLVING;
}
@ -82,24 +108,13 @@ Ref<StreamPeer> HTTPClient::get_connection() const {
Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) {
ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
static const char *_methods[METHOD_MAX] = {
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"OPTIONS",
"TRACE",
"CONNECT",
"PATCH"
};
String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
if ((ssl && conn_port == 443) || (!ssl && conn_port == 80)) {
// don't append the standard ports
if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) {
// Don't append the standard ports
request += "Host: " + conn_host + "\r\n";
} else {
request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
@ -113,17 +128,20 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector
}
if (add_clen) {
request += "Content-Length: " + itos(p_body.size()) + "\r\n";
//should it add utf8 encoding? not sure
// Should it add utf8 encoding?
}
request += "\r\n";
CharString cs = request.utf8();
PoolVector<uint8_t> data;
//Maybe this goes faster somehow?
for (int i = 0; i < cs.length(); i++) {
data.append(cs[i]);
data.resize(cs.length());
{
PoolVector<uint8_t>::Write data_write = data.write();
for (int i = 0; i < cs.length(); i++) {
data_write[i] = cs[i];
}
}
data.append_array(p_body);
PoolVector<uint8_t>::Read r = data.read();
@ -143,24 +161,13 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector
Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) {
ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
static const char *_methods[METHOD_MAX] = {
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"OPTIONS",
"TRACE",
"CONNECT",
"PATCH"
};
String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
if ((ssl && conn_port == 443) || (!ssl && conn_port == 80)) {
// don't append the standard ports
if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) {
// Don't append the standard ports
request += "Host: " + conn_host + "\r\n";
} else {
request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
@ -174,7 +181,7 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str
}
if (add_clen) {
request += "Content-Length: " + itos(p_body.utf8().length()) + "\r\n";
//should it add utf8 encoding? not sure
// Should it add utf8 encoding?
}
request += "\r\n";
request += p_body;
@ -253,7 +260,7 @@ Error HTTPClient::poll() {
IP::ResolverStatus rstatus = IP::get_singleton()->get_resolve_item_status(resolving);
switch (rstatus) {
case IP::RESOLVER_STATUS_WAITING:
return OK; //still resolving
return OK; // Still resolving
case IP::RESOLVER_STATUS_DONE: {
@ -285,7 +292,7 @@ Error HTTPClient::poll() {
switch (s) {
case StreamPeerTCP::STATUS_CONNECTING: {
return OK; //do none
return OK;
} break;
case StreamPeerTCP::STATUS_CONNECTED: {
if (ssl) {
@ -296,7 +303,6 @@ Error HTTPClient::poll() {
status = STATUS_SSL_HANDSHAKE_ERROR;
return ERR_CANT_CONNECT;
}
//print_line("SSL! TURNED ON!");
connection = ssl;
}
status = STATUS_CONNECTED;
@ -312,7 +318,7 @@ Error HTTPClient::poll() {
}
} break;
case STATUS_CONNECTED: {
//request something please
// Connection established, requests can now be made
return OK;
} break;
case STATUS_REQUESTING: {
@ -328,7 +334,7 @@ Error HTTPClient::poll() {
}
if (rec == 0)
return OK; //keep trying!
return OK; // Still requesting, keep trying!
response_str.push_back(byte);
int rs = response_str.size();
@ -336,11 +342,10 @@ Error HTTPClient::poll() {
(rs >= 2 && response_str[rs - 2] == '\n' && response_str[rs - 1] == '\n') ||
(rs >= 4 && response_str[rs - 4] == '\r' && response_str[rs - 3] == '\n' && response_str[rs - 2] == '\r' && response_str[rs - 1] == '\n')) {
//end of response, parse.
// End of response, parse.
response_str.push_back(0);
String response;
response.parse_utf8((const char *)response_str.ptr());
//print_line("END OF RESPONSE? :\n"+response+"\n------");
Vector<String> responses = response.split("\n");
body_size = 0;
chunked = false;
@ -363,7 +368,6 @@ Error HTTPClient::poll() {
if (s.begins_with("transfer-encoding:")) {
String encoding = header.substr(header.find(":") + 1, header.length()).strip_edges();
//print_line("TRANSFER ENCODING: "+encoding);
if (encoding == "chunked") {
chunked = true;
}
@ -381,14 +385,14 @@ Error HTTPClient::poll() {
if (body_size == 0 && !chunked) {
status = STATUS_CONNECTED; //ask for something again?
status = STATUS_CONNECTED; // Ready for new requests
} else {
status = STATUS_BODY;
}
return OK;
}
}
//wait for response
// Wait for response
return OK;
} break;
case STATUS_DISCONNECTED: {
@ -424,7 +428,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
while (true) {
if (chunk_left == 0) {
//reading len
// Reading length
uint8_t b;
int rec = 0;
err = _get_http_data(&b, 1, rec);
@ -467,7 +471,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
}
if (len == 0) {
//end!
// End reached!
status = STATUS_CONNECTED;
chunk.clear();
return PoolByteArray();
@ -525,7 +529,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
to_read -= rec;
_offset += rec;
} else {
if (to_read > 0) //ended up reading less
if (to_read > 0) // Ended up reading less
ret.resize(_offset);
break;
}
@ -540,7 +544,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
close();
if (err == ERR_FILE_EOF) {
status = STATUS_DISCONNECTED; //server disconnected
status = STATUS_DISCONNECTED; // Server disconnected
} else {
status = STATUS_CONNECTION_ERROR;
@ -593,7 +597,7 @@ HTTPClient::HTTPClient() {
tcp_connection = StreamPeerTCP::create_ref();
resolving = IP::RESOLVER_INVALID_ID;
status = STATUS_DISCONNECTED;
conn_port = 80;
conn_port = -1;
body_size = 0;
chunked = false;
body_left = 0;
@ -653,7 +657,7 @@ PoolStringArray HTTPClient::_get_response_headers() {
void HTTPClient::_bind_methods() {
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_ssl", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_ssl", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(-1), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("set_connection", "connection"), &HTTPClient::set_connection);
ClassDB::bind_method(D_METHOD("get_connection"), &HTTPClient::get_connection);
ClassDB::bind_method(D_METHOD("request_raw", "method", "url", "headers", "body"), &HTTPClient::request_raw);
@ -689,13 +693,13 @@ void HTTPClient::_bind_methods() {
BIND_ENUM_CONSTANT(METHOD_MAX);
BIND_ENUM_CONSTANT(STATUS_DISCONNECTED);
BIND_ENUM_CONSTANT(STATUS_RESOLVING); //resolving hostname (if passed a hostname)
BIND_ENUM_CONSTANT(STATUS_RESOLVING); // Resolving hostname (if hostname was passed in)
BIND_ENUM_CONSTANT(STATUS_CANT_RESOLVE);
BIND_ENUM_CONSTANT(STATUS_CONNECTING); //connecting to ip
BIND_ENUM_CONSTANT(STATUS_CONNECTING); // Connecting to IP
BIND_ENUM_CONSTANT(STATUS_CANT_CONNECT);
BIND_ENUM_CONSTANT(STATUS_CONNECTED); //connected ); requests only accepted here
BIND_ENUM_CONSTANT(STATUS_REQUESTING); // request in progress
BIND_ENUM_CONSTANT(STATUS_BODY); // request resulted in body ); which must be read
BIND_ENUM_CONSTANT(STATUS_CONNECTED); // Connected, now accepting requests
BIND_ENUM_CONSTANT(STATUS_REQUESTING); // Request in progress
BIND_ENUM_CONSTANT(STATUS_BODY); // Request resulted in body which must be read
BIND_ENUM_CONSTANT(STATUS_CONNECTION_ERROR);
BIND_ENUM_CONSTANT(STATUS_SSL_HANDSHAKE_ERROR);