Просмотр исходного кода

Allows HTTPClient to talk to proxy server

* Makes request uri accept absolute URL and authority
* Adds Host header only when missing

(cherry picked from commit d92ca6fbb173a86095d92c94462deb4581f2cc0d)
Haoyu Qiu 4 лет назад
Родитель
Сommit
8361caad86
1 измененных файлов с 45 добавлено и 15 удалено
  1. 45 15
      core/io/http_client.cpp

+ 45 - 15
core/io/http_client.cpp

@@ -114,25 +114,41 @@ Ref<StreamPeer> HTTPClient::get_connection() const {
 	return connection;
 }
 
-Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) {
+static bool _check_request_url(HTTPClient::Method p_method, const String &p_url) {
+	switch (p_method) {
+		case HTTPClient::METHOD_CONNECT: {
+			// Authority in host:port format, as in RFC7231
+			int pos = p_url.find_char(':');
+			return 0 < pos && pos < p_url.length() - 1;
+		}
+		case HTTPClient::METHOD_OPTIONS: {
+			if (p_url == "*") {
+				return true;
+			}
+			FALLTHROUGH;
+		}
+		default:
+			// Absolute path or absolute URL
+			return p_url.begins_with("/") || p_url.begins_with("http://") || p_url.begins_with("https://");
+	}
+}
 
+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(!_check_request_url(p_method, p_url), ERR_INVALID_PARAMETER);
 	ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
 	ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
 
 	String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
-	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";
-	}
+	bool add_host = true;
 	bool add_clen = p_body.size() > 0;
 	bool add_uagent = true;
 	bool add_accept = true;
 	for (int i = 0; i < p_headers.size(); i++) {
 		request += p_headers[i] + "\r\n";
+		if (add_host && p_headers[i].findn("Host:") == 0) {
+			add_host = false;
+		}
 		if (add_clen && p_headers[i].findn("Content-Length:") == 0) {
 			add_clen = false;
 		}
@@ -143,6 +159,14 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector
 			add_accept = false;
 		}
 	}
+	if (add_host) {
+		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";
+		}
+	}
 	if (add_clen) {
 		request += "Content-Length: " + itos(p_body.size()) + "\r\n";
 		// Should it add utf8 encoding?
@@ -185,22 +209,20 @@ 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(!_check_request_url(p_method, p_url), ERR_INVALID_PARAMETER);
 	ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
 	ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
 
 	String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
-	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";
-	}
+	bool add_host = true;
 	bool add_uagent = true;
 	bool add_accept = true;
 	bool add_clen = p_body.length() > 0;
 	for (int i = 0; i < p_headers.size(); i++) {
 		request += p_headers[i] + "\r\n";
+		if (add_host && p_headers[i].findn("Host:") == 0) {
+			add_host = false;
+		}
 		if (add_clen && p_headers[i].findn("Content-Length:") == 0) {
 			add_clen = false;
 		}
@@ -211,6 +233,14 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str
 			add_accept = false;
 		}
 	}
+	if (add_host) {
+		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";
+		}
+	}
 	if (add_clen) {
 		request += "Content-Length: " + itos(p_body.utf8().length()) + "\r\n";
 		// Should it add utf8 encoding?