From 67fdec20726e48ba3a934cb25bb30d47ec4a4f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaroslav=20De=20La=20Pe=C3=B1a=20Smirnov?= Date: Wed, 29 Nov 2017 11:44:34 +0300 Subject: Initial commit, version 0.5.3 --- node_modules/uws/src/http.h | 357 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 node_modules/uws/src/http.h (limited to 'node_modules/uws/src/http.h') diff --git a/node_modules/uws/src/http.h b/node_modules/uws/src/http.h new file mode 100644 index 0000000..61c9d2e --- /dev/null +++ b/node_modules/uws/src/http.h @@ -0,0 +1,357 @@ +#include + +Persistent reqTemplate, resTemplate; +Persistent httpPersistent; + +uWS::HttpRequest *currentReq = nullptr; + +struct HttpServer { + + struct Request { + static void on(const FunctionCallbackInfo &args) { + NativeString eventName(args[0]); + if (std::string(eventName.getData(), eventName.getLength()) == "data") { + args.Holder()->SetInternalField(1, args[1]); + } else if (std::string(eventName.getData(), eventName.getLength()) == "end") { + args.Holder()->SetInternalField(2, args[1]); + } else { + std::cout << "Warning: req.on(" << std::string(eventName.getData(), eventName.getLength()) << ") is not implemented!" << std::endl; + } + args.GetReturnValue().Set(args.Holder()); + } + + static void headers(Local property, const PropertyCallbackInfo &args) { + uWS::HttpRequest *req = currentReq; + if (!req) { + std::cerr << "Warning: req.headers usage past request handler is not supported!" << std::endl; + } else { + NativeString nativeString(property); + uWS::Header header = req->getHeader(nativeString.getData(), nativeString.getLength()); + if (header) { + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) header.value, String::kNormalString, header.valueLength)); + } + } + } + + static void url(Local property, const PropertyCallbackInfo &args) { + args.GetReturnValue().Set(args.This()->GetInternalField(4)); + } + + static void method(Local property, const PropertyCallbackInfo &args) { + //std::cout << "method" << std::endl; + long methodId = ((long) args.This()->GetAlignedPointerFromInternalField(3)) >> 1; + switch (methodId) { + case uWS::HttpMethod::METHOD_GET: + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) "GET", String::kNormalString, 3)); + break; + case uWS::HttpMethod::METHOD_PUT: + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) "PUT", String::kNormalString, 3)); + break; + case uWS::HttpMethod::METHOD_POST: + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) "POST", String::kNormalString, 4)); + break; + case uWS::HttpMethod::METHOD_HEAD: + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) "HEAD", String::kNormalString, 4)); + break; + case uWS::HttpMethod::METHOD_PATCH: + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) "PATCH", String::kNormalString, 5)); + break; + case uWS::HttpMethod::METHOD_TRACE: + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) "TRACE", String::kNormalString, 5)); + break; + case uWS::HttpMethod::METHOD_DELETE: + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) "DELETE", String::kNormalString, 6)); + break; + case uWS::HttpMethod::METHOD_OPTIONS: + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) "OPTIONS", String::kNormalString, 7)); + break; + case uWS::HttpMethod::METHOD_CONNECT: + args.GetReturnValue().Set(String::NewFromOneByte(args.GetIsolate(), (uint8_t *) "CONNECT", String::kNormalString, 7)); + break; + } + } + + // placeholders + static void unpipe(const FunctionCallbackInfo &args) { + //std::cout << "req.unpipe called" << std::endl; + } + + static void resume(const FunctionCallbackInfo &args) { + //std::cout << "req.resume called" << std::endl; + } + + static void socket(const FunctionCallbackInfo &args) { + // return new empty object + args.GetReturnValue().Set(Object::New(args.GetIsolate())); + } + + static Local getTemplateObject(Isolate *isolate) { + Local reqTemplateLocal = FunctionTemplate::New(isolate); + reqTemplateLocal->SetClassName(String::NewFromUtf8(isolate, "uws.Request")); + reqTemplateLocal->InstanceTemplate()->SetInternalFieldCount(5); + reqTemplateLocal->PrototypeTemplate()->SetAccessor(String::NewFromUtf8(isolate, "url"), Request::url); + reqTemplateLocal->PrototypeTemplate()->SetAccessor(String::NewFromUtf8(isolate, "method"), Request::method); + reqTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "on"), FunctionTemplate::New(isolate, Request::on)); + reqTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "unpipe"), FunctionTemplate::New(isolate, Request::unpipe)); + reqTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "resume"), FunctionTemplate::New(isolate, Request::resume)); + reqTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "socket"), FunctionTemplate::New(isolate, Request::socket)); + + Local reqObjectLocal = reqTemplateLocal->GetFunction()->NewInstance(); + + Local headersTemplate = ObjectTemplate::New(isolate); + headersTemplate->SetNamedPropertyHandler(Request::headers); + + reqObjectLocal->Set(String::NewFromUtf8(isolate, "headers"), headersTemplate->NewInstance()); + return reqObjectLocal; + } + }; + + struct Response { + static void on(const FunctionCallbackInfo &args) { + NativeString eventName(args[0]); + if (std::string(eventName.getData(), eventName.getLength()) == "close") { + args.Holder()->SetInternalField(1, args[1]); + } else { + std::cout << "Warning: res.on(" << std::string(eventName.getData(), eventName.getLength()) << ") is not implemented!" << std::endl; + } + args.GetReturnValue().Set(args.Holder()); + } + + static void end(const FunctionCallbackInfo &args) { + uWS::HttpResponse *res = (uWS::HttpResponse *) args.Holder()->GetAlignedPointerFromInternalField(0); + if (res) { + NativeString nativeString(args[0]); + + ((Persistent *) &res->userData)->Reset(); + ((Persistent *) &res->userData)->~Persistent(); + ((Persistent *) &res->extraUserData)->Reset(); + ((Persistent *) &res->extraUserData)->~Persistent(); + res->end(nativeString.getData(), nativeString.getLength()); + } + } + + // todo: this is slow + static void writeHead(const FunctionCallbackInfo &args) { + uWS::HttpResponse *res = (uWS::HttpResponse *) args.Holder()->GetAlignedPointerFromInternalField(0); + if (res) { + std::string head = "HTTP/1.1 " + std::to_string(args[0]->IntegerValue()) + " "; + + if (args.Length() > 1 && args[1]->IsString()) { + NativeString statusMessage(args[1]); + head.append(statusMessage.getData(), statusMessage.getLength()); + } else { + head += "OK"; + } + + if (args[args.Length() - 1]->IsObject()) { + Local headersObject = args[args.Length() - 1]->ToObject(); + Local headers = headersObject->GetOwnPropertyNames(); + for (int i = 0; i < headers->Length(); i++) { + Local key = headers->Get(i); + Local value = headersObject->Get(key); + + NativeString nativeKey(key); + NativeString nativeValue(value); + + head += "\r\n"; + head.append(nativeKey.getData(), nativeKey.getLength()); + head += ": "; + head.append(nativeValue.getData(), nativeValue.getLength()); + } + } + + head += "\r\n\r\n"; + res->write(head.data(), head.length()); + } + } + + // todo: if not writeHead called before then should write implicit headers + static void write(const FunctionCallbackInfo &args) { + uWS::HttpResponse *res = (uWS::HttpResponse *) args.Holder()->GetAlignedPointerFromInternalField(0); + + if (res) { + NativeString nativeString(args[0]); + res->write(nativeString.getData(), nativeString.getLength()); + } + } + + static void setHeader(const FunctionCallbackInfo &args) { + //std::cout << "res.setHeader called" << std::endl; + } + + static void getHeader(const FunctionCallbackInfo &args) { + //std::cout << "res.getHeader called" << std::endl; + } + + static Local getTemplateObject(Isolate *isolate) { + Local resTemplateLocal = FunctionTemplate::New(isolate); + resTemplateLocal->SetClassName(String::NewFromUtf8(isolate, "uws.Response")); + resTemplateLocal->InstanceTemplate()->SetInternalFieldCount(5); + resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "end"), FunctionTemplate::New(isolate, Response::end)); + resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "writeHead"), FunctionTemplate::New(isolate, Response::writeHead)); + resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "write"), FunctionTemplate::New(isolate, Response::write)); + resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "on"), FunctionTemplate::New(isolate, Response::on)); + resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "setHeader"), FunctionTemplate::New(isolate, Response::setHeader)); + resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "getHeader"), FunctionTemplate::New(isolate, Response::getHeader)); + return resTemplateLocal->GetFunction()->NewInstance(); + } + }; + + // todo: wrap everything up - most important function to get correct + static void createServer(const FunctionCallbackInfo &args) { + + // todo: delete this on destructor + uWS::Group *group = hub.createGroup(); + group->setUserData(new GroupData); + GroupData *groupData = (GroupData *) group->getUserData(); + + Isolate *isolate = args.GetIsolate(); + Persistent *httpRequestCallback = &groupData->httpRequestHandler; + httpRequestCallback->Reset(isolate, Local::Cast(args[0])); + group->onHttpRequest([isolate, httpRequestCallback](uWS::HttpResponse *res, uWS::HttpRequest req, char *data, size_t length, size_t remainingBytes) { + HandleScope hs(isolate); + + currentReq = &req; + + Local reqObject = Local::New(isolate, reqTemplate)->Clone(); + reqObject->SetAlignedPointerInInternalField(0, &req); + new (&res->extraUserData) Persistent(isolate, reqObject); + + Local resObject = Local::New(isolate, resTemplate)->Clone(); + resObject->SetAlignedPointerInInternalField(0, res); + new (&res->userData) Persistent(isolate, resObject); + + // store url & method (needed by Koa and Express) + long methodId = req.getMethod() << 1; + reqObject->SetAlignedPointerInInternalField(3, (void *) methodId); + reqObject->SetInternalField(4, String::NewFromOneByte(isolate, (uint8_t *) req.getUrl().value, String::kNormalString, req.getUrl().valueLength)); + + Local argv[] = {reqObject, resObject}; + Local::New(isolate, *httpRequestCallback)->Call(isolate->GetCurrentContext()->Global(), 2, argv); + + if (length) { + Local dataCallback = reqObject->GetInternalField(1); + if (!dataCallback->IsUndefined()) { + Local argv[] = {ArrayBuffer::New(isolate, data, length)}; + Local::Cast(dataCallback)->Call(isolate->GetCurrentContext()->Global(), 1, argv); + } + + if (!remainingBytes) { + Local endCallback = reqObject->GetInternalField(2); + if (!endCallback->IsUndefined()) { + Local::Cast(endCallback)->Call(isolate->GetCurrentContext()->Global(), 0, nullptr); + } + } + } + + currentReq = nullptr; + reqObject->SetAlignedPointerInInternalField(0, nullptr); + }); + + group->onCancelledHttpRequest([isolate](uWS::HttpResponse *res) { + HandleScope hs(isolate); + + // mark res as invalid + Local resObject = Local::New(isolate, *(Persistent *) &res->userData); + resObject->SetAlignedPointerInInternalField(0, nullptr); + + // mark req as invalid + Local reqObject = Local::New(isolate, *(Persistent *) &res->extraUserData); + reqObject->SetAlignedPointerInInternalField(0, nullptr); + + // emit res 'close' on aborted response + Local closeCallback = resObject->GetInternalField(1); + if (!closeCallback->IsUndefined()) { + Local::Cast(closeCallback)->Call(isolate->GetCurrentContext()->Global(), 0, nullptr); + } + + ((Persistent *) &res->userData)->Reset(); + ((Persistent *) &res->userData)->~Persistent(); + ((Persistent *) &res->extraUserData)->Reset(); + ((Persistent *) &res->extraUserData)->~Persistent(); + }); + + group->onHttpData([isolate](uWS::HttpResponse *res, char *data, size_t length, size_t remainingBytes) { + Local reqObject = Local::New(isolate, *(Persistent *) res->extraUserData); + + Local dataCallback = reqObject->GetInternalField(1); + if (!dataCallback->IsUndefined()) { + Local argv[] = {ArrayBuffer::New(isolate, data, length)}; + Local::Cast(dataCallback)->Call(isolate->GetCurrentContext()->Global(), 1, argv); + } + + if (!remainingBytes) { + Local endCallback = reqObject->GetInternalField(2); + if (!endCallback->IsUndefined()) { + Local::Cast(endCallback)->Call(isolate->GetCurrentContext()->Global(), 0, nullptr); + } + } + }); + + Local newInstance; + if (!args.IsConstructCall()) { + args.GetReturnValue().Set(newInstance = Local::New(args.GetIsolate(), httpPersistent)->NewInstance()); + } else { + args.GetReturnValue().Set(newInstance = args.This()); + } + + newInstance->SetAlignedPointerInInternalField(0, group); + } + + static void on(const FunctionCallbackInfo &args) { + NativeString eventName(args[0]); + std::cout << "Warning: server.on(" << std::string(eventName.getData(), eventName.getLength()) << ") is not implemented!" << std::endl; + } + + static void listen(const FunctionCallbackInfo &args) { + uWS::Group *group = (uWS::Group *) args.Holder()->GetAlignedPointerFromInternalField(0); + std::cout << "listen: " << hub.listen(args[0]->IntegerValue(), nullptr, 0, group) << std::endl; + + if (args[args.Length() - 1]->IsFunction()) { + Local::Cast(args[args.Length() - 1])->Call(args.GetIsolate()->GetCurrentContext()->Global(), 0, nullptr); + } + } + + // var app = getExpressApp(express) + static void getExpressApp(const FunctionCallbackInfo &args) { + Isolate *isolate = args.GetIsolate(); + if (args[0]->IsFunction()) { + Local express = Local::Cast(args[0]); + express->Get(String::NewFromUtf8(isolate, "request"))->ToObject()->SetPrototype(Local::New(args.GetIsolate(), reqTemplate)->GetPrototype()); + express->Get(String::NewFromUtf8(isolate, "response"))->ToObject()->SetPrototype(Local::New(args.GetIsolate(), resTemplate)->GetPrototype()); + + // also change app.listen? + + // change prototypes back? + + args.GetReturnValue().Set(express->NewInstance()); + } + } + + static void getResponsePrototype(const FunctionCallbackInfo &args) { + args.GetReturnValue().Set(Local::New(args.GetIsolate(), resTemplate)->GetPrototype()); + } + + static void getRequestPrototype(const FunctionCallbackInfo &args) { + args.GetReturnValue().Set(Local::New(args.GetIsolate(), reqTemplate)->GetPrototype()); + } + + static Local getHttpServer(Isolate *isolate) { + Local httpServer = FunctionTemplate::New(isolate, HttpServer::createServer); + httpServer->InstanceTemplate()->SetInternalFieldCount(1); + + httpServer->Set(String::NewFromUtf8(isolate, "createServer"), FunctionTemplate::New(isolate, HttpServer::createServer)); + httpServer->Set(String::NewFromUtf8(isolate, "getExpressApp"), FunctionTemplate::New(isolate, HttpServer::getExpressApp)); + httpServer->Set(String::NewFromUtf8(isolate, "getResponsePrototype"), FunctionTemplate::New(isolate, HttpServer::getResponsePrototype)); + httpServer->Set(String::NewFromUtf8(isolate, "getRequestPrototype"), FunctionTemplate::New(isolate, HttpServer::getRequestPrototype)); + httpServer->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "listen"), FunctionTemplate::New(isolate, HttpServer::listen)); + httpServer->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "on"), FunctionTemplate::New(isolate, HttpServer::on)); + + reqTemplate.Reset(isolate, Request::getTemplateObject(isolate)); + resTemplate.Reset(isolate, Response::getTemplateObject(isolate)); + + Local httpServerLocal = httpServer->GetFunction(); + httpPersistent.Reset(isolate, httpServerLocal); + return httpServerLocal; + } +}; -- cgit v1.2.3