2019-01-14 12:17:08 +00:00
|
|
|
#include "App.h"
|
2019-01-14 10:45:25 +00:00
|
|
|
#include <v8.h>
|
|
|
|
#include "Utilities.h"
|
|
|
|
using namespace v8;
|
|
|
|
|
2019-01-14 12:17:08 +00:00
|
|
|
struct HttpResponseWrapper {
|
|
|
|
static Persistent<Object> resTemplate[2];
|
|
|
|
|
|
|
|
template <bool SSL>
|
|
|
|
static inline uWS::HttpResponse<SSL> *getHttpResponse(const FunctionCallbackInfo<Value> &args) {
|
|
|
|
return (uWS::HttpResponse<SSL> *) args.Holder()->GetAlignedPointerFromInternalField(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// res.onData(JS function)
|
2019-01-14 12:39:43 +00:00
|
|
|
// res.onAborted
|
2019-01-15 07:10:57 +00:00
|
|
|
|
2019-01-17 05:31:55 +00:00
|
|
|
template <bool SSL>
|
|
|
|
static void res_onAborted(const FunctionCallbackInfo<Value> &args) {
|
|
|
|
/* This thing perfectly fits in with unique_function, and will Reset on destructor */
|
|
|
|
UniquePersistent<Function> p(isolate, Local<Function>::Cast(args[0]));
|
|
|
|
|
|
|
|
getHttpResponse<SSL>(args)->onAborted([p = std::move(p)]() {
|
|
|
|
HandleScope hs(isolate);
|
|
|
|
|
|
|
|
Local<Value> argv[] = {};
|
|
|
|
Local<Function>::New(isolate, p)->Call(isolate->GetCurrentContext()->Global(), 0, argv);
|
|
|
|
});
|
|
|
|
|
|
|
|
args.GetReturnValue().Set(args.Holder());
|
|
|
|
}
|
|
|
|
|
2019-01-15 10:52:55 +00:00
|
|
|
/* Returns the current write offset */
|
|
|
|
template <bool SSL>
|
|
|
|
static void res_getWriteOffset(const FunctionCallbackInfo<Value> &args) {
|
|
|
|
args.GetReturnValue().Set(Integer::New(isolate, getHttpResponse<SSL>(args)->getWriteOffset()));
|
|
|
|
}
|
|
|
|
|
2019-01-15 07:10:57 +00:00
|
|
|
/* Takes function of bool(int), returns this */
|
|
|
|
template <bool SSL>
|
|
|
|
static void res_onWritable(const FunctionCallbackInfo<Value> &args) {
|
|
|
|
/* This thing perfectly fits in with unique_function, and will Reset on destructor */
|
|
|
|
UniquePersistent<Function> p(isolate, Local<Function>::Cast(args[0]));
|
|
|
|
|
|
|
|
getHttpResponse<SSL>(args)->onWritable([p = std::move(p)](int offset) {
|
|
|
|
HandleScope hs(isolate);
|
|
|
|
|
|
|
|
Local<Value> argv[] = {Integer::NewFromUnsigned(isolate, offset)};
|
|
|
|
return Local<Function>::New(isolate, p)->Call(isolate->GetCurrentContext()->Global(), 1, argv)->BooleanValue();
|
|
|
|
});
|
|
|
|
|
|
|
|
args.GetReturnValue().Set(args.Holder());
|
|
|
|
}
|
2019-01-14 12:39:43 +00:00
|
|
|
|
|
|
|
/* Takes string or arraybuffer, returns this */
|
|
|
|
template <bool SSL>
|
|
|
|
static void res_writeStatus(const FunctionCallbackInfo<Value> &args) {
|
|
|
|
NativeString data(args.GetIsolate(), args[0]);
|
|
|
|
getHttpResponse<SSL>(args)->writeStatus(std::string_view(data.getData(), data.getLength()));
|
|
|
|
|
|
|
|
args.GetReturnValue().Set(args.Holder());
|
|
|
|
}
|
2019-01-14 12:17:08 +00:00
|
|
|
|
|
|
|
/* Takes string or arraybuffer, returns this */
|
|
|
|
template <bool SSL>
|
|
|
|
static void res_end(const FunctionCallbackInfo<Value> &args) {
|
|
|
|
NativeString data(args.GetIsolate(), args[0]);
|
|
|
|
getHttpResponse<SSL>(args)->end(std::string_view(data.getData(), data.getLength()));
|
|
|
|
|
|
|
|
args.GetReturnValue().Set(args.Holder());
|
|
|
|
}
|
|
|
|
|
2019-01-14 12:39:43 +00:00
|
|
|
/* Takes data and optionally totalLength, returns true for success, false for backpressure */
|
|
|
|
template <bool SSL>
|
|
|
|
static void res_tryEnd(const FunctionCallbackInfo<Value> &args) {
|
|
|
|
NativeString data(args.GetIsolate(), args[0]);
|
|
|
|
|
|
|
|
int totalSize = 0;
|
|
|
|
if (args.Length() > 1) {
|
|
|
|
totalSize = args[1]->Uint32Value();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ok = getHttpResponse<SSL>(args)->tryEnd(std::string_view(data.getData(), data.getLength()), totalSize);
|
|
|
|
|
|
|
|
args.GetReturnValue().Set(Boolean::New(isolate, ok));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Takes data, returns true for success, false for backpressure */
|
|
|
|
template <bool SSL>
|
|
|
|
static void res_write(const FunctionCallbackInfo<Value> &args) {
|
|
|
|
NativeString data(args.GetIsolate(), args[0]);
|
|
|
|
bool ok = getHttpResponse<SSL>(args)->write(std::string_view(data.getData(), data.getLength()));
|
|
|
|
|
|
|
|
args.GetReturnValue().Set(Boolean::New(isolate, ok));
|
|
|
|
}
|
|
|
|
|
2019-01-14 12:17:08 +00:00
|
|
|
/* Takes key, value. Returns this */
|
|
|
|
template <bool SSL>
|
|
|
|
static void res_writeHeader(const FunctionCallbackInfo<Value> &args) {
|
|
|
|
NativeString header(args.GetIsolate(), args[0]);
|
|
|
|
NativeString value(args.GetIsolate(), args[1]);
|
|
|
|
getHttpResponse<SSL>(args)->writeHeader(std::string_view(header.getData(), header.getLength()),
|
|
|
|
std::string_view(value.getData(), value.getLength()));
|
|
|
|
|
|
|
|
args.GetReturnValue().Set(args.Holder());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <bool SSL>
|
|
|
|
static void initResTemplate() {
|
|
|
|
Local<FunctionTemplate> resTemplateLocal = FunctionTemplate::New(isolate);
|
|
|
|
if (SSL) {
|
|
|
|
resTemplateLocal->SetClassName(String::NewFromUtf8(isolate, "uWS.SSLHttpResponse"));
|
|
|
|
} else {
|
|
|
|
resTemplateLocal->SetClassName(String::NewFromUtf8(isolate, "uWS.HttpResponse"));
|
|
|
|
}
|
|
|
|
resTemplateLocal->InstanceTemplate()->SetInternalFieldCount(1);
|
|
|
|
|
|
|
|
/* Register our functions */
|
2019-01-14 12:39:43 +00:00
|
|
|
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "writeStatus"), FunctionTemplate::New(isolate, res_writeStatus<SSL>));
|
2019-01-14 12:17:08 +00:00
|
|
|
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "end"), FunctionTemplate::New(isolate, res_end<SSL>));
|
2019-01-14 12:39:43 +00:00
|
|
|
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "tryEnd"), FunctionTemplate::New(isolate, res_tryEnd<SSL>));
|
|
|
|
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "write"), FunctionTemplate::New(isolate, res_write<SSL>));
|
2019-01-14 12:17:08 +00:00
|
|
|
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "writeHeader"), FunctionTemplate::New(isolate, res_writeHeader<SSL>));
|
|
|
|
|
2019-01-15 10:52:55 +00:00
|
|
|
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "getWriteOffset"), FunctionTemplate::New(isolate, res_getWriteOffset<SSL>));
|
2019-01-15 07:10:57 +00:00
|
|
|
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "onWritable"), FunctionTemplate::New(isolate, res_onWritable<SSL>));
|
2019-01-17 05:31:55 +00:00
|
|
|
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "onAborted"), FunctionTemplate::New(isolate, res_onAborted<SSL>));
|
2019-01-15 07:10:57 +00:00
|
|
|
|
2019-01-14 12:17:08 +00:00
|
|
|
/* Create our template */
|
|
|
|
Local<Object> resObjectLocal = resTemplateLocal->GetFunction()->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
|
|
resTemplate[SSL].Reset(isolate, resObjectLocal);
|
2019-01-14 10:34:20 +00:00
|
|
|
}
|
2019-01-14 12:17:08 +00:00
|
|
|
|
|
|
|
template <class APP>
|
|
|
|
static Local<Object> getResInstance() {
|
|
|
|
return Local<Object>::New(isolate, resTemplate[std::is_same<APP, uWS::SSLApp>::value])->Clone();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Persistent<Object> HttpResponseWrapper::resTemplate[2];
|