Register HttpRequest to script.

Register Deserializer::Read() & Serializer::Write() to script. They operate on Array<uint8>.
Trim HttpRequest headers and do not add empty headers.
This commit is contained in:
Lasse Öörni 2013-09-10 21:11:39 +00:00
parent 8992e0a881
commit 6350f246e6
8 changed files with 139 additions and 26 deletions

View File

@ -905,6 +905,7 @@ Properties:<br>
Serializer
Methods:<br>
- uint Write(uint8[]@)
- bool WriteInt(int)
- bool WriteShort(int16)
- bool WriteByte(int8)
@ -937,6 +938,7 @@ Methods:<br>
Deserializer
Methods:<br>
- uint8[]@ Read(uint)
- int ReadInt()
- int16 ReadShort()
- int8 ReadByte()
@ -980,6 +982,7 @@ Methods:<br>
- void SendEvent(const String&, VariantMap& arg1 = VariantMap ( ))
- bool Open(const String&, FileMode arg1 = FILE_READ)
- void Close()
- uint Write(uint8[]@)
- bool WriteInt(int)
- bool WriteShort(int16)
- bool WriteByte(int8)
@ -1007,6 +1010,7 @@ Methods:<br>
- bool WriteVLE(uint)
- bool WriteNetID(uint)
- bool WriteLine(const String&)
- uint8[]@ Read(uint)
- int ReadInt()
- int16 ReadShort()
- int8 ReadByte()
@ -1058,6 +1062,7 @@ Methods:<br>
- void SetData(Deserializer@, uint)
- void Clear()
- void Resize(uint)
- uint Write(uint8[]@)
- bool WriteInt(int)
- bool WriteShort(int16)
- bool WriteByte(int8)
@ -1085,6 +1090,7 @@ Methods:<br>
- bool WriteVLE(uint)
- bool WriteNetID(uint)
- bool WriteLine(const String&)
- uint8[]@ Read(uint)
- int ReadInt()
- int16 ReadShort()
- int8 ReadByte()
@ -5852,6 +5858,52 @@ Properties:<br>
- VariantMap identity
HttpRequest
Methods:<br>
- uint8[]@ Read(uint)
- int ReadInt()
- int16 ReadShort()
- int8 ReadByte()
- uint ReadUInt()
- uint16 ReadUShort()
- uint8 ReadUByte()
- bool ReadBool()
- float ReadFloat()
- IntRect ReadIntRect()
- IntVector2 ReadIntVector2()
- Vector2 ReadVector2()
- Vector3 ReadVector3()
- Vector3 ReadPackedVector3(float)
- Vector4 ReadVector4()
- Quaternion ReadQuaternion()
- Quaternion ReadPackedQuaternion()
- Color ReadColor()
- BoundingBox ReadBoundingBox()
- String ReadString()
- String ReadFileID()
- StringHash ReadStringHash()
- ShortStringHash ReadShortStringHash()
- Variant ReadVariant()
- VariantMap ReadVariantMap()
- uint ReadVLE()
- uint ReadNetID()
- String ReadLine()
- uint Seek(uint)
Properties:<br>
- int refs (readonly)
- int weakRefs (readonly)
- String name (readonly)
- uint checksum (readonly)
- uint position (readonly)
- uint size (readonly)
- bool eof (readonly)
- String url (readonly)
- String verb (readonly)
- bool open (readonly)
Network
Methods:<br>
@ -5868,6 +5920,7 @@ Methods:<br>
- void UnregisterRemoteEvent(const String&) const
- void UnregisterAllRemoteEvents()
- bool CheckRemoteEvent(const String&) const
- HttpRequest@ MakeHttpRequest(const String&, const String& arg1 = String ( ), String[]@ arg2 = null, const String& arg3 = String ( ))
Properties:<br>
- int refs (readonly)

View File

@ -23,6 +23,7 @@
#include "Precompiled.h"
#include "HttpRequest.h"
#include "Log.h"
#include "Profiler.h"
#include "StringUtils.h"
#include <civetweb.h>
@ -35,23 +36,27 @@ namespace Urho3D
static const unsigned ERROR_BUFFER_LEN = 256;
HttpRequest::HttpRequest(const String& url, const String& verb, const Vector<String>& headers, const String& postData) :
url_(url),
url_(url.Trimmed()),
verb_(!verb.Empty() ? verb : "GET"),
connection_(0)
{
// Size of response is unknown, so just set maximum value. The position will also be changed
// to maximum value once the request is done, signaling end for Deserializer::IsEof().
size_ = M_MAX_UNSIGNED;
String protocol = "http";
String host;
String path = "/";
int port = 80;
unsigned protocolEnd = url.Find("://");
unsigned protocolEnd = url_.Find("://");
if (protocolEnd != String::NPOS)
{
protocol = url.Substring(0, protocolEnd);
host = url.Substring(protocolEnd + 3);
protocol = url_.Substring(0, protocolEnd);
host = url_.Substring(protocolEnd + 3);
}
else
host = url;
host = url_;
unsigned pathStart = host.Find('/');
if (pathStart != String::NPOS)
@ -72,9 +77,14 @@ HttpRequest::HttpRequest(const String& url, const String& verb, const Vector<Str
char errorBuffer[ERROR_BUFFER_LEN];
memset(errorBuffer, 0, sizeof(errorBuffer));
String headerStr;
String headersStr;
for (unsigned i = 0; i < headers.Size(); ++i)
headerStr += headers[i] + "\r\n";
{
// Trim and only add non-empty header strings
String header = headers[i].Trimmed();
if (header.Length())
headersStr += header + "\r\n";
}
/// \todo SSL mode will not actually work unless Civetweb's SSL mode is initialized with an external SSL DLL
if (postData.Empty())
@ -83,7 +93,7 @@ HttpRequest::HttpRequest(const String& url, const String& verb, const Vector<Str
"%s %s HTTP/1.0\r\n"
"Host: %s\r\n"
"%s"
"\r\n", verb_.CString(), path.CString(), host.CString(), headerStr.CString());
"\r\n", verb_.CString(), path.CString(), host.CString(), headersStr.CString());
}
else
{
@ -93,7 +103,7 @@ HttpRequest::HttpRequest(const String& url, const String& verb, const Vector<Str
"%s"
"Content-Length: %d\r\n"
"\r\n"
"%s", verb_.CString(), path.CString(), host.CString(), headerStr.CString(), postData.Length(), postData.CString());
"%s", verb_.CString(), path.CString(), host.CString(), headersStr.CString(), postData.Length(), postData.CString());
}
if (!connection_)
@ -124,6 +134,7 @@ void HttpRequest::Release()
{
mg_close_connection((mg_connection*)connection_);
connection_ = 0;
position_ = M_MAX_UNSIGNED;
}
}

View File

@ -22,13 +22,14 @@
#pragma once
#include "Deserializer.h"
#include "RefCounted.h"
namespace Urho3D
{
/// HTTP request class.
class HttpRequest : public RefCounted
class HttpRequest : public RefCounted, public Deserializer
{
public:
/// Construct with parameters.
@ -37,7 +38,10 @@ public:
~HttpRequest();
/// Read response data from the HTTP connection. Return bytes actually read or 0 on error or end of data.
unsigned Read(void* dest, unsigned size);
virtual unsigned Read(void* dest, unsigned size);
/// Set position from the beginning of the stream. Not supported
virtual unsigned Seek(unsigned position) { return position_; }
/// Return whether connection is still open.
bool IsOpen() const { return connection_ != 0; }
/// Return URL used in the request.

View File

@ -312,6 +312,8 @@ void Network::SetPackageCacheDir(const String& path)
SharedPtr<HttpRequest> Network::MakeHttpRequest(const String& url, const String& verb, const Vector<String>& headers, const String& postData)
{
PROFILE(MakeHttpRequest);
SharedPtr<HttpRequest> request(new HttpRequest(url, verb, headers, postData));
const String& error = request->GetError();
if (!error.Empty())

View File

@ -91,10 +91,9 @@ template <class T> CScriptArray* VectorToArray(const PODVector<T>& vector, const
{
asIObjectType* type = GetScriptContext()->GetSubsystem<Script>()->GetObjectType(arrayName);
CScriptArray* arr = new CScriptArray(vector.Size(), type);
for (unsigned i = 0; i < arr->GetSize(); ++i)
*(static_cast<T*>(arr->At(i))) = vector[i];
if (vector.Size())
memcpy(arr->At(0), &vector[0], vector.Size() * sizeof(T));
return arr;
}
else
@ -191,6 +190,18 @@ template <class T> CScriptArray* VectorToHandleArray(const Vector<SharedPtr<T> >
return 0;
}
/// Template function for array to Vector conversion.
template <class T> Vector<T> ArrayToVector(CScriptArray* arr)
{
Vector<T> dest(arr ? arr->GetSize() : 0);
if (arr)
{
for (unsigned i = 0; i < arr->GetSize(); ++i)
dest[i] = *static_cast<T*>(arr->At(i));
}
return dest;
}
/// Template function for registering implicit casts between base and subclass.
template <class T, class U> void RegisterSubclass(asIScriptEngine* engine, const char* classNameT, const char* classNameU)
{
@ -204,9 +215,17 @@ template <class T, class U> void RegisterSubclass(asIScriptEngine* engine, const
engine->RegisterObjectBehaviour(classNameU, asBEHAVE_IMPLICIT_REF_CAST, declReturnT.CString(), asFUNCTION((RefCast<U, T>)), asCALL_CDECL_OBJLAST);
}
/// Template function for writing to a serializer from an array.
template <class T> unsigned SerializerWrite(CScriptArray* arr, T* ptr)
{
unsigned bytesToWrite = arr->GetSize();
return bytesToWrite ? ptr->Write(arr->At(0), bytesToWrite) : 0;
}
/// Template function for registering a class derived from Serializer.
template <class T> void RegisterSerializer(asIScriptEngine* engine, const char* className)
{
engine->RegisterObjectMethod(className, "uint Write(Array<uint8>@+)", asFUNCTION(SerializerWrite<T>), asCALL_CDECL_OBJLAST);
engine->RegisterObjectMethod(className, "bool WriteInt(int)", asMETHODPR(T, WriteInt, (int), bool), asCALL_THISCALL);
engine->RegisterObjectMethod(className, "bool WriteShort(int16)", asMETHODPR(T, WriteShort, (short), bool), asCALL_THISCALL);
engine->RegisterObjectMethod(className, "bool WriteByte(int8)", asMETHODPR(T, WriteByte, (signed char), bool), asCALL_THISCALL);
@ -236,9 +255,19 @@ template <class T> void RegisterSerializer(asIScriptEngine* engine, const char*
engine->RegisterObjectMethod(className, "bool WriteLine(const String&in)", asMETHODPR(T, WriteLine, (const String&), bool), asCALL_THISCALL);
}
/// Template function for reading from a serializer into an array.
template <class T> CScriptArray* DeserializerRead(unsigned size, T* ptr)
{
PODVector<unsigned char> vector(size);
unsigned bytesRead = size ? ptr->Read(&vector[0], size) : 0;
vector.Resize(bytesRead);
return VectorToArray(vector, "Array<uint8>");
}
/// Template function for registering a class derived from Deserializer.
template <class T> void RegisterDeserializer(asIScriptEngine* engine, const char* className)
{
engine->RegisterObjectMethod(className, "Array<uint8>@ Read(uint)", asFUNCTION(DeserializerRead<T>), asCALL_CDECL_OBJLAST);
engine->RegisterObjectMethod(className, "int ReadInt()", asMETHODPR(T, ReadInt, (), int), asCALL_THISCALL);
engine->RegisterObjectMethod(className, "int16 ReadShort()", asMETHODPR(T, ReadShort, (), short), asCALL_THISCALL);
engine->RegisterObjectMethod(className, "int8 ReadByte()", asMETHODPR(T, ReadByte, (), signed char), asCALL_THISCALL);
@ -285,7 +314,7 @@ template <class T> void RegisterRefCounted(asIScriptEngine* engine, const char*
RegisterSubclass<RefCounted, T>(engine, "RefCounted", className);
}
template <class T> void ObjectSendEvent(const String& eventType, VariantMap& eventData, T* ptr)
template <class T> void ObjectSendEvent(const String& eventType, VariantMap& eventData, T* ptr)
{
if (ptr)
ptr->SendEvent(StringHash(eventType), eventData);
@ -461,7 +490,7 @@ static CScriptArray* NodeGetChildren(bool recursive, Node* ptr)
return VectorToHandleArray<Node>(nodes, "Array<Node@>");
}
static CScriptArray* NodeGetChildrenWithComponent(String& typeName, bool recursive, Node* ptr)
static CScriptArray* NodeGetChildrenWithComponent(const String& typeName, bool recursive, Node* ptr)
{
PODVector<Node*> nodes;
ptr->GetChildrenWithComponent(nodes, typeName, recursive);

View File

@ -91,7 +91,7 @@ static CScriptArray* ScriptArrayFactoryDefVal(asIObjectType *ot, asUINT length,
return 0;
}
return a;
return a;
}
static CScriptArray* ScriptArrayFactory(asIObjectType *ot)

View File

@ -541,14 +541,6 @@ static CScriptArray* StringSplit(char separator, const String* str)
return VectorToArray<String>(result, "Array<String>");
}
template <class T> Vector<T> ArrayToVector(CScriptArray* arr)
{
Vector<T> dest(arr->GetSize());
for (unsigned i = 0; i < arr->GetSize(); ++i)
dest[i] = *static_cast<T*>(arr->At(i));
return dest;
}
static void StringJoin(CScriptArray* arr, const String& glue, String* str)
{
Vector<String> subStrings = ArrayToVector<String>(arr);

View File

@ -23,6 +23,7 @@
#include "Precompiled.h"
#include "APITemplates.h"
#include "Controls.h"
#include "HttpRequest.h"
#include "Network.h"
#include "NetworkPriority.h"
#include "Protocol.h"
@ -118,6 +119,15 @@ static void RegisterConnection(asIScriptEngine* engine)
engine->RegisterObjectMethod("Node", "Connection@+ get_owner() const", asMETHOD(Node, GetOwner), asCALL_THISCALL);
}
static void RegisterHttpRequest(asIScriptEngine* engine)
{
RegisterRefCounted<HttpRequest>(engine, "HttpRequest");
RegisterDeserializer<HttpRequest>(engine, "HttpRequest");
engine->RegisterObjectMethod("HttpRequest", "const String& get_url() const", asMETHOD(HttpRequest, GetURL), asCALL_THISCALL);
engine->RegisterObjectMethod("HttpRequest", "const String& get_verb() const", asMETHOD(HttpRequest, GetVerb), asCALL_THISCALL);
engine->RegisterObjectMethod("HttpRequest", "bool get_open() const", asMETHOD(HttpRequest, IsOpen), asCALL_THISCALL);
}
static Network* GetNetwork()
{
return GetScriptContext()->GetSubsystem<Network>();
@ -159,6 +169,16 @@ static bool NetworkCheckRemoteEvent(const String& eventType, Network* ptr)
return ptr->CheckRemoteEvent(eventType);
}
static HttpRequest* NetworkMakeHttpRequest(const String& url, const String& verb, CScriptArray* headers, const String& postData, Network* ptr)
{
SharedPtr<HttpRequest> request = ptr->MakeHttpRequest(url, verb, ArrayToVector<String>(headers), postData);
// The shared pointer will go out of scope, so have to increment the reference count
// (here an auto handle can not be used)
if (request)
request->AddRef();
return request.Get();
}
void RegisterNetwork(asIScriptEngine* engine)
{
RegisterObject<Network>(engine, "Network");
@ -174,6 +194,7 @@ void RegisterNetwork(asIScriptEngine* engine)
engine->RegisterObjectMethod("Network", "void UnregisterRemoteEvent(const String&in) const", asFUNCTION(NetworkUnregisterRemoteEvent), asCALL_CDECL_OBJLAST);
engine->RegisterObjectMethod("Network", "void UnregisterAllRemoteEvents()", asMETHOD(Network, UnregisterAllRemoteEvents), asCALL_THISCALL);
engine->RegisterObjectMethod("Network", "bool CheckRemoteEvent(const String&in) const", asFUNCTION(NetworkCheckRemoteEvent), asCALL_CDECL_OBJLAST);
engine->RegisterObjectMethod("Network", "HttpRequest@ MakeHttpRequest(const String&in, const String&in verb = String(), Array<String>@+ headers = null, const String&in postData = String())", asFUNCTION(NetworkMakeHttpRequest), asCALL_CDECL_OBJLAST);
engine->RegisterObjectMethod("Network", "void set_updateFps(int)", asMETHOD(Network, SetUpdateFps), asCALL_THISCALL);
engine->RegisterObjectMethod("Network", "int get_updateFps() const", asMETHOD(Network, GetUpdateFps), asCALL_THISCALL);
engine->RegisterObjectMethod("Network", "void set_packageCacheDir(const String&in)", asMETHOD(Network, SetPackageCacheDir), asCALL_THISCALL);
@ -189,6 +210,7 @@ void RegisterNetworkAPI(asIScriptEngine* engine)
RegisterControls(engine);
RegisterNetworkPriority(engine);
RegisterConnection(engine);
RegisterHttpRequest(engine);
RegisterNetwork(engine);
}