Skip to content

Commit 48afe0d

Browse files
committed
- rebase
1 parent 321b71c commit 48afe0d

File tree

1 file changed

+349
-0
lines changed

1 file changed

+349
-0
lines changed
Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
2+
#include "UEPyIHttpRequest.h"
3+
4+
#include "UEPyIHttpResponse.h"
5+
6+
#include "Runtime/Online/HTTP/Public/HttpManager.h"
7+
8+
static PyObject *py_ue_ihttp_request_set_verb(ue_PyIHttpRequest *self, PyObject * args)
9+
{
10+
11+
char *verb;
12+
if (!PyArg_ParseTuple(args, "s:set_verb", &verb))
13+
{
14+
return NULL;
15+
}
16+
17+
self->http_request->SetVerb(UTF8_TO_TCHAR(verb));
18+
19+
Py_RETURN_NONE;
20+
}
21+
22+
static PyObject *py_ue_ihttp_request_set_url(ue_PyIHttpRequest *self, PyObject * args)
23+
{
24+
25+
char *url;
26+
if (!PyArg_ParseTuple(args, "s:set_url", &url))
27+
{
28+
return NULL;
29+
}
30+
31+
self->http_request->SetURL(UTF8_TO_TCHAR(url));
32+
33+
Py_RETURN_NONE;
34+
}
35+
36+
static PyObject *py_ue_ihttp_request_set_header(ue_PyIHttpRequest *self, PyObject * args)
37+
{
38+
39+
char *key;
40+
char *value;
41+
if (!PyArg_ParseTuple(args, "ss:set_header", &key, &value))
42+
{
43+
return NULL;
44+
}
45+
46+
self->http_request->SetHeader(UTF8_TO_TCHAR(key), UTF8_TO_TCHAR(value));
47+
48+
Py_RETURN_NONE;
49+
}
50+
51+
static PyObject *py_ue_ihttp_request_append_to_header(ue_PyIHttpRequest *self, PyObject * args)
52+
{
53+
54+
char *key;
55+
char *value;
56+
if (!PyArg_ParseTuple(args, "ss:append_to_header", &key, &value))
57+
{
58+
return NULL;
59+
}
60+
61+
self->http_request->AppendToHeader(UTF8_TO_TCHAR(key), UTF8_TO_TCHAR(value));
62+
63+
Py_RETURN_NONE;
64+
}
65+
66+
static PyObject *py_ue_ihttp_request_set_content(ue_PyIHttpRequest *self, PyObject * args)
67+
{
68+
69+
PyObject *py_obj;
70+
if (!PyArg_ParseTuple(args, "O:set_content", &py_obj))
71+
{
72+
return NULL;
73+
}
74+
75+
if (PyUnicodeOrString_Check(py_obj))
76+
{
77+
self->http_request->SetContentAsString(UTF8_TO_TCHAR(UEPyUnicode_AsUTF8(py_obj)));
78+
}
79+
else if (PyBytes_Check(py_obj))
80+
{
81+
char *buf = nullptr;
82+
Py_ssize_t len = 0;
83+
PyBytes_AsStringAndSize(py_obj, &buf, &len);
84+
TArray<uint8> data;
85+
data.Append((uint8 *)buf, len);
86+
self->http_request->SetContent(data);
87+
}
88+
89+
Py_RETURN_NONE;
90+
}
91+
92+
static PyObject *py_ue_ihttp_request_tick(ue_PyIHttpRequest *self, PyObject * args)
93+
{
94+
95+
float delta_seconds;
96+
if (!PyArg_ParseTuple(args, "f:tick", &delta_seconds))
97+
{
98+
return NULL;
99+
}
100+
101+
FHttpModule::Get().GetHttpManager().Tick(delta_seconds);
102+
103+
self->http_request->Tick(delta_seconds);
104+
105+
Py_RETURN_NONE;
106+
}
107+
108+
static PyObject *py_ue_ihttp_request_process_request(ue_PyIHttpRequest *self, PyObject * args)
109+
{
110+
self->http_request->ProcessRequest();
111+
112+
Py_RETURN_NONE;
113+
}
114+
115+
static PyObject *py_ue_ihttp_request_cancel_request(ue_PyIHttpRequest *self, PyObject * args)
116+
{
117+
self->http_request->CancelRequest();
118+
119+
Py_RETURN_NONE;
120+
}
121+
122+
static PyObject *py_ue_ihttp_request_get_status(ue_PyIHttpRequest *self, PyObject * args)
123+
{
124+
return PyLong_FromLong((int)self->http_request->GetStatus());
125+
}
126+
127+
static PyObject *py_ue_ihttp_request_get_verb(ue_PyIHttpRequest *self, PyObject * args)
128+
{
129+
return PyUnicode_FromString(TCHAR_TO_UTF8(*self->http_request->GetVerb()));
130+
}
131+
132+
static PyObject *py_ue_ihttp_request_get_elapsed_time(ue_PyIHttpRequest *self, PyObject * args)
133+
{
134+
return PyFloat_FromDouble(self->http_request->GetElapsedTime());
135+
}
136+
137+
static PyObject *py_ue_ihttp_request_get_response(ue_PyIHttpRequest *self, PyObject * args)
138+
{
139+
FHttpResponsePtr response = self->http_request->GetResponse();
140+
if (!response.IsValid())
141+
{
142+
return PyErr_Format(PyExc_Exception, "unable to retrieve IHttpResponse");
143+
}
144+
return py_ue_new_ihttp_response(response.Get());
145+
}
146+
147+
void FPythonSmartHttpDelegate::OnRequestComplete(FHttpRequestPtr request, FHttpResponsePtr response, bool successful)
148+
{
149+
FScopePythonGIL gil;
150+
151+
if (!request.IsValid() || !response.IsValid())
152+
{
153+
UE_LOG(LogPython, Error, TEXT("Unable to retrieve HTTP infos"));
154+
return;
155+
}
156+
157+
PyObject *ret = PyObject_CallFunction(py_callable, (char *)"ONO", py_http_request, py_ue_new_ihttp_response(response.Get()), successful ? Py_True : Py_False);
158+
if (!ret)
159+
{
160+
unreal_engine_py_log_error();
161+
return;
162+
}
163+
Py_DECREF(ret);
164+
}
165+
166+
void FPythonSmartHttpDelegate::OnRequestProgress(FHttpRequestPtr request, int32 sent, int32 received)
167+
{
168+
FScopePythonGIL gil;
169+
170+
if (!request.IsValid())
171+
{
172+
UE_LOG(LogPython, Error, TEXT("Unable to retrieve HTTP infos"));
173+
return;
174+
}
175+
176+
PyObject *ret = PyObject_CallFunction(py_callable, (char *)"Oii", py_http_request, sent, received);
177+
if (!ret)
178+
{
179+
unreal_engine_py_log_error();
180+
return;
181+
}
182+
Py_DECREF(ret);
183+
}
184+
185+
static PyObject *py_ue_ihttp_request_bind_on_process_request_complete(ue_PyIHttpRequest *self, PyObject * args)
186+
{
187+
188+
PyObject *py_callable;
189+
if (!PyArg_ParseTuple(args, "O:bind_on_process_request_complete", &py_callable))
190+
{
191+
return nullptr;
192+
}
193+
194+
if (!PyCallable_Check(py_callable))
195+
{
196+
return PyErr_Format(PyExc_Exception, "argument is not a callable");
197+
}
198+
199+
TSharedRef<FPythonSmartHttpDelegate> py_delegate = MakeShareable(new FPythonSmartHttpDelegate);
200+
py_delegate->SetPyCallable(py_callable);
201+
// this trick avoids generating a new python object
202+
py_delegate->SetPyHttpRequest(self);
203+
self->http_request->OnProcessRequestComplete().BindSP(py_delegate, &FPythonSmartHttpDelegate::OnRequestComplete);
204+
205+
self->on_process_request_complete = py_delegate;
206+
207+
Py_RETURN_NONE;
208+
}
209+
210+
static PyObject *py_ue_ihttp_request_bind_on_request_progress(ue_PyIHttpRequest *self, PyObject * args)
211+
{
212+
213+
PyObject *py_callable;
214+
if (!PyArg_ParseTuple(args, "O:bind_on_request_progress", &py_callable))
215+
{
216+
return nullptr;
217+
}
218+
219+
if (!PyCallable_Check(py_callable))
220+
{
221+
return PyErr_Format(PyExc_Exception, "argument is not a callable");
222+
}
223+
224+
TSharedRef<FPythonSmartHttpDelegate> py_delegate = MakeShareable(new FPythonSmartHttpDelegate);
225+
py_delegate->SetPyCallable(py_callable);
226+
// this trick avoids generating a new python object
227+
py_delegate->SetPyHttpRequest(self);
228+
self->http_request->OnRequestProgress().BindSP(py_delegate, &FPythonSmartHttpDelegate::OnRequestProgress);
229+
230+
Py_RETURN_NONE;
231+
}
232+
233+
static PyMethodDef ue_PyIHttpRequest_methods[] = {
234+
{ "bind_on_process_request_complete", (PyCFunction)py_ue_ihttp_request_bind_on_process_request_complete, METH_VARARGS, "" },
235+
{ "bind_on_request_progress", (PyCFunction)py_ue_ihttp_request_bind_on_request_progress, METH_VARARGS, "" },
236+
{ "append_to_header", (PyCFunction)py_ue_ihttp_request_append_to_header, METH_VARARGS, "" },
237+
{ "cancel_request", (PyCFunction)py_ue_ihttp_request_cancel_request, METH_VARARGS, "" },
238+
{ "get_elapsed_time", (PyCFunction)py_ue_ihttp_request_get_elapsed_time, METH_VARARGS, "" },
239+
{ "get_response", (PyCFunction)py_ue_ihttp_request_get_response, METH_VARARGS, "" },
240+
{ "get_status", (PyCFunction)py_ue_ihttp_request_get_status, METH_VARARGS, "" },
241+
{ "get_verb", (PyCFunction)py_ue_ihttp_request_get_verb, METH_VARARGS, "" },
242+
{ "process_request", (PyCFunction)py_ue_ihttp_request_process_request, METH_VARARGS, "" },
243+
{ "set_content", (PyCFunction)py_ue_ihttp_request_set_content, METH_VARARGS, "" },
244+
{ "set_header", (PyCFunction)py_ue_ihttp_request_set_header, METH_VARARGS, "" },
245+
{ "set_url", (PyCFunction)py_ue_ihttp_request_set_url, METH_VARARGS, "" },
246+
{ "set_verb", (PyCFunction)py_ue_ihttp_request_set_verb, METH_VARARGS, "" },
247+
{ "tick", (PyCFunction)py_ue_ihttp_request_tick, METH_VARARGS, "" },
248+
{ NULL } /* Sentinel */
249+
};
250+
251+
252+
static PyObject *ue_PyIHttpRequest_str(ue_PyIHttpRequest *self)
253+
{
254+
return PyUnicode_FromFormat("<unreal_engine.IHttpRequest '%p'>",
255+
&self->http_request.Get());
256+
}
257+
258+
static void ue_PyIHttpRequest_dealloc(ue_PyIHttpRequest *self)
259+
{
260+
#if defined(UEPY_MEMORY_DEBUG)
261+
UE_LOG(LogPython, Warning, TEXT("Destroying ue_PyIHttpRequest %p mapped to IHttpRequest %p"), self, &self->http_request.Get());
262+
#endif
263+
self->on_process_request_complete = nullptr;
264+
self->on_request_progress = nullptr;
265+
Py_DECREF(self->py_dict);
266+
Py_TYPE(self)->tp_free((PyObject *)self);
267+
}
268+
269+
static PyTypeObject ue_PyIHttpRequestType = {
270+
PyVarObject_HEAD_INIT(NULL, 0)
271+
"unreal_engine.IHttpRequest", /* tp_name */
272+
sizeof(ue_PyIHttpRequest), /* tp_basicsize */
273+
0, /* tp_itemsize */
274+
(destructor)ue_PyIHttpRequest_dealloc, /* tp_dealloc */
275+
0, /* tp_print */
276+
0, /* tp_getattr */
277+
0, /* tp_setattr */
278+
0, /* tp_reserved */
279+
0, /* tp_repr */
280+
0, /* tp_as_number */
281+
0, /* tp_as_sequence */
282+
0, /* tp_as_mapping */
283+
0, /* tp_hash */
284+
0, /* tp_call */
285+
(reprfunc)ue_PyIHttpRequest_str, /* tp_str */
286+
0, /* tp_getattro */
287+
0, /* tp_setattro */
288+
0, /* tp_as_buffer */
289+
Py_TPFLAGS_DEFAULT, /* tp_flags */
290+
"Unreal Engine HttpRequest Interface", /* tp_doc */
291+
0, /* tp_traverse */
292+
0, /* tp_clear */
293+
0, /* tp_richcompare */
294+
0, /* tp_weaklistoffset */
295+
0, /* tp_iter */
296+
0, /* tp_iternext */
297+
ue_PyIHttpRequest_methods, /* tp_methods */
298+
0,
299+
0,
300+
};
301+
302+
static int ue_py_ihttp_request_init(ue_PyIHttpRequest *self, PyObject *args, PyObject *kwargs)
303+
{
304+
char *verb = nullptr;
305+
char* url = nullptr;
306+
if (!PyArg_ParseTuple(args, "|ss:__init__", &verb, &url))
307+
{
308+
return -1;
309+
}
310+
#if ENGINE_MINOR_VERSION == 27
311+
new(&self->http_request) TSharedRef<IHttpRequest, ESPMode::ThreadSafe>(FHttpModule::Get().CreateRequest());
312+
#else
313+
new(&self->http_request) TSharedRef<IHttpRequest>(FHttpModule::Get().CreateRequest());
314+
#endif
315+
new(&self->on_process_request_complete) TSharedPtr<FPythonSmartHttpDelegate>(nullptr);
316+
new(&self->on_request_progress) TSharedPtr<FPythonSmartHttpDelegate>(nullptr);
317+
self->py_dict = PyDict_New();
318+
if (verb)
319+
{
320+
self->http_request->SetVerb(UTF8_TO_TCHAR(verb));
321+
}
322+
323+
if (url)
324+
{
325+
self->http_request->SetURL(UTF8_TO_TCHAR(url));
326+
}
327+
328+
self->base.http_base = &self->http_request.Get();
329+
return 0;
330+
}
331+
332+
void ue_python_init_ihttp_request(PyObject *ue_module)
333+
{
334+
ue_PyIHttpRequestType.tp_new = PyType_GenericNew;
335+
336+
ue_PyIHttpRequestType.tp_init = (initproc)ue_py_ihttp_request_init;
337+
338+
ue_PyIHttpRequestType.tp_base = &ue_PyIHttpBaseType;
339+
340+
ue_PyIHttpRequestType.tp_getattro = PyObject_GenericGetAttr;
341+
ue_PyIHttpRequestType.tp_setattro = PyObject_GenericSetAttr;
342+
ue_PyIHttpRequestType.tp_dictoffset = offsetof(ue_PyIHttpRequest, py_dict);
343+
344+
if (PyType_Ready(&ue_PyIHttpRequestType) < 0)
345+
return;
346+
347+
Py_INCREF(&ue_PyIHttpRequestType);
348+
PyModule_AddObject(ue_module, "IHttpRequest", (PyObject *)&ue_PyIHttpRequestType);
349+
}

0 commit comments

Comments
 (0)