Merge pull request #2822 from kurikaesu/master

HTTPClient docs & request functionality + fixes
This commit is contained in:
Juan Linietsky 2015-11-19 09:18:09 -03:00
commit 232b1a3fef
8 changed files with 119 additions and 8 deletions

View File

@ -579,7 +579,7 @@ Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received)
void HTTPClient::_bind_methods() { void HTTPClient::_bind_methods() {
ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true)); ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true));
ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection);
ObjectTypeDB::bind_method(_MD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String())); ObjectTypeDB::bind_method(_MD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String()));
ObjectTypeDB::bind_method(_MD("send_body_text","body"),&HTTPClient::send_body_text); ObjectTypeDB::bind_method(_MD("send_body_text","body"),&HTTPClient::send_body_text);
@ -601,6 +601,8 @@ void HTTPClient::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_status"),&HTTPClient::get_status); ObjectTypeDB::bind_method(_MD("get_status"),&HTTPClient::get_status);
ObjectTypeDB::bind_method(_MD("poll:Error"),&HTTPClient::poll); ObjectTypeDB::bind_method(_MD("poll:Error"),&HTTPClient::poll);
ObjectTypeDB::bind_method(_MD("query_string_from_dict:String","fields"),&HTTPClient::query_string_from_dict);
BIND_CONSTANT( METHOD_GET ); BIND_CONSTANT( METHOD_GET );
BIND_CONSTANT( METHOD_HEAD ); BIND_CONSTANT( METHOD_HEAD );
@ -689,6 +691,16 @@ void HTTPClient::set_read_chunk_size(int p_size) {
read_chunk_size=p_size; read_chunk_size=p_size;
} }
String HTTPClient::query_string_from_dict(const Dictionary& p_dict) {
String query = "";
Array keys = p_dict.keys();
for (int i = 0; i < keys.size(); ++i) {
query += "&" + String(keys[i]).http_escape() + "=" + String(p_dict[keys[i]]).http_escape();
}
query.erase(0, 1);
return query;
}
HTTPClient::HTTPClient(){ HTTPClient::HTTPClient(){
tcp_connection = StreamPeerTCP::create_ref(); tcp_connection = StreamPeerTCP::create_ref();
@ -710,4 +722,3 @@ HTTPClient::~HTTPClient(){
} }

View File

@ -192,6 +192,8 @@ public:
Error poll(); Error poll();
String query_string_from_dict(const Dictionary& p_dict);
HTTPClient(); HTTPClient();
~HTTPClient(); ~HTTPClient();
}; };

View File

@ -3079,6 +3079,48 @@ String String::world_wrap(int p_chars_per_line) const {
return ret; return ret;
} }
String String::http_escape() const {
const CharString temp = utf8();
String res;
for (int i = 0; i < length(); ++i) {
CharType ord = temp[i];
if (ord == '.' || ord == '-' || ord == '_' || ord == '~' ||
(ord >= 'a' && ord <= 'z') ||
(ord >= 'A' && ord <= 'Z') ||
(ord >= '0' && ord <= '9')) {
res += ord;
} else {
char h_Val[3];
snprintf(h_Val, 3, "%.2X", ord);
res += "%";
res += h_Val;
}
}
return res;
}
String String::http_unescape() const {
String res;
for (int i = 0; i < length(); ++i) {
if (ord_at(i) == '%' && i+2 < length()) {
CharType ord1 = ord_at(i+1);
if ((ord1 >= '0' && ord1 <= '9') || (ord1 >= 'A' && ord1 <= 'Z')) {
CharType ord2 = ord_at(i+2);
if ((ord2 >= '0' && ord2 <= '9') || (ord2 >= 'A' && ord2 <= 'Z')) {
char bytes[2] = {ord1, ord2};
res += (char)strtol(bytes, NULL, 16);
i+=2;
}
} else {
res += ord_at(i);
}
} else {
res += ord_at(i);
}
}
return String::utf8(res.ascii());
}
String String::c_unescape() const { String String::c_unescape() const {
String escaped=*this; String escaped=*this;

View File

@ -207,6 +207,8 @@ public:
String xml_escape(bool p_escape_quotes=false) const; String xml_escape(bool p_escape_quotes=false) const;
String xml_unescape() const; String xml_unescape() const;
String http_escape() const;
String http_unescape() const;
String c_escape() const; String c_escape() const;
String c_unescape() const; String c_unescape() const;
String world_wrap(int p_chars_per_line) const; String world_wrap(int p_chars_per_line) const;

View File

@ -12518,9 +12518,13 @@ This approximation makes straight segments between each point, then subdivides t
</argument> </argument>
<argument index="2" name="use_ssl" type="bool" default="false"> <argument index="2" name="use_ssl" type="bool" default="false">
</argument> </argument>
<argument index="3" name="arg3" type="bool" default="true"> <argument index="3" name="verify_host" type="bool" default="true">
</argument> </argument>
<description> <description>
Connect to a host. This needs to be done before any requests are sent.
The host should not have http:// prepended but will strip the protocol identifier if provided.
verify_host will check the SSL identity of the host if set to true.
</description> </description>
</method> </method>
<method name="set_connection"> <method name="set_connection">
@ -12541,6 +12545,20 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="3" name="body" type="String" default="&quot;&quot;"> <argument index="3" name="body" type="String" default="&quot;&quot;">
</argument> </argument>
<description> <description>
Sends a request to the connected host. The url is the what is normally behind the hostname,
i.e;
http://somehost.com/index.php
url would be &quot;index.php&quot;
Headers are HTTP request headers
To create a POST request with query strings to push to the server, do:
var fields = {"username" : "user",
"password" : "pass"}
var queryString = httpClient.query_string_from_dict(fields)
var headers = ["Content-Type: application/x-www-form-urlencoded",
"Content-Length: " + str(queryString.length())]
var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, queryString)
</description> </description>
</method> </method>
<method name="send_body_text"> <method name="send_body_text">
@ -12548,7 +12566,8 @@ This approximation makes straight segments between each point, then subdivides t
</return> </return>
<argument index="0" name="body" type="String"> <argument index="0" name="body" type="String">
</argument> </argument>
<description> <description>
Stub function
</description> </description>
</method> </method>
<method name="send_body_data"> <method name="send_body_data">
@ -12557,6 +12576,7 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="0" name="body" type="RawArray"> <argument index="0" name="body" type="RawArray">
</argument> </argument>
<description> <description>
Stub function
</description> </description>
</method> </method>
<method name="close"> <method name="close">
@ -12609,12 +12629,14 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="0" name="bytes" type="int"> <argument index="0" name="bytes" type="int">
</argument> </argument>
<description> <description>
Sets the size of the buffer used and maximum bytes to read per iteration
</description> </description>
</method> </method>
<method name="set_blocking_mode"> <method name="set_blocking_mode">
<argument index="0" name="enabled" type="bool"> <argument index="0" name="enabled" type="bool">
</argument> </argument>
<description> <description>
If set to true, execute will wait until all data is read from the response.
</description> </description>
</method> </method>
<method name="is_blocking_mode_enabled" qualifiers="const"> <method name="is_blocking_mode_enabled" qualifiers="const">
@ -12627,14 +12649,30 @@ This approximation makes straight segments between each point, then subdivides t
<return type="int"> <return type="int">
</return> </return>
<description> <description>
Returns a status string like STATUS_REQUESTING. Need to call [method poll] in order to get status updates.
</description> </description>
</method> </method>
<method name="poll"> <method name="poll">
<return type="Error"> <return type="Error">
</return> </return>
<description> <description>
This needs to be called in order to have any request processed. Check results with [method get_status]
</description> </description>
</method> </method>
<method name="query_string_from_dict">
<return type="String">
</return>
<argument index="0" name="fields" type="Dictionary">
</argument>
<description>
Generates a GET/POST application/x-www-form-urlencoded style query string from a provided dictionary.
var fields = {"username": "user", "password": "pass"}
String queryString = httpClient.query_string_from_dict(fields)
returns:= "username=user&amp;password=pass"
</description>
</method>
</methods> </methods>
<constants> <constants>
<constant name="METHOD_GET" value="0"> <constant name="METHOD_GET" value="0">

View File

@ -189,9 +189,11 @@ void DocData::generate(bool p_basic_types) {
arginfo=E->get().return_val; arginfo=E->get().return_val;
if (arginfo.type==Variant::NIL) if (arginfo.type==Variant::NIL)
continue; continue;
#ifdef DEBUG_METHODS_ENABLED
if (m && m->get_return_type()!=StringName()) if (m && m->get_return_type()!=StringName())
method.return_type=m->get_return_type(); method.return_type=m->get_return_type();
else else
#endif
method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type); method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type);
} else { } else {

View File

@ -1,5 +1,19 @@
import sys import sys
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from xml.sax.saxutils import escape, unescape
html_escape_table = {
'"': "&quot;",
"'": "&apos;"
}
html_unescape_table = {v:k for k, v in html_escape_table.items()}
def html_escape(text):
return escape(text, html_escape_table)
def html_unescape(text):
return unescape(text, html_unescape_table)
input_list = [] input_list = []
@ -96,7 +110,7 @@ def make_html_class_list(class_list,columns):
idx=0 idx=0
for n in class_list: for n in class_list:
col = idx/col_max col = int(idx/col_max)
if (col>=columns): if (col>=columns):
col=columns-1 col=columns-1
fit_columns[col]+=[n] fit_columns[col]+=[n]
@ -299,6 +313,7 @@ def make_type(p_type,p_parent):
def make_text_def(class_name,parent,text): def make_text_def(class_name,parent,text):
text = html_escape(text)
pos=0 pos=0
while(True): while(True):
pos = text.find("[",pos) pos = text.find("[",pos)
@ -598,7 +613,6 @@ def make_html_class(node):
descr=node.find("description") descr=node.find("description")
if (descr!=None and descr.text.strip()!=""): if (descr!=None and descr.text.strip()!=""):
h4=ET.SubElement(div,"h4") h4=ET.SubElement(div,"h4")
h4.text="Description:" h4.text="Description:"
@ -644,7 +658,6 @@ def make_html_class(node):
class_names=[] class_names=[]
classes={} classes={}
for file in input_list: for file in input_list:
tree = ET.parse(file) tree = ET.parse(file)
doc=tree.getroot() doc=tree.getroot()

View File

@ -1,5 +1,6 @@
Import('env') Import('env')
env.add_source_files(env.tool_sources,"*.cpp") env.add_source_files(env.tool_sources,"*.cpp")
env.Append(LIBS=["iconv"])
Export('env') Export('env')