#include "App.h" #include #include "Utilities.h" using namespace v8; struct HttpResponseWrapper { static Persistent resTemplate[2]; template static inline uWS::HttpResponse *getHttpResponse(const FunctionCallbackInfo &args) { return (uWS::HttpResponse *) args.Holder()->GetAlignedPointerFromInternalField(0); } // res.onData(JS function) // res.onAborted template static void res_onAborted(const FunctionCallbackInfo &args) { /* This thing perfectly fits in with unique_function, and will Reset on destructor */ UniquePersistent p(isolate, Local::Cast(args[0])); getHttpResponse(args)->onAborted([p = std::move(p)]() { HandleScope hs(isolate); Local argv[] = {}; Local::New(isolate, p)->Call(isolate->GetCurrentContext()->Global(), 0, argv); }); args.GetReturnValue().Set(args.Holder()); } /* Returns the current write offset */ template static void res_getWriteOffset(const FunctionCallbackInfo &args) { args.GetReturnValue().Set(Integer::New(isolate, getHttpResponse(args)->getWriteOffset())); } /* Takes function of bool(int), returns this */ template static void res_onWritable(const FunctionCallbackInfo &args) { /* This thing perfectly fits in with unique_function, and will Reset on destructor */ UniquePersistent p(isolate, Local::Cast(args[0])); getHttpResponse(args)->onWritable([p = std::move(p)](int offset) { HandleScope hs(isolate); Local argv[] = {Integer::NewFromUnsigned(isolate, offset)}; return Local::New(isolate, p)->Call(isolate->GetCurrentContext()->Global(), 1, argv)->BooleanValue(); }); args.GetReturnValue().Set(args.Holder()); } /* Takes string or arraybuffer, returns this */ template static void res_writeStatus(const FunctionCallbackInfo &args) { NativeString data(args.GetIsolate(), args[0]); getHttpResponse(args)->writeStatus(std::string_view(data.getData(), data.getLength())); args.GetReturnValue().Set(args.Holder()); } /* Takes string or arraybuffer, returns this */ template static void res_end(const FunctionCallbackInfo &args) { NativeString data(args.GetIsolate(), args[0]); getHttpResponse(args)->end(std::string_view(data.getData(), data.getLength())); args.GetReturnValue().Set(args.Holder()); } /* Takes data and optionally totalLength, returns true for success, false for backpressure */ template static void res_tryEnd(const FunctionCallbackInfo &args) { NativeString data(args.GetIsolate(), args[0]); int totalSize = 0; if (args.Length() > 1) { totalSize = args[1]->Uint32Value(); } bool ok = getHttpResponse(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 static void res_write(const FunctionCallbackInfo &args) { NativeString data(args.GetIsolate(), args[0]); bool ok = getHttpResponse(args)->write(std::string_view(data.getData(), data.getLength())); args.GetReturnValue().Set(Boolean::New(isolate, ok)); } /* Takes key, value. Returns this */ template static void res_writeHeader(const FunctionCallbackInfo &args) { NativeString header(args.GetIsolate(), args[0]); NativeString value(args.GetIsolate(), args[1]); getHttpResponse(args)->writeHeader(std::string_view(header.getData(), header.getLength()), std::string_view(value.getData(), value.getLength())); args.GetReturnValue().Set(args.Holder()); } template static void initResTemplate() { Local 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 */ resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "writeStatus"), FunctionTemplate::New(isolate, res_writeStatus)); resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "end"), FunctionTemplate::New(isolate, res_end)); resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "tryEnd"), FunctionTemplate::New(isolate, res_tryEnd)); resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "write"), FunctionTemplate::New(isolate, res_write)); resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "writeHeader"), FunctionTemplate::New(isolate, res_writeHeader)); resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "getWriteOffset"), FunctionTemplate::New(isolate, res_getWriteOffset)); resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "onWritable"), FunctionTemplate::New(isolate, res_onWritable)); resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "onAborted"), FunctionTemplate::New(isolate, res_onAborted)); /* Create our template */ Local resObjectLocal = resTemplateLocal->GetFunction()->NewInstance(isolate->GetCurrentContext()).ToLocalChecked(); resTemplate[SSL].Reset(isolate, resObjectLocal); } template static Local getResInstance() { return Local::New(isolate, resTemplate[std::is_same::value])->Clone(); } }; Persistent HttpResponseWrapper::resTemplate[2];