summaryrefslogtreecommitdiff
path: root/core/io/http_client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/io/http_client.cpp')
-rw-r--r--core/io/http_client.cpp128
1 files changed, 66 insertions, 62 deletions
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 9d89baafb1..c865ce4669 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -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);