Browse Source

Upgrade to Hunt 1.5.x (#5607)

* Upgrade to Hunt 1.5.x

* Fixed: Config error

* Minor fixes

* Add missing make

* /json failed
Xueping 5 years ago
parent
commit
a8dd855223

+ 0 - 52
frameworks/D/hunt/benchmark_config.json

@@ -4,15 +4,10 @@
     {
       "default": {
         "json_url": "/json",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
         "plaintext_url": "/plaintext",
-        "fortune_url": "/fortunes",
-        "update_url": "/updates?queries=",
         "port": 8080,
         "approach": "Realistic",
         "classification": "Platform",
-        "database": "Postgres",
         "framework": "Hunt",
         "language": "D",
         "flavor": "DLang2",
@@ -24,53 +19,6 @@
         "display_name": "hunt",
         "notes": "",
         "versus": "Hunt"
-      },
-      "dmd": {
-        "json_url": "/json",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
-        "plaintext_url": "/plaintext",
-        "fortune_url": "/fortunes",
-        "update_url": "/updates?queries=",
-        "port": 8080,
-        "approach": "Realistic",
-        "classification": "Platform",
-        "database": "Postgres",
-        "framework": "Hunt",
-        "language": "D",
-        "flavor": "DLang2",
-        "orm": "Raw",
-        "platform": "None",
-        "webserver": "None",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "hunt-dmd",
-        "notes": "",
-        "versus": "Hunt",
-        "tags": ["broken"]
-      },
-      "http": {
-        "json_url": "/json",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
-        "plaintext_url": "/plaintext",
-        "fortune_url": "/fortunes",
-        "update_url": "/updates?queries=",
-        "port": 8080,
-        "approach": "Realistic",
-        "classification": "Platform",
-        "database": "Postgres",
-        "framework": "Hunt",
-        "language": "D",
-        "flavor": "DLang2",
-        "orm": "Raw",
-        "platform": "None",
-        "webserver": "None",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "hunt-http",
-        "notes": "",
-        "versus": "Hunt"
       }
     }
   ]

+ 47 - 47
frameworks/D/hunt/dub.json

@@ -6,55 +6,55 @@
 	"homepage": "https://www.huntlabs.net",
 	"license": "Apache-2.0",
 	"dependencies": {
-		"hunt": "~>1.2.2",
-		"hunt-database": "~>1.2.0",
+		"hunt": "~>1.5.0-beta.2",
 		"std_data_json": "~>0.18.2"
 	},
 	"versions": [
-		"POSTGRESQL"
+		"POSTGRESQL1"
 	],
-	"configurations": [
-		{
-			"name": "default",
-			"sourcePaths": ["http"],
-			"libs-posix": [
-				"http_parser"
-			],
-			"lflags-posix": [
-				"-Lhttp-parser/"
-			],
-			"versions": [
-				"HTTP"
-			]
-		},
-		{
-			"name": "minihttp",
-			"sourcePaths": ["pico"],
-			"libs-posix": [
-				"picohttpparser"
-			],
-			"lflags-posix": [
-				"-Lpicohttpparser/"
-			],
-			"versions": [
-				"MINIHTTP"
-			]
-		},
-		{
-			"name": "mmap",
-			"sourcePaths": ["mmap"],
-			"libs-posix": [
-				"picohttpparser"
-			],
-			"lflags-posix": [
-				"-Lpicohttpparser/"
-			],
-			"versions": [
-				"MMAP"
-			]
-		}
-	],
-	"subConfigurations": {
-		"hunt-database": "postgresql"
-	}
+  "configurations": [
+    {
+      "name": "default",
+      "sourcePaths": ["http"],
+      "libs-posix": [
+        "http_parser"
+      ],
+      "lflags-posix": [
+        "-Lhttp-parser/"
+      ],
+      "versions": [
+        "HTTP"
+      ]
+    },
+    {
+      "name": "minihttp",
+      "sourcePaths": ["pico"],
+      "libs-posix": [
+        "picohttpparser"
+      ],
+      "lflags-posix": [
+        "-Lpicohttpparser/"
+      ],
+      "versions": [
+        "MINIHTTP"
+      ]
+    },
+    {
+      "name": "mmap",
+      "sourcePaths": ["mmap"],
+      "libs-posix": [
+        "picohttpparser"
+      ],
+      "lflags-posix": [
+        "-Lpicohttpparser/"
+      ],
+      "versions": [
+        "MMAP"
+      ]
+    }
+  ],
+  "subConfigurations": {
+    "hunt-database": "postgresql"
+  }
+
 }

+ 17 - 17
frameworks/D/hunt/http/app.d

@@ -1,7 +1,7 @@
 /*
  * Collie - An asynchronous event-driven network framework using Dlang development
  *
- * Copyright (C) 2015-2018  Shanghai Putao Technology Co., Ltd 
+ * Copyright (C) 2015-2018  Shanghai Putao Technology Co., Ltd
  *
  * Developer: Putao's Dlang team
  *
@@ -11,7 +11,7 @@
 import std.getopt;
 import std.stdio;
 
-import hunt.database;
+//import hunt.database;
 import hunt.io;
 import hunt.system.Memory : totalCPUs;
 import http.Processor;
@@ -26,22 +26,22 @@ void main(string[] args) {
 		return;
 	}
 
-	version (POSTGRESQL) {
-		DatabaseOption options;
-		debug {
-			options = new DatabaseOption(
-					"postgresql://benchmarkdbuser:[email protected]:5432/hello_world?charset=utf-8");
-		} else {
-			options = new DatabaseOption(
-					"postgresql://benchmarkdbuser:benchmarkdbpass@tfb-database:5432/hello_world?charset=utf-8");
-		}
-						
-		options.setMinimumConnection(totalCPUs*3);
-		options.setMaximumConnection(totalCPUs*3);
-		dbConnection = new Database(options);
-	}
+	//version (POSTGRESQL) {
+	//	DatabaseOption options;
+	//	debug {
+	//		options = new DatabaseOption(
+	//				"postgresql://benchmarkdbuser:[email protected]:5432/hello_world?charset=utf-8");
+	//	} else {
+	//		options = new DatabaseOption(
+	//				"postgresql://benchmarkdbuser:benchmarkdbpass@tfb-database:5432/hello_world?charset=utf-8");
+	//	}
+	//
+	//	options.setMinimumConnection(totalCPUs*3);
+	//	options.setMaximumConnection(totalCPUs*3);
+	//	dbConnection = new Database(options);
+	//}
 
 	AbstractTcpServer httpServer = new HttpServer!(DemoProcessor)("0.0.0.0", port, totalCPUs);
 	writefln("listening on http://%s", httpServer.bindingAddress.toString());
 	httpServer.start();
-}
+}

+ 3 - 3
frameworks/D/hunt/http/http/DemoProcessor.d

@@ -5,7 +5,7 @@ module http.DemoProcessor;
 // import stdx.data.json;
 import std.json;
 
-import hunt.database;
+//import hunt.database;
 import hunt.io;
 import http.Processor;
 import http.HttpURI;
@@ -61,7 +61,7 @@ class DemoProcessor : HttpProcessor {
         } else {
             respondWith404();
         }
-        }    
+        }
     }
 
 
@@ -77,7 +77,7 @@ class DemoProcessor : HttpProcessor {
     version (POSTGRESQL) {
         private void handleDbUpdate(string url) {
             uri.parse(url);
-            
+
             switch(uri.getPath()) {
             case "/queries":
                 UrlEncoded queriesMap = new UrlEncoded();

+ 15 - 15
frameworks/D/hunt/http/http/HttpURI.d

@@ -32,19 +32,19 @@ import hunt.logging;
  * <li>{@link #getQuery()} - query</li>
  * <li>{@link #getFragment()} - fragment</li>
  * </ul>
- * 
+ *
 	https://bob:[email protected]:8080/file;p=1?q=2#third
 	\___/   \_/ \___/ \______________/ \__/\_______/ \_/ \___/
 	|      |    |          |          |      | \_/  |    |
 	Scheme User Password    Host       Port  Path |   | Fragment
 			\_____________________________/       | Query
 						|               Path parameter
-					Authority 
+					Authority
  * <p>
  * Any parameters will be returned from {@link #getPath()}, but are excluded
  * from the return value of {@link #getDecodedPath()}. If there are multiple
  * parameters, the {@link #getParam()} method returns only the last one.
- * 
+ *
  * See_Also:
  *	 https://stackoverflow.com/questions/1634271/url-encoding-the-space-character-or-20
  *   https://web.archive.org/web/20151218094722/http://blog.lunatech.com/2009/02/03/what-every-web-developer-must-know-about-url-encoding
@@ -68,7 +68,7 @@ class HttpURI {
 
 	/**
 	 * Construct a normalized URI. Port is not set if it is the default port.
-	 * 
+	 *
 	 * @param scheme
 	 *            the URI scheme
 	 * @param host
@@ -159,7 +159,7 @@ class HttpURI {
 
 	/**
 	 * Parse according to https://tools.ietf.org/html/rfc7230#section-5.3
-	 * 
+	 *
 	 * @param method
 	 *            the request method
 	 * @param uri
@@ -345,7 +345,7 @@ class HttpURI {
 				case '[':
 					state = State.IPV6;
 					break;
-					
+
 				default:
 					break;
 				}
@@ -367,7 +367,7 @@ class HttpURI {
 						state = State.PATH;
 					}
 					break;
-					
+
 				default:
 					break;
 				}
@@ -415,7 +415,7 @@ class HttpURI {
 					if ('/' == last)
 						encoded = true;
 					break;
-					
+
 				default:
 					break;
 				}
@@ -445,7 +445,7 @@ class HttpURI {
 					// multiple parameters
 					mark = i + 1;
 					break;
-					
+
 				default:
 					break;
 				}
@@ -544,7 +544,7 @@ class HttpURI {
 
 	/**
 	 * The parsed Path.
-	 * 
+	 *
 	 * @return the path as parsed on valid URI. null for invalid URI.
 	 */
 	string getPath() {
@@ -755,10 +755,10 @@ class URIUtils
                             char u = path.charAt(i + 1);
                             if (u == 'u') {
                                 // TODO this is wrong. This is a codepoint not a char
-                                builder.append(cast(char) (0xffff & TypeUtils.parseInt(path, i + 2, 4, 16)));
+                                //builder.append(cast(char) (0xffff & TypeUtils.parseInt(path, i + 2, 4, 16)));
                                 i += 5;
                             } else {
-                                builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
+                                //builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
                                 i += 2;
                             }
                         } else {
@@ -820,10 +820,10 @@ class URIUtils
                         char u = path.charAt(i + 1);
                         if (u == 'u') {
                             // TODO this is wrong. This is a codepoint not a char
-                            builder.append(cast(char) (0xffff & TypeUtils.parseInt(path, i + 2, 4, 16)));
+                           // builder.append(cast(char) (0xffff & TypeUtils.parseInt(path, i + 2, 4, 16)));
                             i += 5;
                         } else {
-                            builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
+                            //builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
                             i += 2;
                         }
                     } else {
@@ -1165,4 +1165,4 @@ class URIUtils
         }
         return false;
     }
-}
+}

+ 69 - 25
frameworks/D/hunt/http/http/Processor.d

@@ -13,7 +13,11 @@ import hunt.collection.ByteBuffer;
 import hunt.logging;
 import hunt.io;
 import hunt.util.DateTime;
-
+import std.array;
+import std.string;
+import core.stdc.string;
+import core.stdc.stdlib;
+import std.stdio;
 
 struct HttpHeader {
 	string name, value;
@@ -29,6 +33,10 @@ version(NO_HTTPPARSER) {
 enum string ResponseData = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\nConnection: Keep-Alive\r\nContent-Type: text/plain\r\nServer: Hunt/1.0\r\nDate: Wed, 17 Apr 2013 12:00:00 GMT\r\n\r\nHello, World!";
 }
 
+
+enum string keepAliveResponseData = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\nConnection: Keep-Alive\r\nContent-Type: text/plain\r\nServer: Hunt/1.0\r\nDate: Wed, 17 Apr 2013 12:00:00 GMT\r\n\r\nHello, World!";
+enum string nokeepAliveResponseData = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\nConnection: close\r\nContent-Type: text/plain\r\nServer: Hunt/1.0\r\nDate: Wed, 17 Apr 2013 12:00:00 GMT\r\n\r\nHello, World!";
+
 abstract class HttpProcessor {
 private:
 	enum State {
@@ -48,7 +56,14 @@ private:
 	HttpRequest request;
 	State state;
 	bool serving;
-	
+  string resData;
+  long index1;
+  long index2;
+  long length1;
+  long length2;
+  void * keepAliveValue;
+  void * nokeepAliveValue;
+
 public:
 	TcpStream client;
 
@@ -58,10 +73,17 @@ public:
 		headers = new HttpHeader[1];
 		pad = ScratchPad(16 * 1024);
 		parser = httpParser(this, HttpParserType.request);
+    index1 = keepAliveResponseData.indexOf("Date:") + 6;
+    length1 = keepAliveResponseData.length;
+    length2 = nokeepAliveResponseData.length;
+    keepAliveValue = malloc(length1);
+    nokeepAliveValue = malloc(length2);
+    memcpy(keepAliveValue , (cast(ubyte[])keepAliveResponseData).ptr, length1);
+    memcpy(nokeepAliveValue , (cast(ubyte[])nokeepAliveResponseData).ptr, length2);
 	}
 
 	void run() {
-		client.onReceived((ByteBuffer buffer) { 
+		client.onReceived((ByteBuffer buffer) {
 			version(NO_HTTPPARSER) {
 				client.write(cast(ubyte[])ResponseData);
 			} else {
@@ -70,10 +92,10 @@ public:
 
 		})
 		.onClosed(() {
-			// notifyClientClosed();
+			 //notifyClientClosed();
 		})
-		.onError((string msg) { 
-			debug warning("Error: ", msg); 
+		.onError((string msg) {
+			debug warning("Error: ", msg);
 		})
 		.start();
 	}
@@ -83,27 +105,49 @@ public:
 	}
 
 	void respondWith(string _body, uint status, HttpHeader[] headers...) {
-		return respondWith(cast(const(ubyte)[]) _body, status, headers);
+    //outBuf.clear();
+
+    if (parser.shouldKeepAlive)
+    {
+      memcpy(keepAliveValue + index1 , (cast(ubyte[])(DateTimeHelper.getDateAsGMT())).ptr, 29);
+      client.write(cast(ubyte[]) keepAliveValue[0 .. length1]);
+    }else
+    {
+      memcpy(nokeepAliveValue + index2 , (cast(ubyte[])(DateTimeHelper.getDateAsGMT())).ptr, 29);
+      client.write(cast(ubyte[]) nokeepAliveValue[0 .. length2]);
+    }
+
+		//return respondWith( _body, status, headers);
 	}
 
-	void respondWith(const(ubyte)[] _body, uint status, HttpHeader[] headers...) {
-		outBuf.clear();
-		formattedWrite(outBuf, "HTTP/1.1 %s OK\r\n", status);
-		outBuf.put("Server: Hunt/1.0\r\n");
-
-		formattedWrite(outBuf, "Date: %s\r\n", DateTimeHelper.getDateAsGMT());
-		if (!parser.shouldKeepAlive)
-			outBuf.put("Connection: close\r\n");
-		foreach (ref hdr; headers) {
-			outBuf.put(hdr.name);
-			outBuf.put(": ");
-			outBuf.put(hdr.value);
-			outBuf.put("\r\n");
-		}
-		formattedWrite(outBuf, "Content-Length: %d\r\n\r\n", _body.length);
-		outBuf.put(cast(string) _body);
-		client.write(cast(ubyte[]) outBuf.data); // TODO: short-writes are quite possible
-	}
+	//void respondWith(string _body, uint status, HttpHeader[] headers...) {
+	//	outBuf.clear();
+  //  //if (parser.shouldKeepAlive)
+  //  //{
+  //  //  formattedWrite(outBuf, "HTTP/1.1 %s OK\r\n Server: Hunt/1.0\r\n Date: %s\r\n Content-Type: text/plain; charset=UTF-8\r\n Content-Length: %d\r\n\r\n%s", status,  DateTimeHelper.getDateAsGMT(), _body.length, _body);
+  //  //}else
+  //  //{
+  //  //  formattedWrite(outBuf, "HTTP/1.1 %s OK\r\n Server: Hunt/1.0\r\n Date: %s\r\n Connection: close\r\n Content-Type: text/plain; charset=UTF-8\r\n Content-Length: %d\r\n\r\n%s", status,  DateTimeHelper.getDateAsGMT(), _body.length, _body);
+  //  //}
+  //  //warning("%s", outBuf.data);
+  //  //client.write(cast(ubyte[]) outBuf.data);
+	//	formattedWrite(outBuf, "HTTP/1.1 %s OK\r\n", status);
+	//	outBuf.put("Server: Hunt/1.0\r\n");
+  //
+	//	formattedWrite(outBuf, "Date: %s\r\n", DateTimeHelper.getDateAsGMT());
+	//	if (!parser.shouldKeepAlive)
+	//		outBuf.put("Connection: close\r\n");
+	//	foreach (ref hdr; headers) {
+	//		outBuf.put(hdr.name);
+	//		outBuf.put(": ");
+	//		outBuf.put(hdr.value);
+	//		outBuf.put("\r\n");
+	//	}
+	//	formattedWrite(outBuf, "Content-Length: %d\r\n\r\n", _body.length);
+	//	outBuf.put( _body);
+  //  warning("%s", outBuf.data);
+	//	client.write(cast(ubyte[]) outBuf.data); // TODO: short-writes are quite possible
+	//}
 
 	void onStart(HttpRequest req) {
 	}

+ 9 - 6
frameworks/D/hunt/http/http/Server.d

@@ -17,9 +17,10 @@ import std.stdio;
 
 import http.Parser;
 import http.Processor;
+import std.experimental.allocator;
 
 shared static this() {
-	DateTimeHelper.startClock();
+	//DateTimeHelper.startClock();
 }
 
 import hunt.io.channel;
@@ -31,11 +32,12 @@ abstract class AbstractTcpServer {
 	protected bool _isStarted = false;
 	protected Address _address;
 	protected int _workersCount;
-	TcpStreamOption _tcpStreamoption;
+	TcpStreamOptions _tcpStreamoption;
+
 
 	this(Address address, int thread = (totalCPUs - 1), int workersCount = 0) {
 		this._address = address;
-		_tcpStreamoption = TcpStreamOption.createOption();
+		_tcpStreamoption = TcpStreamOptions.create();
 		_tcpStreamoption.bufferSize = 1024 * 2;
 		_tcpStreamoption.isKeepalive = false;
 		_group = new EventLoopGroup(cast(uint) thread);
@@ -58,9 +60,9 @@ abstract class AbstractTcpServer {
 
 		trace("Launching http server");
 		debug {
-			_group.start();
+			_group.start(_tcpStreamoption.bufferSize);
 		} else {
-			_group.start(100);
+			_group.start(100, _tcpStreamoption.bufferSize);
 		}
 
 		if (_workersCount) {
@@ -82,7 +84,8 @@ abstract class AbstractTcpServer {
 				}
 				// EventLoop loop = _group.nextLoop();
 				EventLoop loop = _group.nextLoop(socket.handle);
-				TcpStream stream = new TcpStream(loop, socket, _tcpStreamoption);
+				//TcpStream stream = new TcpStream(loop, socket, _tcpStreamoption);
+        TcpStream stream = theAllocator.make!TcpStream(loop, socket, _tcpStreamoption);
 				onConnectionAccepted(stream);
 			} catch (Exception e) {
 				warningf("Failure on accepting %s", e);

+ 4 - 5
frameworks/D/hunt/http/http/UrlEncoded.d

@@ -39,8 +39,8 @@ import std.array;
  *
  * @see java.net.URLEncoder
  */
-class UrlEncoded  : MultiMap!string { 
-    
+class UrlEncoded  : MultiMap!string {
+
     enum string ENCODING = StandardCharsets.UTF_8;
 
 
@@ -104,7 +104,6 @@ class UrlEncoded  : MultiMap!string {
             charset = ENCODING;
 
         StringBuilder result = new StringBuilder(128);
-
         bool delim = false;
         foreach(string key, List!string list; map)
         {
@@ -236,7 +235,6 @@ class UrlEncoded  : MultiMap!string {
      */
     static string decodeString(string encoded, int offset, int length, string charset = ENCODING) {
         StringBuffer buffer = null;
-
         for (int i = 0; i < length; i++) {
             char c = encoded.charAt(offset + i);
             if (c < 0 || c > 0xff) {
@@ -265,7 +263,7 @@ class UrlEncoded  : MultiMap!string {
                         if (i + 2 < length) {
                             int o = offset + i + 1;
                             i += 3;
-                            ba[n] = cast(byte) TypeUtils.parseInt(encoded, o, 2, 16);
+                            //ba[n] = cast(byte) TypeUtils.parseInt(encoded, o, 2, 16);
                             n++;
                         } else {
                             ba[n++] = cast(byte) '?';
@@ -326,6 +324,7 @@ class UrlEncoded  : MultiMap!string {
 
         int len = cast(int)bytes.length;
         byte[] encoded = new byte[bytes.length * 3];
+        warningf("encoded");
         int n = 0;
         bool noEncode = true;
 

+ 5 - 1
frameworks/D/hunt/hunt.dockerfile

@@ -3,7 +3,11 @@ FROM dlangchina/dlang-ldc:latest
 ADD ./ /hunt
 WORKDIR /hunt
 
-RUN apt-get update -y && apt-get install -y --no-install-recommends git && apt-get install -yqq libpq-dev libsqlite3-dev default-libmysqlclient-dev zlib1g-dev  && rm -rf /var/lib/apt/lists/* && rm -rf /var/cache/apt/*
+RUN apt-get update -y 
+RUN apt-get install -y --no-install-recommends make
+RUN apt-get install -y --no-install-recommends git
+RUN apt-get install -yqq libpq-dev libsqlite3-dev default-libmysqlclient-dev zlib1g-dev
+RUN rm -rf /var/lib/apt/lists/* && rm -rf /var/cache/apt/*
 
 RUN git clone https://github.com/h2o/picohttpparser.git && \
     cp -rf patches/Makefile picohttpparser && \

+ 1 - 1
frameworks/D/hunt/mmap/http/Server.d

@@ -17,7 +17,7 @@ import http.Parser;
 import http.Processor;
 
 shared static this() {
-	DateTimeHelper.startClock();
+	//DateTimeHelper.startClock();
 }
 
 import hunt.io.channel;

+ 18 - 18
frameworks/D/hunt/pico/app.d

@@ -1,7 +1,7 @@
 /*
  * Collie - An asynchronous event-driven network framework using Dlang development
  *
- * Copyright (C) 2015-2018  Shanghai Putao Technology Co., Ltd 
+ * Copyright (C) 2015-2018  Shanghai Putao Technology Co., Ltd
  *
  * Developer: Putao's Dlang team
  *
@@ -11,13 +11,13 @@
 import std.getopt;
 import std.stdio;
 
-import hunt.database;
+//import hunt.database;
 import hunt.io;
 import hunt.system.Memory : totalCPUs;
 import http.Processor;
 import http.Server;
 import http.DemoProcessor;
-
+import std.experimental.allocator;
 void main(string[] args) {
 	ushort port = 8080;
 	GetoptResult o = getopt(args, "port|p", "Port (default 8080)", &port);
@@ -26,22 +26,22 @@ void main(string[] args) {
 		return;
 	}
 
-	version (POSTGRESQL) {
-		DatabaseOption options;
-		debug {
-			options = new DatabaseOption(
-					"postgresql://benchmarkdbuser:[email protected]:5432/hello_world?charset=utf-8");
-		} else {
-			options = new DatabaseOption(
-					"postgresql://benchmarkdbuser:benchmarkdbpass@tfb-database:5432/hello_world?charset=utf-8");
-		}
-		
-		options.setMinimumConnection(totalCPUs*3);
-		options.setMaximumConnection(totalCPUs*3);
-		dbConnection = new Database(options);
-	}
+	//version (POSTGRESQL) {
+	//	DatabaseOption options;
+	//	debug {
+	//		options = new DatabaseOption(
+	//				"postgresql://benchmarkdbuser:[email protected]:5432/hello_world?charset=utf-8");
+	//	} else {
+	//		options = new DatabaseOption(
+	//				"postgresql://benchmarkdbuser:benchmarkdbpass@tfb-database:5432/hello_world?charset=utf-8");
+	//	}
+  //
+	//	options.setMinimumConnection(totalCPUs*3);
+	//	options.setMaximumConnection(totalCPUs*3);
+	//	dbConnection = new Database(options);
+	//}
 
 	AbstractTcpServer httpServer = new HttpServer!(DemoProcessor)("0.0.0.0", port, totalCPUs);
 	writefln("listening on http://%s", httpServer.bindingAddress.toString());
 	httpServer.start();
-}
+}

+ 69 - 70
frameworks/D/hunt/pico/http/DemoProcessor.d

@@ -5,7 +5,6 @@ module http.DemoProcessor;
 // import stdx.data.json;
 import std.json;
 
-import hunt.database;
 import hunt.io;
 import http.Common;
 import http.Processor;
@@ -20,7 +19,7 @@ import std.random;
 import std.string;
 
 version (POSTGRESQL) {
-    __gshared Database dbConnection;
+   // __gshared Database dbConnection;
 }
 
 enum HttpHeader textHeader = HttpHeader("Content-Type", "text/plain; charset=UTF-8");
@@ -45,10 +44,10 @@ class DemoProcessor : HttpProcessor {
 
         string path = req.uri;
         if(path.length == plaintextLength) { // plaintext
-            respondWith("Hello, World!", 200, textHeader);
+            respondWith(RET.TEXT, 200, textHeader);
         } else if(path.length == jsonLength) { // json
-            JSONValue js = JSONValue(["message" : JSONValue("Hello, World!")]);
-            respondWith(js.toJSON(), 200, jsonHeader);
+            //JSONValue js = JSONValue(["message" : JSONValue("Hello, World!")]);
+            respondWith(RET.JSON, 200, jsonHeader);
         } else {
 
         version (POSTGRESQL) {
@@ -63,23 +62,23 @@ class DemoProcessor : HttpProcessor {
         } else {
             respondWith404();
         }
-        }    
+        }
     }
 
 
     private void respondWith404() {
-        version (POSTGRESQL) {
-            respondWith("The available paths are: /plaintext, /json, /db, /fortunes," ~
-             " /queries?queries=number, /updates?queries=number", 404);
-        } else {
-            respondWith("The available paths are: /plaintext, /json", 404);
-        }
+        //version (POSTGRESQL) {
+        //    respondWith("The available paths are: /plaintext, /json, /db, /fortunes," ~
+        //     " /queries?queries=number, /updates?queries=number", 404);
+        //} else {
+        //    respondWith("The available paths are: /plaintext, /json", 404);
+        //}
     }
 
     version (POSTGRESQL) {
         private void handleDbUpdate(string url) {
             uri.parse(url);
-            
+
             switch(uri.getPath()) {
             case "/queries":
                 UrlEncoded queriesMap = new UrlEncoded();
@@ -152,44 +151,44 @@ class DemoProcessor : HttpProcessor {
 
 
         private void respondSingleQuery() {
-            int id = uniform(1, 10001);
-            string query = "SELECT randomNumber FROM world WHERE id = " ~ id.to!string;
-            ResultSet rs = dbConnection.query(query);
-
-            JSONValue js = JSONValue(["id" : JSONValue(id), "randomNumber"
-                    : JSONValue(to!int(rs.front()[0]))]);
-
-            respondWith(js.toJSON(), 200, jsonHeader);
+            //int id = uniform(1, 10001);
+            //string query = "SELECT randomNumber FROM world WHERE id = " ~ id.to!string;
+            //ResultSet rs = dbConnection.query(query);
+            //
+            //JSONValue js = JSONValue(["id" : JSONValue(id), "randomNumber"
+            //        : JSONValue(to!int(rs.front()[0]))]);
+            //
+            //respondWith(js.toJSON(), 200, jsonHeader);
         }
 
         private void respondMultipleQuery(int queries) {
-            if (queries < 1)
-                queries = 1;
-            else if (queries > 500)
-                queries = 500;
-
-            JSONValue[] arr = new JSONValue[queries];
-            for (int i = 0; i < queries; i++) {
-                immutable id = uniform(1, 10001);
-                immutable query = "SELECT randomNumber FROM world WHERE id = " ~ id.to!string;
-                ResultSet rs = dbConnection.query(query);
-
-                arr[i] = JSONValue(["id" : JSONValue(id), "randomNumber"
-                        : JSONValue(to!int(rs.front()[0]))]);
-            }
-            JSONValue js = JSONValue(arr);
-            respondWith(js.toJSON(), 200, jsonHeader);
+            //if (queries < 1)
+            //    queries = 1;
+            //else if (queries > 500)
+            //    queries = 500;
+            //
+            //JSONValue[] arr = new JSONValue[queries];
+            //for (int i = 0; i < queries; i++) {
+            //    immutable id = uniform(1, 10001);
+            //    immutable query = "SELECT randomNumber FROM world WHERE id = " ~ id.to!string;
+            //    ResultSet rs = dbConnection.query(query);
+            //
+            //    arr[i] = JSONValue(["id" : JSONValue(id), "randomNumber"
+            //            : JSONValue(to!int(rs.front()[0]))]);
+            //}
+            //JSONValue js = JSONValue(arr);
+            //respondWith(js.toJSON(), 200, jsonHeader);
         }
 
         private void respondFortunes() {
-            immutable query = "SELECT id, message::text FROM Fortune";
-            ResultSet rs = dbConnection.query(query);
-            FortuneModel[] data = rs.map!(f => FortuneModel(f["id"].to!int, f["message"])).array;
-            data ~= FortuneModel(0, "Additional fortune added at request time.");
-            data.sort!((a, b) => a.message < b.message);
-            // trace(data);
-
-            respondWith(randerFortunes(data), 200, htmlHeader);
+            //immutable query = "SELECT id, message::text FROM Fortune";
+            //ResultSet rs = dbConnection.query(query);
+            //FortuneModel[] data = rs.map!(f => FortuneModel(f["id"].to!int, f["message"])).array;
+            //data ~= FortuneModel(0, "Additional fortune added at request time.");
+            //data.sort!((a, b) => a.message < b.message);
+            //// trace(data);
+            //
+            //respondWith(randerFortunes(data), 200, htmlHeader);
         }
 
         static string randerFortunes(FortuneModel[] data) {
@@ -219,31 +218,31 @@ class DemoProcessor : HttpProcessor {
         }
 
         private void respondUpdates(int queries) {
-            if (queries < 1)
-                queries = 1;
-            else if (queries > 500)
-                queries = 500;
-
-            JSONValue[] arr = new JSONValue[queries];
-            for (int i = 0; i < queries; i++) {
-                immutable id = uniform(1, 10001);
-                immutable idString = id.to!string;
-                immutable query = "SELECT randomNumber FROM world WHERE id = " ~ idString;
-                ResultSet rs = dbConnection.query(query);
-                int randomNumber = to!int(rs.front()[0]);
-                debug tracef("id=%d, randomNumber=%d", id, randomNumber);
-
-                randomNumber = uniform(1, 10001);
-                string updateSql = "UPDATE world SET randomNumber = "
-                    ~ randomNumber.to!string ~ "  WHERE id = " ~ idString;
-                int r = dbConnection.execute(updateSql);
-                // debug tracef("r=%d", r);
-
-                arr[i] = JSONValue(["id" : JSONValue(id), "randomNumber" : JSONValue(randomNumber)]);
-            }
-
-            JSONValue js = JSONValue(arr);
-            respondWith(js.toJSON(), 200, jsonHeader);
+            //if (queries < 1)
+            //    queries = 1;
+            //else if (queries > 500)
+            //    queries = 500;
+            //
+            //JSONValue[] arr = new JSONValue[queries];
+            //for (int i = 0; i < queries; i++) {
+            //    immutable id = uniform(1, 10001);
+            //    immutable idString = id.to!string;
+            //    immutable query = "SELECT randomNumber FROM world WHERE id = " ~ idString;
+            //    ResultSet rs = dbConnection.query(query);
+            //    int randomNumber = to!int(rs.front()[0]);
+            //    debug tracef("id=%d, randomNumber=%d", id, randomNumber);
+            //
+            //    randomNumber = uniform(1, 10001);
+            //    string updateSql = "UPDATE world SET randomNumber = "
+            //        ~ randomNumber.to!string ~ "  WHERE id = " ~ idString;
+            //    int r = dbConnection.execute(updateSql);
+            //    // debug tracef("r=%d", r);
+            //
+            //    arr[i] = JSONValue(["id" : JSONValue(id), "randomNumber" : JSONValue(randomNumber)]);
+            //}
+            //
+            //JSONValue js = JSONValue(arr);
+            //respondWith(js.toJSON(), 200, jsonHeader);
         }
     }
 }

+ 17 - 18
frameworks/D/hunt/pico/http/HttpURI.d

@@ -32,19 +32,19 @@ import hunt.logging;
  * <li>{@link #getQuery()} - query</li>
  * <li>{@link #getFragment()} - fragment</li>
  * </ul>
- * 
+ *
 	https://bob:[email protected]:8080/file;p=1?q=2#third
 	\___/   \_/ \___/ \______________/ \__/\_______/ \_/ \___/
 	|      |    |          |          |      | \_/  |    |
 	Scheme User Password    Host       Port  Path |   | Fragment
 			\_____________________________/       | Query
 						|               Path parameter
-					Authority 
+					Authority
  * <p>
  * Any parameters will be returned from {@link #getPath()}, but are excluded
  * from the return value of {@link #getDecodedPath()}. If there are multiple
  * parameters, the {@link #getParam()} method returns only the last one.
- * 
+ *
  * See_Also:
  *	 https://stackoverflow.com/questions/1634271/url-encoding-the-space-character-or-20
  *   https://web.archive.org/web/20151218094722/http://blog.lunatech.com/2009/02/03/what-every-web-developer-must-know-about-url-encoding
@@ -68,7 +68,7 @@ class HttpURI {
 
 	/**
 	 * Construct a normalized URI. Port is not set if it is the default port.
-	 * 
+	 *
 	 * @param scheme
 	 *            the URI scheme
 	 * @param host
@@ -159,7 +159,7 @@ class HttpURI {
 
 	/**
 	 * Parse according to https://tools.ietf.org/html/rfc7230#section-5.3
-	 * 
+	 *
 	 * @param method
 	 *            the request method
 	 * @param uri
@@ -345,7 +345,7 @@ class HttpURI {
 				case '[':
 					state = State.IPV6;
 					break;
-					
+
 				default:
 					break;
 				}
@@ -367,7 +367,7 @@ class HttpURI {
 						state = State.PATH;
 					}
 					break;
-					
+
 				default:
 					break;
 				}
@@ -415,7 +415,7 @@ class HttpURI {
 					if ('/' == last)
 						encoded = true;
 					break;
-					
+
 				default:
 					break;
 				}
@@ -445,7 +445,7 @@ class HttpURI {
 					// multiple parameters
 					mark = i + 1;
 					break;
-					
+
 				default:
 					break;
 				}
@@ -544,7 +544,7 @@ class HttpURI {
 
 	/**
 	 * The parsed Path.
-	 * 
+	 *
 	 * @return the path as parsed on valid URI. null for invalid URI.
 	 */
 	string getPath() {
@@ -741,7 +741,6 @@ class URIUtils
     static string decodePath(string path, int offset, int length) {
         try {
             StringBuilder builder = null;
-
             int end = offset + length;
             for (int i = offset; i < end; i++) {
                 char c = path[i];
@@ -755,10 +754,10 @@ class URIUtils
                             char u = path.charAt(i + 1);
                             if (u == 'u') {
                                 // TODO this is wrong. This is a codepoint not a char
-                                builder.append(cast(char) (0xffff & TypeUtils.parseInt(path, i + 2, 4, 16)));
+                                //builder.append(cast(char) (0xffff & TypeUtils.parseInt(path, i + 2, 4, 16)));
                                 i += 5;
                             } else {
-                                builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
+                                //builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
                                 i += 2;
                             }
                         } else {
@@ -820,10 +819,10 @@ class URIUtils
                         char u = path.charAt(i + 1);
                         if (u == 'u') {
                             // TODO this is wrong. This is a codepoint not a char
-                            builder.append(cast(char) (0xffff & TypeUtils.parseInt(path, i + 2, 4, 16)));
+                           // builder.append(cast(char) (0xffff & TypeUtils.parseInt(path, i + 2, 4, 16)));
                             i += 5;
                         } else {
-                            builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
+                            //builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
                             i += 2;
                         }
                     } else {
@@ -875,6 +874,8 @@ class URIUtils
      * @return the canonical path, or null if path traversal above root.
      */
     static string canonicalPath(string path) {
+
+      warningf("canonicalPath ...............");
         if (path.empty)
             return path;
 
@@ -984,7 +985,6 @@ class URIUtils
     static string canonicalEncodedPath(string path) {
         if (path.empty)
             return path;
-
         bool slash = true;
         int end = cast(int)path.length;
         int i = 0;
@@ -1094,7 +1094,6 @@ class URIUtils
     static string compactPath(string path) {
         if (path == null || path.length == 0)
             return path;
-
         int state = 0;
         int end = cast(int)path.length;
         int i = 0;
@@ -1165,4 +1164,4 @@ class URIUtils
         }
         return false;
     }
-}
+}

+ 11 - 11
frameworks/D/hunt/pico/http/Parser.d

@@ -11,7 +11,7 @@ import std.conv;
 import std.range.primitives;
 import core.stdc.string;
 
-
+import std.experimental.allocator;
 
 /* contains name and value of a header (name == NULL if is a continuing line
  * of a multiline header */
@@ -24,17 +24,17 @@ struct phr_header {
 
 /* returns number of bytes consumed if successful, -2 if request is partial,
  * -1 if failed */
-extern (C) pure @nogc nothrow int phr_parse_request(const char *buf, size_t len, const char **method, 
+extern (C) pure @nogc nothrow int phr_parse_request(const char *buf, size_t len, const char **method,
 	size_t *method_len, const char **path, size_t *path_len,
     int *minor_version, phr_header *headers, size_t *num_headers, size_t last_len);
 
 /* ditto */
-extern (C) pure @nogc nothrow int phr_parse_response(const char *_buf, size_t len, int *minor_version, 
+extern (C) pure @nogc nothrow int phr_parse_response(const char *_buf, size_t len, int *minor_version,
 	int *status, const char **msg, size_t *msg_len,
     phr_header *headers, size_t *num_headers, size_t last_len);
 
 /* ditto */
-extern (C) pure @nogc nothrow int phr_parse_headers(const char *buf, size_t len, 
+extern (C) pure @nogc nothrow int phr_parse_headers(const char *buf, size_t len,
 	phr_header *headers, size_t *num_headers, size_t last_len);
 
 /* should be zero-filled before start */
@@ -75,7 +75,7 @@ class HttpException : Exception {
 }
 
 struct HttpParser(Interceptor) {
-	
+
 private {
 	Interceptor interceptor;
 	Throwable failure;
@@ -114,7 +114,7 @@ private {
 
 	HttpHeader[] headers(bool canCopy=false)() {
 		HttpHeader[] hs = new HttpHeader[num_headers];
-		
+    //HttpHeader[] hs = theAllocator.make!(HttpHeader[num_headers]);
 		for(int i; i<num_headers; i++) {
 			phr_header* h = &_headers[i];
 			static if(canCopy) {
@@ -150,15 +150,15 @@ private {
 
 		failure = null;
 		num_headers = cast(int)_headers.length;
-		int pret = phr_parse_request(cast(const char*)chunk.ptr, cast(int)chunk.length, 
-					&_method, &method_len, 
+		int pret = phr_parse_request(cast(const char*)chunk.ptr, cast(int)chunk.length,
+					&_method, &method_len,
 					&path, &path_len,
-					&minor_version, 
+					&minor_version,
 					_headers.ptr, &num_headers,
 					0);
 		debug {
 			infof("buffer: %d bytes, request: %d bytes", chunk.length, pret);
-		} 
+		}
 
 		if(pret > 0) {
 			/* successfully parsed the request */
@@ -175,7 +175,7 @@ private {
 			debug warning("parsing incomplete");
 			num_headers = 0;
 			debug infof("pret=%d, chunk=%d", pret, chunk.length);
-			return 0;			
+			return 0;
 		}
 
 		warning("wrong data format");

+ 134 - 32
frameworks/D/hunt/pico/http/Processor.d

@@ -15,10 +15,60 @@ import http.Common;
 import hunt.logging;
 import hunt.io;
 import hunt.util.DateTime;
+import std.array;
+import std.string;
+import core.stdc.string;
+import core.stdc.stdlib;
+import std.stdio;
 
-
+import std.experimental.allocator;
 private	alias Parser = HttpParser!HttpProcessor;
 
+void * keepAliveValue;
+void * nokeepAliveValue;
+long index1;
+long index2;
+long length1;
+long length2;
+
+
+void * keepAliveJson;
+void * nokeepAliveJson;
+long index3;
+long index4;
+long length3;
+long length4;
+
+
+enum RET
+{
+    TEXT,
+    JSON,
+    DEF
+}
+
+
+static this()
+{
+  index1 =  keepAliveResponseData.indexOf("Date:") + 6;
+  index2 = nokeepAliveResponseData.indexOf("Date:") + 6;
+  length1 = keepAliveResponseData.length;
+  length2 = nokeepAliveResponseData.length;
+  keepAliveValue = malloc(length1);
+  nokeepAliveValue  = malloc(length2);
+  memcpy(keepAliveValue , (cast(ubyte[])keepAliveResponseData).ptr, length1);
+  memcpy(nokeepAliveValue , (cast(ubyte[])nokeepAliveResponseData).ptr, length2);
+
+
+  index3 =  keepAliveJsonDate.indexOf("Date:") + 6;
+  index4 = nokeepAliveJsonDate.indexOf("Date:") + 6;
+  length3 = keepAliveJsonDate.length;
+  length4 = nokeepAliveJsonDate.length;
+  keepAliveJson = malloc(length3);
+  nokeepAliveJson  = malloc(length4);
+  memcpy(keepAliveJson , (cast(ubyte[])keepAliveJsonDate).ptr, length3);
+  memcpy(nokeepAliveJson , (cast(ubyte[])nokeepAliveJsonDate).ptr, length4);
+}
 
 struct HttpRequest {
 	private Parser* parser;
@@ -36,19 +86,25 @@ struct HttpRequest {
 	}
 }
 
-version(NO_HTTPPARSER) {
+//version(NO_HTTPPARSER) {
 enum string ResponseData = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\nConnection: Keep-Alive\r\nContent-Type: text/plain\r\nServer: Hunt/1.0\r\nDate: Wed, 17 Apr 2013 12:00:00 GMT\r\n\r\nHello, World!";
-}
+//}
+
+enum string keepAliveResponseData = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\nConnection: Keep-Alive\r\nContent-Type: text/plain\r\nServer: Hunt/1.0\r\nDate: Wed, 17 Apr 2013 12:00:00 GMT\r\n\r\nHello, World!";
+enum string nokeepAliveResponseData = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\nConnection: close\r\nContent-Type: text/plain\r\nServer: Hunt/1.0\r\nDate: Wed, 17 Apr 2013 12:00:00 GMT\r\n\r\nHello, World!";
+
+enum string keepAliveJsonDate = "HTTP/1.1 200 OK\r\nContent-Length: 27\r\nConnection: Keep-Alive\r\nContent-Type: application/json; charset=UTF-8\r\nServer: Hunt/1.0\r\nDate: Wed, 17 Apr 2013 12:00:00 GMT\r\n\r\n{\"message\":\"Hello, World!\"}";
+enum string nokeepAliveJsonDate = "HTTP/1.1 200 OK\r\nContent-Length: 27\r\nConnection: close\r\nContent-Type: application/json; charset=UTF-8\r\nServer: Hunt/1.0\r\nDate: Wed, 17 Apr 2013 12:00:00 GMT\r\n\r\n{\"message\":\"Hello, World!\"}";
 
 abstract class HttpProcessor {
-	
+
 package:
-	Appender!(char[]) outBuf;
 	HttpHeader[] headers; // buffer for headers
 	Parser parser;
 	HttpRequest request;
 	bool serving;
-	
+
+
 public:
 	TcpStream client;
 
@@ -56,12 +112,20 @@ public:
 		serving = true;
 		client = sock;
 		headers = new HttpHeader[1];
+    //headers = theAllocator.makeArray!(HttpHeader)(1);
 		parser = httpParser(this);
 		request.parser = &parser;
+    //index1 = keepAliveResponseData.indexOf("Date:") + 6;
+    //length1 = keepAliveResponseData.length;
+    //length2 = nokeepAliveResponseData.length;
+    //keepAliveValue = malloc(length1);
+    //nokeepAliveValue = malloc(length2);
+    //memcpy(keepAliveValue , (cast(ubyte[])keepAliveResponseData).ptr, length1);
+    //memcpy(nokeepAliveValue , (cast(ubyte[])nokeepAliveResponseData).ptr, length2);
 	}
 
 	void run() {
-		client.onReceived((ByteBuffer buffer) { 
+		client.onReceived((ByteBuffer buffer) {
 			version(NO_HTTPPARSER) {
 				client.write(cast(ubyte[])ResponseData);
 			} else {
@@ -70,15 +134,15 @@ public:
 					buffer.position(buffer.position() + len);
 				} catch(Exception ex) {
 					buffer.clear(); // drop all the  wrong data
-					respondWith(ex.msg, 500);
+					//respondWith(ex.msg, 500);
 				}
 			}
 		})
 		.onClosed(() {
 			// notifyClientClosed();
 		})
-		.onError((string msg) { 
-			debug warning("Error: ", msg); 
+		.onError((string msg) {
+			 warning("Error: ", msg);
 		})
 		.start();
 	}
@@ -87,32 +151,70 @@ public:
 		debug tracef("The connection[%s] is closed", client.remoteAddress());
 	}
 
-	void respondWith(string _body, uint status, HttpHeader[] headers...) {
-		return respondWith(cast(const(ubyte)[]) _body, status, headers);
+	void respondWith(RET type, uint status, HttpHeader[] headers...) {
+    switch(type)
+    {
+      case RET.TEXT:
+      {
+        if (parser.shouldKeepAlive)
+        {
+          memcpy(keepAliveValue + index1 , (cast(ubyte[])(DateTimeHelper.getDateAsGMT())).ptr, 29);
+          //memcpy(keepAliveValue + index1 , (cast(ubyte[])("Wed, 17 Apr 2013 12:00:00 GMT")).ptr, 29);
+          client.write(cast(ubyte[]) keepAliveValue[0 .. length1]);
+        }else
+        {
+          memcpy(nokeepAliveValue + index2 , (cast(ubyte[])(DateTimeHelper.getDateAsGMT())).ptr, 29);
+          //memcpy(nokeepAliveValue + index2 , (cast(ubyte[])("Wed, 17 Apr 2013 12:00:00 GMT")).ptr, 29);
+          client.write(cast(ubyte[]) nokeepAliveValue[0 .. length2]);
+        }
+        break;
+      }
+      case RET.JSON:
+      {
+        if (parser.shouldKeepAlive)
+        {
+          memcpy(keepAliveJson + index3 , (cast(ubyte[])(DateTimeHelper.getDateAsGMT())).ptr, 29);
+          //memcpy(keepAliveValue + index1 , (cast(ubyte[])("Wed, 17 Apr 2013 12:00:00 GMT")).ptr, 29);
+          client.write(cast(ubyte[]) keepAliveJson[0 .. length3]);
+        }else
+        {
+          memcpy(nokeepAliveJson + index4 , (cast(ubyte[])(DateTimeHelper.getDateAsGMT())).ptr, 29);
+          //memcpy(nokeepAliveValue + index2 , (cast(ubyte[])("Wed, 17 Apr 2013 12:00:00 GMT")).ptr, 29);
+          client.write(cast(ubyte[]) nokeepAliveJson[0 .. length4]);
+        }
+        break;
+      }
+      default:
+      {
+
+      }
+    }
+
+		//return respondWith(cast(const(ubyte)[]) _body, status, headers);
 	}
 
-	void respondWith(const(ubyte)[] _body, uint status, HttpHeader[] headers...) {
-		outBuf.clear();
-		formattedWrite(outBuf, "HTTP/1.1 %s OK\r\n", status);
-		outBuf.put("Server: Hunt/1.0\r\n");
-
-		formattedWrite(outBuf, "Date: %s\r\n", DateTimeHelper.getDateAsGMT());
-		if (!parser.shouldKeepAlive)
-			outBuf.put("Connection: close\r\n");
-		foreach (ref hdr; headers) {
-			outBuf.put(hdr.name);
-			outBuf.put(": ");
-			outBuf.put(hdr.value);
-			outBuf.put("\r\n");
-		}
-		formattedWrite(outBuf, "Content-Length: %d\r\n\r\n", _body.length);
-		outBuf.put(cast(string) _body);
-		client.write(cast(ubyte[]) outBuf.data); // TODO: short-writes are quite possible
-	}
+	//void respondWith(const(ubyte)[] _body, uint status, HttpHeader[] headers...) {
+	//	outBuf.clear();
+	//	formattedWrite(outBuf, "HTTP/1.1 %s OK\r\n", status);
+	//	outBuf.put("Server: Hunt/1.0\r\n");
+  //
+	//	formattedWrite(outBuf, "Date: %s\r\n", DateTimeHelper.getDateAsGMT());
+	//	if (!parser.shouldKeepAlive)
+	//		outBuf.put("Connection: close\r\n");
+	//	foreach (ref hdr; headers) {
+	//		outBuf.put(hdr.name);
+	//		outBuf.put(": ");
+	//		outBuf.put(hdr.value);
+	//		outBuf.put("\r\n");
+	//	}
+	//	formattedWrite(outBuf, "Content-Length: %d\r\n\r\n", _body.length);
+	//	outBuf.put(cast(string) _body);
+	//	client.write(cast(ubyte[]) outBuf.data); // TODO: short-writes are quite possible
+	//}
 
 	void onChunk(ref HttpRequest req, const(ubyte)[] chunk) {
 		// TODO: Tasks pending completion - 5/16/2019, 5:40:18 PM
-		// 
+		//
 	}
 
 	void onComplete(ref HttpRequest req);
@@ -127,7 +229,7 @@ public:
 		try {
 			onComplete(request);
 		} catch(Exception ex) {
-			respondWith(ex.msg, 500);
+			//respondWith(ex.msg, 500);
 		}
 		if (!parser.shouldKeepAlive)
 			serving = false;

+ 19 - 10
frameworks/D/hunt/pico/http/Server.d

@@ -17,13 +17,16 @@ import std.stdio;
 
 import http.Parser;
 import http.Processor;
+import hunt.io.channel.Common;
 
 shared static this() {
 	DateTimeHelper.startClock();
 }
 
-import hunt.io.channel;
 
+
+import hunt.io.channel;
+import std.experimental.allocator;
 /**
 */
 abstract class AbstractTcpServer {
@@ -31,15 +34,17 @@ abstract class AbstractTcpServer {
 	protected bool _isStarted = false;
 	protected Address _address;
 	protected int _workersCount;
-	TcpStreamOption _tcpStreamoption;
+	TcpStreamOptions _tcpStreamoption;
 
 	this(Address address, int thread = (totalCPUs - 1), int workersCount = 0) {
 		this._address = address;
-		_tcpStreamoption = TcpStreamOption.createOption();
-		_tcpStreamoption.bufferSize = 1024 * 2;
+		_tcpStreamoption = TcpStreamOptions.create();
+		_tcpStreamoption.bufferSize = 1024 * 4;
 		_tcpStreamoption.isKeepalive = false;
-		_group = new EventLoopGroup(cast(uint) thread);
+		_group = new EventLoopGroup(cast(uint) thread*6);
+    //_group = theAllocator.make!EventLoopGroup(cast(uint) thread*2);
 		this._workersCount = workersCount;
+    //defaultPoolThreads(thread);
 	}
 
 	@property Address bindingAddress() {
@@ -52,15 +57,17 @@ abstract class AbstractTcpServer {
 		_isStarted = true;
 
 		Socket server = new TcpSocket();
+    //Socket server = theAllocator.make!TcpSocket;
 		server.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
 		server.bind(new InternetAddress("0.0.0.0", 8080));
+    //server.bind( theAllocator.make!(InternetAddress("0.0.0.0", 8080)));
 		server.listen(8192);
 
 		trace("Launching mini-http server");
 		debug {
-			_group.start();
+			_group.start(_tcpStreamoption.bufferSize);
 		} else {
-			_group.start(100);
+			_group.start(_tcpStreamoption.bufferSize);
 		}
 
 		if (_workersCount) {
@@ -82,7 +89,8 @@ abstract class AbstractTcpServer {
 				}
 				// EventLoop loop = _group.nextLoop();
 				EventLoop loop = _group.nextLoop(socket.handle);
-				TcpStream stream = new TcpStream(loop, socket, _tcpStreamoption);
+        TcpStream stream = theAllocator.make!TcpStream(loop, socket, _tcpStreamoption);
+				//TcpStream stream = new TcpStream(loop, socket, _tcpStreamoption);
 				onConnectionAccepted(stream);
 			} catch (Exception e) {
 				warningf("Failure on accepting %s", e);
@@ -109,7 +117,7 @@ alias ProcessorCreater = HttpProcessor delegate(TcpStream client);
 class HttpServer(T) : AbstractTcpServer if (is(T : HttpProcessor)) {
 
 	this(string ip, ushort port, int thread = (totalCPUs - 1)) {
-		super(new InternetAddress(ip, port), thread);
+		super(theAllocator.make!InternetAddress(ip, port), thread);
 	}
 
 	this(Address address, int thread = (totalCPUs - 1)) {
@@ -117,7 +125,8 @@ class HttpServer(T) : AbstractTcpServer if (is(T : HttpProcessor)) {
 	}
 
 	override protected void onConnectionAccepted(TcpStream client) {
-		HttpProcessor httpProcessor = new T(client);
+		//HttpProcessor httpProcessor = new T(client);
+    HttpProcessor httpProcessor = theAllocator.make!T(client);
 		httpProcessor.run();
 	}
 

+ 5 - 6
frameworks/D/hunt/pico/http/UrlEncoded.d

@@ -39,8 +39,8 @@ import std.array;
  *
  * @see java.net.URLEncoder
  */
-class UrlEncoded  : MultiMap!string { 
-    
+class UrlEncoded  : MultiMap!string {
+
     enum string ENCODING = StandardCharsets.UTF_8;
 
 
@@ -104,7 +104,6 @@ class UrlEncoded  : MultiMap!string {
             charset = ENCODING;
 
         StringBuilder result = new StringBuilder(128);
-
         bool delim = false;
         foreach(string key, List!string list; map)
         {
@@ -236,7 +235,7 @@ class UrlEncoded  : MultiMap!string {
      */
     static string decodeString(string encoded, int offset, int length, string charset = ENCODING) {
         StringBuffer buffer = null;
-
+        warningf("decodeString ...............");
         for (int i = 0; i < length; i++) {
             char c = encoded.charAt(offset + i);
             if (c < 0 || c > 0xff) {
@@ -265,7 +264,7 @@ class UrlEncoded  : MultiMap!string {
                         if (i + 2 < length) {
                             int o = offset + i + 1;
                             i += 3;
-                            ba[n] = cast(byte) TypeUtils.parseInt(encoded, o, 2, 16);
+                           // ba[n] = cast(byte) TypeUtils.parseInt(encoded, o, 2, 16);
                             n++;
                         } else {
                             ba[n++] = cast(byte) '?';
@@ -323,7 +322,7 @@ class UrlEncoded  : MultiMap!string {
             charset = ENCODING;
         byte[] bytes = cast(byte[])str;
         // bytes = string.getBytes(charset);
-
+        warningf("encodeString ...............");
         int len = cast(int)bytes.length;
         byte[] encoded = new byte[bytes.length * 3];
         int n = 0;