Browse Source

Remove D/hunt (#7198)

Nate 3 years ago
parent
commit
9e07c1ba5b
32 changed files with 0 additions and 7638 deletions
  1. 0 29
      frameworks/D/hunt/README.md
  2. 0 25
      frameworks/D/hunt/benchmark_config.json
  3. 0 13
      frameworks/D/hunt/build.sh
  4. 0 14
      frameworks/D/hunt/config.toml
  5. 0 60
      frameworks/D/hunt/dub.json
  6. 0 47
      frameworks/D/hunt/http/app.d
  7. 0 252
      frameworks/D/hunt/http/http/DemoProcessor.d
  8. 0 1168
      frameworks/D/hunt/http/http/HttpURI.d
  9. 0 283
      frameworks/D/hunt/http/http/Parser.d
  10. 0 273
      frameworks/D/hunt/http/http/Processor.d
  11. 0 127
      frameworks/D/hunt/http/http/Server.d
  12. 0 362
      frameworks/D/hunt/http/http/UrlEncoded.d
  13. 0 19
      frameworks/D/hunt/hunt-dmd.dockerfile
  14. 0 18
      frameworks/D/hunt/hunt-http.dockerfile
  15. 0 23
      frameworks/D/hunt/hunt.dockerfile
  16. 0 267
      frameworks/D/hunt/mmap/DemoProcessor.d
  17. 0 47
      frameworks/D/hunt/mmap/app.d
  18. 0 84
      frameworks/D/hunt/mmap/http/Common.d
  19. 0 1166
      frameworks/D/hunt/mmap/http/HttpURI.d
  20. 0 202
      frameworks/D/hunt/mmap/http/Parser.d
  21. 0 137
      frameworks/D/hunt/mmap/http/Processor.d
  22. 0 122
      frameworks/D/hunt/mmap/http/Server.d
  23. 0 361
      frameworks/D/hunt/mmap/http/UrlEncoded.d
  24. 0 50
      frameworks/D/hunt/patches/Makefile
  25. 0 47
      frameworks/D/hunt/pico/app.d
  26. 0 85
      frameworks/D/hunt/pico/http/Common.d
  27. 0 253
      frameworks/D/hunt/pico/http/DemoProcessor.d
  28. 0 1167
      frameworks/D/hunt/pico/http/HttpURI.d
  29. 0 203
      frameworks/D/hunt/pico/http/Parser.d
  30. 0 239
      frameworks/D/hunt/pico/http/Processor.d
  31. 0 133
      frameworks/D/hunt/pico/http/Server.d
  32. 0 362
      frameworks/D/hunt/pico/http/UrlEncoded.d

+ 0 - 29
frameworks/D/hunt/README.md

@@ -1,29 +0,0 @@
-# Hunt Benchmarking Test
-
-This is the Hunt portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
-
-
-## Requirements
-* Dlang > 2.077
-
-## Test URLs
-    
-### PlanText Test
-
-    http://localhost:8080/plaintext
-
-### JSON Encoding Test
-
-    http://localhost:8080/json
-    
-### Single database query
-
-    http://localhost:8080/db
-    
-### Multiple database queries
-
-    http://localhost:8080//queries?queries=10
-    
-### Database updates
-
-    http://localhost:8080/updates?queries=10

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

@@ -1,25 +0,0 @@
-{
-  "framework": "hunt",
-  "tests": [
-    {
-      "default": {
-        "json_url": "/json",
-        "plaintext_url": "/plaintext",
-        "port": 8080,
-        "approach": "Realistic",
-        "classification": "Platform",
-        "framework": "Hunt",
-        "language": "D",
-        "flavor": "DLang2",
-        "orm": "Raw",
-        "platform": "None",
-        "webserver": "None",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "hunt",
-        "notes": "",
-        "versus": "Hunt"
-      }
-    }
-  ]
-}

+ 0 - 13
frameworks/D/hunt/build.sh

@@ -1,13 +0,0 @@
-#!/bin/bash
-
-rm -rf picohttpparser
-git clone https://github.com/h2o/picohttpparser.git
-cp patches/Makefile picohttpparser
-cd picohttpparser
-make package
-
-
-rm -rf http-parser
-git clone https://github.com/nodejs/http-parser.git
-cd http-parser
-make package

+ 0 - 14
frameworks/D/hunt/config.toml

@@ -1,14 +0,0 @@
-[framework]
-name = "hunt"
-
-[main]
-urls.plaintext = "/plaintext"
-urls.json = "/json"
-approach = "Realistic"
-classification = "Platform"
-database_os = "Linux"
-os = "Linux"
-orm = "Raw"
-platform = "None"
-webserver = "None"
-versus = "Hunt"

+ 0 - 60
frameworks/D/hunt/dub.json

@@ -1,60 +0,0 @@
-{
-	"name": "hunt-minihttp",
-	"targetType": "executable",
-	"description": "A mini http server powered by Hunt.",
-	"copyright": "Copyright (C) 2017-2020, HuntLabs",
-	"homepage": "https://www.huntlabs.net",
-	"license": "Apache-2.0",
-	"dependencies": {
-		"hunt": "~>1.5.0-beta.3",
-		"std_data_json": "~>0.18.2"
-	},
-	"versions": [
-		"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"
-  }
-
-}

+ 0 - 47
frameworks/D/hunt/http/app.d

@@ -1,47 +0,0 @@
-/*
- * Collie - An asynchronous event-driven network framework using Dlang development
- *
- * Copyright (C) 2015-2018  Shanghai Putao Technology Co., Ltd
- *
- * Developer: Putao's Dlang team
- *
- * Licensed under the Apache-2.0 License.
- *
- */
-import std.getopt;
-import std.stdio;
-
-//import hunt.database;
-import hunt.io;
-import hunt.system.Memory : totalCPUs;
-import http.Processor;
-import http.Server;
-import http.DemoProcessor;
-
-void main(string[] args) {
-	ushort port = 8080;
-	GetoptResult o = getopt(args, "port|p", "Port (default 8080)", &port);
-	if (o.helpWanted) {
-		defaultGetoptPrinter("A simple http server powered by Hunt!", o.options);
-		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);
-	//}
-
-	AbstractTcpServer httpServer = new HttpServer!(DemoProcessor)("0.0.0.0", port, totalCPUs);
-	writefln("listening on http://%s", httpServer.bindingAddress.toString());
-	httpServer.start();
-}

+ 0 - 252
frameworks/D/hunt/http/http/DemoProcessor.d

@@ -1,252 +0,0 @@
-module http.DemoProcessor;
-
-
-
-// import stdx.data.json;
-import std.json;
-
-//import hunt.database;
-import hunt.io;
-import http.Processor;
-import http.HttpURI;
-import http.UrlEncoded;
-import hunt.logging.ConsoleLogger : trace, warning, tracef;
-
-import std.algorithm;
-import std.array;
-import std.exception;
-import std.random;
-import std.string;
-
-version (POSTGRESQL) {
-    __gshared Database dbConnection;
-}
-
-enum HttpHeader textHeader = HttpHeader("Content-Type", "text/plain; charset=UTF-8");
-enum HttpHeader htmlHeader = HttpHeader("Content-Type", "text/html; charset=UTF-8");
-enum HttpHeader jsonHeader = HttpHeader("Content-Type", "application/json; charset=UTF-8");
-
-
-enum plaintextLength = "/plaintext".length;
-enum jsonLength = "/json".length;
-enum dbLength = "/db".length;
-enum fortunesLength = "/fortunes".length;
-
-class DemoProcessor : HttpProcessor {
-    version (POSTGRESQL) HttpURI uri;
-
-    this(TcpStream client) {
-        version (POSTGRESQL) uri = new HttpURI();
-        super(client);
-    }
-
-    override void onComplete(HttpRequest req) {
-        string path = req.uri;
-        if(path.length == plaintextLength) { // plaintext
-            respondWith("Hello, World!", 200, textHeader);
-        } else if(path.length == jsonLength) { // json
-            JSONValue js = JSONValue(["message" : JSONValue("Hello, World!")]);
-            respondWith(js.toJSON(), 200, jsonHeader);
-        } else {
-
-        version (POSTGRESQL) {
-            if(path.length == dbLength) {
-                respondSingleQuery();
-            } else if(path.length == fortunesLength) {
-                respondFortunes();
-            } else {
-                handleDbUpdate(path);
-            }
-
-        } 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) {
-        private void handleDbUpdate(string url) {
-            uri.parse(url);
-
-            switch(uri.getPath()) {
-            case "/queries":
-                UrlEncoded queriesMap = new UrlEncoded();
-                uri.decodeQueryTo(queriesMap);
-                int number = 1;
-                debug {
-                    trace(queriesMap.toString());
-                    if (!queriesMap.containsKey("queries")) {
-                        respondWith404();
-                        return;
-                    }
-
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                            warning(ex.msg);
-                        }
-                    }
-                } else {
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                        }
-                    }
-                }
-
-                respondMultipleQuery(number);
-                break;
-
-
-            case "/updates":
-                UrlEncoded queriesMap = new UrlEncoded();
-                uri.decodeQueryTo(queriesMap);
-                int number = 1;
-                debug {
-                    if (!queriesMap.containsKey("queries")) {
-                        respondWith404();
-                        return;
-                    }
-
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                            warning(ex.msg);
-                        }
-                    }
-                } else {
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                        }
-                    }
-                }
-                respondUpdates(number);
-                break;
-
-            default:
-                respondWith404();
-                break;
-            }
-        }
-
-
-        private void respondSingleQuery() {
-            int id = uniform(1, 10001);
-            string query = "SELECT id, 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 id, 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);
-        }
-
-        static string randerFortunes(FortuneModel[] data) {
-            Appender!string sb;
-            sb.put(`<!DOCTYPE html>
-<html>
-	<head>
-		<title>Fortunes</title>
-	</head>
-	<body>
-		<table>
-			<tr>
-				<th>id</th><th>message</th>
-			</tr>
-`);
-
-            foreach (FortuneModel f; data) {
-                string message = replace(f.message, ">", "&gt;");
-                message = replace(message, "<", "&lt;");
-                message = replace(message, "\"", "&quot;");
-                sb.put(format("			<tr>\n				<td>%d</td><td>%s</td>\n			</tr>\n", f.id, message));
-            }
-
-            sb.put("		</table>\n	</body>\n</html>");
-
-            return sb.data;
-        }
-
-        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 id, 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);
-        }
-    }
-}
-
-struct FortuneModel {
-    int id;
-    string message;
-}

+ 0 - 1168
frameworks/D/hunt/http/http/HttpURI.d

@@ -1,1168 +0,0 @@
-module http.HttpURI;
-
-
-
-import hunt.collection.MultiMap;
-
-import hunt.Exceptions;
-import hunt.text.Charset;
-import hunt.text.Common;
-import hunt.text.StringBuilder;
-import hunt.util.TypeUtils;
-import http.UrlEncoded;
-
-import std.array;
-import std.conv;
-import std.string;
-
-import hunt.logging;
-
-
-/**
- * Http URI. Parse a HTTP URI from a string or byte array. Given a URI
- * <code>http://user@host:port/path/info;param?query#fragment</code> this class
- * will split it into the following undecoded optional elements:
- * <ul>
- * <li>{@link #getScheme()} - http:</li>
- * <li>{@link #getAuthority()} - //name@host:port</li>
- * <li>{@link #getHost()} - host</li>
- * <li>{@link #getPort()} - port</li>
- * <li>{@link #getPath()} - /path/info</li>
- * <li>{@link #getParam()} - param</li>
- * <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
- * <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
- */
-class HttpURI {
-	private enum State {
-		START, HOST_OR_PATH, SCHEME_OR_PATH, HOST, IPV6, PORT, PATH, PARAM, QUERY, FRAGMENT, ASTERISK
-	}
-
-	private string _scheme;
-	private string _user;
-	private string _host;
-	private int _port;
-	private string _path;
-	private string _param;
-	private string _query;
-	private string _fragment;
-
-	string _uri;
-	string _decodedPath;
-
-	/**
-	 * Construct a normalized URI. Port is not set if it is the default port.
-	 *
-	 * @param scheme
-	 *            the URI scheme
-	 * @param host
-	 *            the URI hose
-	 * @param port
-	 *            the URI port
-	 * @param path
-	 *            the URI path
-	 * @param param
-	 *            the URI param
-	 * @param query
-	 *            the URI query
-	 * @param fragment
-	 *            the URI fragment
-	 * @return the normalized URI
-	 */
-	static HttpURI createHttpURI(string scheme, string host, int port, string path, string param, string query,
-			string fragment) {
-		if (port == 80 && (scheme == "http"))
-			port = 0;
-		if (port == 443 && (scheme == "https"))
-			port = 0;
-		return new HttpURI(scheme, host, port, path, param, query, fragment);
-	}
-
-	this() {
-	}
-
-	this(string scheme, string host, int port, string path, string param, string query, string fragment) {
-		_scheme = scheme;
-		_host = host;
-		_port = port;
-		_path = path;
-		_param = param;
-		_query = query;
-		_fragment = fragment;
-	}
-
-	this(HttpURI uri) {
-		this(uri._scheme, uri._host, uri._port, uri._path, uri._param, uri._query, uri._fragment);
-		_uri = uri._uri;
-	}
-
-	this(string uri) {
-		_port = -1;
-		parse(State.START, uri);
-	}
-
-	// this(URI uri) {
-	// 	_uri = null;
-
-	// 	_scheme = uri.getScheme();
-	// 	_host = uri.getHost();
-	// 	if (_host == null && uri.getRawSchemeSpecificPart().startsWith("//"))
-	// 		_host = "";
-	// 	_port = uri.getPort();
-	// 	_user = uri.getUserInfo();
-	// 	_path = uri.getRawPath();
-
-	// 	_decodedPath = uri.getPath();
-	// 	if (_decodedPath != null) {
-	// 		int p = _decodedPath.lastIndexOf(';');
-	// 		if (p >= 0)
-	// 			_param = _decodedPath.substring(p + 1);
-	// 	}
-	// 	_query = uri.getRawQuery();
-	// 	_fragment = uri.getFragment();
-
-	// 	_decodedPath = null;
-	// }
-
-	this(string scheme, string host, int port, string pathQuery) {
-		_uri = null;
-
-		_scheme = scheme;
-		_host = host;
-		_port = port;
-
-		parse(State.PATH, pathQuery);
-
-	}
-
-	void parse(string uri) {
-		clear();
-		_uri = uri;
-		parse(State.START, uri);
-	}
-
-	/**
-	 * Parse according to https://tools.ietf.org/html/rfc7230#section-5.3
-	 *
-	 * @param method
-	 *            the request method
-	 * @param uri
-	 *            the request uri
-	 */
-	void parseRequestTarget(string method, string uri) {
-		clear();
-		_uri = uri;
-
-		if (method == "CONNECT")
-			_path = uri;
-		else
-			parse(uri.startsWith("/") ? State.PATH : State.START, uri);
-	}
-
-	// deprecated("")
-	// void parseConnect(string uri) {
-	// 	clear();
-	// 	_uri = uri;
-	// 	_path = uri;
-	// }
-
-	void parse(string uri, int offset, int length) {
-		clear();
-		int end = offset + length;
-		_uri = uri.substring(offset, end);
-		parse(State.START, uri);
-	}
-
-	private void parse(State state, string uri) {
-		bool encoded = false;
-		int end = cast(int)uri.length;
-		int mark = 0;
-		int path_mark = 0;
-		char last = '/';
-		for (int i = 0; i < end; i++) {
-			char c = uri[i];
-
-			final switch (state) {
-			case State.START: {
-				switch (c) {
-				case '/':
-					mark = i;
-					state = State.HOST_OR_PATH;
-					break;
-				case ';':
-					mark = i + 1;
-					state = State.PARAM;
-					break;
-				case '?':
-					// assume empty path (if seen at start)
-					_path = "";
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-				case '#':
-					mark = i + 1;
-					state = State.FRAGMENT;
-					break;
-				case '*':
-					_path = "*";
-					state = State.ASTERISK;
-					break;
-
-				case '.':
-					path_mark = i;
-					state = State.PATH;
-					encoded = true;
-					break;
-
-				default:
-					mark = i;
-					if (_scheme == null)
-						state = State.SCHEME_OR_PATH;
-					else {
-						path_mark = i;
-						state = State.PATH;
-					}
-					break;
-				}
-
-				continue;
-			}
-
-			case State.SCHEME_OR_PATH: {
-				switch (c) {
-				case ':':
-					// must have been a scheme
-					_scheme = uri.substring(mark, i);
-					// Start again with scheme set
-					state = State.START;
-					break;
-
-				case '/':
-					// must have been in a path and still are
-					state = State.PATH;
-					break;
-
-				case ';':
-					// must have been in a path
-					mark = i + 1;
-					state = State.PARAM;
-					break;
-
-				case '?':
-					// must have been in a path
-					_path = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-
-				case '%':
-					// must have be in an encoded path
-					encoded = true;
-					state = State.PATH;
-					break;
-
-				case '#':
-					// must have been in a path
-					_path = uri.substring(mark, i);
-					state = State.FRAGMENT;
-					break;
-
-				default:
-					break;
-				}
-				continue;
-			}
-
-			case State.HOST_OR_PATH: {
-				switch (c) {
-				case '/':
-					_host = "";
-					mark = i + 1;
-					state = State.HOST;
-					break;
-
-				case '@':
-				case ';':
-				case '?':
-				case '#':
-					// was a path, look again
-					i--;
-					path_mark = mark;
-					state = State.PATH;
-					break;
-
-				case '.':
-					// it is a path
-					encoded = true;
-					path_mark = mark;
-					state = State.PATH;
-					break;
-
-				default:
-					// it is a path
-					path_mark = mark;
-					state = State.PATH;
-				}
-				continue;
-			}
-
-			case State.HOST: {
-				switch (c) {
-				case '/':
-					_host = uri.substring(mark, i);
-					path_mark = mark = i;
-					state = State.PATH;
-					break;
-				case ':':
-					if (i > mark)
-						_host = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.PORT;
-					break;
-				case '@':
-					if (_user != null)
-						throw new IllegalArgumentException("Bad authority");
-					_user = uri.substring(mark, i);
-					mark = i + 1;
-					break;
-
-				case '[':
-					state = State.IPV6;
-					break;
-
-				default:
-					break;
-				}
-				break;
-			}
-
-			case State.IPV6: {
-				switch (c) {
-				case '/':
-					throw new IllegalArgumentException("No closing ']' for ipv6 in " ~ uri);
-				case ']':
-					c = uri.charAt(++i);
-					_host = uri.substring(mark, i);
-					if (c == ':') {
-						mark = i + 1;
-						state = State.PORT;
-					} else {
-						path_mark = mark = i;
-						state = State.PATH;
-					}
-					break;
-
-				default:
-					break;
-				}
-
-				break;
-			}
-
-			case State.PORT: {
-				if (c == '@') {
-					if (_user != null)
-						throw new IllegalArgumentException("Bad authority");
-					// It wasn't a port, but a password!
-					_user = _host ~ ":" ~ uri.substring(mark, i);
-					mark = i + 1;
-					state = State.HOST;
-				} else if (c == '/') {
-					// _port = TypeUtils.parseInt(uri, mark, i - mark, 10);
-					_port = to!int(uri[mark .. i], 10);
-					path_mark = mark = i;
-					state = State.PATH;
-				}
-				break;
-			}
-
-			case State.PATH: {
-				switch (c) {
-				case ';':
-					mark = i + 1;
-					state = State.PARAM;
-					break;
-				case '?':
-					_path = uri.substring(path_mark, i);
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-				case '#':
-					_path = uri.substring(path_mark, i);
-					mark = i + 1;
-					state = State.FRAGMENT;
-					break;
-				case '%':
-					encoded = true;
-					break;
-				case '.':
-					if ('/' == last)
-						encoded = true;
-					break;
-
-				default:
-					break;
-				}
-				break;
-			}
-
-			case State.PARAM: {
-				switch (c) {
-				case '?':
-					_path = uri.substring(path_mark, i);
-					_param = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-				case '#':
-					_path = uri.substring(path_mark, i);
-					_param = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.FRAGMENT;
-					break;
-				case '/':
-					encoded = true;
-					// ignore internal params
-					state = State.PATH;
-					break;
-				case ';':
-					// multiple parameters
-					mark = i + 1;
-					break;
-
-				default:
-					break;
-				}
-				break;
-			}
-
-			case State.QUERY: {
-				if (c == '#') {
-					_query = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.FRAGMENT;
-				}
-				break;
-			}
-
-			case State.ASTERISK: {
-				throw new IllegalArgumentException("Bad character '*'");
-			}
-
-			case State.FRAGMENT: {
-				_fragment = uri.substring(mark, end);
-				i = end;
-				break;
-			}
-			}
-			last = c;
-		}
-
-		final switch (state) {
-		case State.START:
-			break;
-		case State.SCHEME_OR_PATH:
-			_path = uri.substring(mark, end);
-			break;
-
-		case State.HOST_OR_PATH:
-			_path = uri.substring(mark, end);
-			break;
-
-		case State.HOST:
-			if (end > mark)
-				_host = uri.substring(mark, end);
-			break;
-
-		case State.IPV6:
-			throw new IllegalArgumentException("No closing ']' for ipv6 in " ~ uri);
-
-		case State.PORT:
-			// _port = TypeUtils.parseInt(uri, mark, end - mark, 10);
-			_port = to!int(uri[mark .. end], 10);
-			break;
-
-		case State.ASTERISK:
-			break;
-
-		case State.FRAGMENT:
-			_fragment = uri.substring(mark, end);
-			break;
-
-		case State.PARAM:
-			_path = uri.substring(path_mark, end);
-			_param = uri.substring(mark, end);
-			break;
-
-		case State.PATH:
-			_path = uri.substring(path_mark, end);
-			break;
-
-		case State.QUERY:
-			_query = uri.substring(mark, end);
-			break;
-		}
-
-		if (!encoded) {
-			if (_param == null)
-				_decodedPath = _path;
-			else
-				_decodedPath = _path[0 .. _path.length - _param.length - 1];
-		}
-	}
-
-	string getScheme() {
-		return _scheme;
-	}
-
-	string getHost() {
-		// Return null for empty host to retain compatibility with java.net.URI
-		if (_host != null && _host.length == 0)
-			return null;
-		return _host;
-	}
-
-	int getPort() {
-		return _port;
-	}
-
-	/**
-	 * The parsed Path.
-	 *
-	 * @return the path as parsed on valid URI. null for invalid URI.
-	 */
-	string getPath() {
-		return _path;
-	}
-
-	string getDecodedPath() {
-		if (_decodedPath.empty && !_path.empty)
-			_decodedPath = URIUtils.canonicalPath(URIUtils.decodePath(_path));
-		return _decodedPath;
-	}
-
-	string getParam() {
-		return _param;
-	}
-
-	string getQuery() {
-		return _query;
-	}
-
-	bool hasQuery() {
-		return _query != null && _query.length > 0;
-	}
-
-	string getFragment() {
-		return _fragment;
-	}
-
-	void decodeQueryTo(MultiMap!string parameters, string encoding = StandardCharsets.UTF_8) {
-		if (_query == _fragment)
-			return;
-
-		UrlEncoded.decodeTo(_query, parameters, encoding);
-	}
-
-	void clear() {
-		_uri = null;
-
-		_scheme = null;
-		_host = null;
-		_port = -1;
-		_path = null;
-		_param = null;
-		_query = null;
-		_fragment = null;
-
-		_decodedPath = null;
-	}
-
-	bool isAbsolute() {
-		return _scheme != null && _scheme.length > 0;
-	}
-
-	override
-	string toString() {
-		if (_uri is null) {
-			StringBuilder ot = new StringBuilder();
-
-			if (_scheme != null)
-				ot.append(_scheme).append(':');
-
-			if (_host != null) {
-				ot.append("//");
-				if (_user != null)
-					ot.append(_user).append('@');
-				ot.append(_host);
-			}
-
-			if (_port > 0)
-				ot.append(':').append(_port);
-
-			if (_path != null)
-				ot.append(_path);
-
-			if (_query != null)
-				ot.append('?').append(_query);
-
-			if (_fragment != null)
-				ot.append('#').append(_fragment);
-
-			if (ot.length > 0)
-				_uri = ot.toString();
-			else
-				_uri = "";
-		}
-		return _uri;
-	}
-
-	bool equals(Object o) {
-		if (o is this)
-			return true;
-		if (!(typeid(o) == typeid(HttpURI)))
-			return false;
-		return toString().equals(o.toString());
-	}
-
-	void setScheme(string scheme) {
-		_scheme = scheme;
-		_uri = null;
-	}
-
-	/**
-	 * @param host
-	 *            the host
-	 * @param port
-	 *            the port
-	 */
-	void setAuthority(string host, int port) {
-		_host = host;
-		_port = port;
-		_uri = null;
-	}
-
-	/**
-	 * @param path
-	 *            the path
-	 */
-	void setPath(string path) {
-		_uri = null;
-		_path = path;
-		_decodedPath = null;
-	}
-
-	/**
-	 * @param path
-	 *            the decoded path
-	 */
-	// void setDecodedPath(string path) {
-	// 	_uri = null;
-	// 	_path = URIUtils.encodePath(path);
-	// 	_decodedPath = path;
-	// }
-
-	void setPathQuery(string path) {
-		_uri = null;
-		_path = null;
-		_decodedPath = null;
-		_param = null;
-		_fragment = null;
-		if (path != null)
-			parse(State.PATH, path);
-	}
-
-	void setQuery(string query) {
-		_query = query;
-		_uri = null;
-	}
-
-	// URI toURI() {
-	// 	return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodestring(_query),
-	// 			_fragment);
-	// }
-
-	string getPathQuery() {
-		if (_query == null)
-			return _path;
-		return _path ~ "?" ~ _query;
-	}
-
-	bool hasAuthority() {
-		return _host != null;
-	}
-
-	string getAuthority() {
-		if (_port > 0)
-			return _host ~ ":" ~ to!string(_port);
-		return _host;
-	}
-
-	string getUser() {
-		return _user;
-	}
-
-}
-
-
-/**
- * Parse an authority string into Host and Port
- * <p>Parse a string in the form "host:port", handling IPv4 an IPv6 hosts</p>
- *
- */
-class URIUtils
-{
-	/* ------------------------------------------------------------ */
-    /* Decode a URI path and strip parameters
-     */
-    static string decodePath(string path) {
-        return decodePath(path, 0, cast(int)path.length);
-    }
-
-    /* ------------------------------------------------------------ */
-    /* Decode a URI path and strip parameters of UTF-8 path
-     */
-    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];
-                switch (c) {
-                    case '%':
-                        if (builder is null) {
-                            builder = new StringBuilder(path.length);
-                            builder.append(path, offset, i - offset);
-                        }
-                        if ((i + 2) < end) {
-                            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)));
-                                i += 5;
-                            } else {
-                                //builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
-                                i += 2;
-                            }
-                        } else {
-                            throw new IllegalArgumentException("Bad URI % encoding");
-                        }
-
-                        break;
-
-                    case ';':
-                        if (builder is null) {
-                            builder = new StringBuilder(path.length);
-                            builder.append(path, offset, i - offset);
-                        }
-
-                        while (++i < end) {
-                            if (path[i] == '/') {
-                                builder.append('/');
-                                break;
-                            }
-                        }
-
-                        break;
-
-                    default:
-                        if (builder !is null)
-                            builder.append(c);
-                        break;
-                }
-            }
-
-            if (builder !is null)
-                return builder.toString();
-            if (offset == 0 && length == path.length)
-                return path;
-            return path.substring(offset, end);
-        } catch (Exception e) {
-            // System.err.println(path.substring(offset, offset + length) + " " + e);
-			error(e.toString);
-            return decodeISO88591Path(path, offset, length);
-        }
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /* Decode a URI path and strip parameters of ISO-8859-1 path
-     */
-    private static string decodeISO88591Path(string path, int offset, int length) {
-        StringBuilder builder = null;
-        int end = offset + length;
-        for (int i = offset; i < end; i++) {
-            char c = path[i];
-            switch (c) {
-                case '%':
-                    if (builder is null) {
-                        builder = new StringBuilder(path.length);
-                        builder.append(path, offset, i - offset);
-                    }
-                    if ((i + 2) < end) {
-                        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)));
-                            i += 5;
-                        } else {
-                            //builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
-                            i += 2;
-                        }
-                    } else {
-                        throw new IllegalArgumentException("");
-                    }
-
-                    break;
-
-                case ';':
-                    if (builder is null) {
-                        builder = new StringBuilder(path.length);
-                        builder.append(path, offset, i - offset);
-                    }
-                    while (++i < end) {
-                        if (path[i] == '/') {
-                            builder.append('/');
-                            break;
-                        }
-                    }
-                    break;
-
-
-                default:
-                    if (builder !is null)
-                        builder.append(c);
-                    break;
-            }
-        }
-
-        if (builder !is null)
-            return builder.toString();
-        if (offset == 0 && length == path.length)
-            return path;
-        return path.substring(offset, end);
-    }
-
-	/* ------------------------------------------------------------ */
-
-    /**
-     * Convert a decoded path to a canonical form.
-     * <p>
-     * All instances of "." and ".." are factored out.
-     * </p>
-     * <p>
-     * Null is returned if the path tries to .. above its root.
-     * </p>
-     *
-     * @param path the path to convert, decoded, with path separators '/' and no queries.
-     * @return the canonical path, or null if path traversal above root.
-     */
-    static string canonicalPath(string path) {
-        if (path.empty)
-            return path;
-
-        bool slash = true;
-        int end = cast(int)path.length;
-        int i = 0;
-
-        loop:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '/':
-                    slash = true;
-                    break;
-
-                case '.':
-                    if (slash)
-                        break loop;
-                    slash = false;
-                    break;
-
-                default:
-                    slash = false;
-            }
-
-            i++;
-        }
-
-        if (i == end)
-            return path;
-
-        StringBuilder canonical = new StringBuilder(path.length);
-        canonical.append(path, 0, i);
-
-        int dots = 1;
-        i++;
-        while (i <= end) {
-            char c = i < end ? path[i] : '\0';
-            switch (c) {
-                case '\0':
-                case '/':
-                    switch (dots) {
-                        case 0:
-                            if (c != '\0')
-                                canonical.append(c);
-                            break;
-
-                        case 1:
-                            break;
-
-                        case 2:
-                            if (canonical.length < 2)
-                                return null;
-                            canonical.setLength(canonical.length - 1);
-                            canonical.setLength(canonical.lastIndexOf("/") + 1);
-                            break;
-
-                        default:
-                            while (dots-- > 0)
-                                canonical.append('.');
-                            if (c != '\0')
-                                canonical.append(c);
-                    }
-
-                    slash = true;
-                    dots = 0;
-                    break;
-
-                case '.':
-                    if (dots > 0)
-                        dots++;
-                    else if (slash)
-                        dots = 1;
-                    else
-                        canonical.append('.');
-                    slash = false;
-                    break;
-
-                default:
-                    while (dots-- > 0)
-                        canonical.append('.');
-                    canonical.append(c);
-                    dots = 0;
-                    slash = false;
-            }
-
-            i++;
-        }
-        return canonical.toString();
-    }
-
-
-    /* ------------------------------------------------------------ */
-
-    /**
-     * Convert a path to a cananonical form.
-     * <p>
-     * All instances of "." and ".." are factored out.
-     * </p>
-     * <p>
-     * Null is returned if the path tries to .. above its root.
-     * </p>
-     *
-     * @param path the path to convert (expects URI/URL form, encoded, and with path separators '/')
-     * @return the canonical path, or null if path traversal above root.
-     */
-    static string canonicalEncodedPath(string path) {
-        if (path.empty)
-            return path;
-
-        bool slash = true;
-        int end = cast(int)path.length;
-        int i = 0;
-
-        loop:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '/':
-                    slash = true;
-                    break;
-
-                case '.':
-                    if (slash)
-                        break loop;
-                    slash = false;
-                    break;
-
-                case '?':
-                    return path;
-
-                default:
-                    slash = false;
-            }
-
-            i++;
-        }
-
-        if (i == end)
-            return path;
-
-        StringBuilder canonical = new StringBuilder(path.length);
-        canonical.append(path, 0, i);
-
-        int dots = 1;
-        i++;
-        while (i <= end) {
-            char c = i < end ? path[i] : '\0';
-            switch (c) {
-                case '\0':
-                case '/':
-                case '?':
-                    switch (dots) {
-                        case 0:
-                            if (c != '\0')
-                                canonical.append(c);
-                            break;
-
-                        case 1:
-                            if (c == '?')
-                                canonical.append(c);
-                            break;
-
-                        case 2:
-                            if (canonical.length < 2)
-                                return null;
-                            canonical.setLength(canonical.length - 1);
-                            canonical.setLength(canonical.lastIndexOf("/") + 1);
-                            if (c == '?')
-                                canonical.append(c);
-                            break;
-                        default:
-                            while (dots-- > 0)
-                                canonical.append('.');
-                            if (c != '\0')
-                                canonical.append(c);
-                    }
-
-                    slash = true;
-                    dots = 0;
-                    break;
-
-                case '.':
-                    if (dots > 0)
-                        dots++;
-                    else if (slash)
-                        dots = 1;
-                    else
-                        canonical.append('.');
-                    slash = false;
-                    break;
-
-                default:
-                    while (dots-- > 0)
-                        canonical.append('.');
-                    canonical.append(c);
-                    dots = 0;
-                    slash = false;
-            }
-
-            i++;
-        }
-        return canonical.toString();
-    }
-
-
-
-    /* ------------------------------------------------------------ */
-
-    /**
-     * Convert a path to a compact form.
-     * All instances of "//" and "///" etc. are factored out to single "/"
-     *
-     * @param path the path to compact
-     * @return the compacted path
-     */
-    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;
-
-        loop:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '?':
-                    return path;
-                case '/':
-                    state++;
-                    if (state == 2)
-                        break loop;
-                    break;
-                default:
-                    state = 0;
-            }
-            i++;
-        }
-
-        if (state < 2)
-            return path;
-
-        StringBuilder buf = new StringBuilder(path.length);
-        buf.append(path, 0, i);
-
-        loop2:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '?':
-                    buf.append(path, i, end);
-                    break loop2;
-                case '/':
-                    if (state++ == 0)
-                        buf.append(c);
-                    break;
-                default:
-                    state = 0;
-                    buf.append(c);
-            }
-            i++;
-        }
-
-        return buf.toString();
-    }
-
-    /* ------------------------------------------------------------ */
-
-    /**
-     * @param uri URI
-     * @return True if the uri has a scheme
-     */
-    static bool hasScheme(string uri) {
-        for (int i = 0; i < uri.length; i++) {
-            char c = uri[i];
-            if (c == ':')
-                return true;
-            if (!(c >= 'a' && c <= 'z' ||
-                    c >= 'A' && c <= 'Z' ||
-                    (i > 0 && (c >= '0' && c <= '9' ||
-                            c == '.' ||
-                            c == '+' ||
-                            c == '-'))
-            ))
-                break;
-        }
-        return false;
-    }
-}

+ 0 - 283
frameworks/D/hunt/http/http/Parser.d

@@ -1,283 +0,0 @@
-/// Minimalistic low-overhead wrapper for nodejs/http-parser
-/// Used for benchmarks with simple server
-module http.Parser;
-
-
-
-private:
-
-import std.range.primitives;
-import core.stdc.string;
-
-alias http_data_cb = extern (C) int function(http_parser*, const ubyte* at, size_t length);
-alias http_cb = extern (C) int function(http_parser*);
-
-public enum HttpParserType : uint {
-	request = 0,
-	response = 1,
-	both = 2
-}
-
-public enum HttpMethod : uint {
-	DELETE = 0,
-	GET = 1,
-	HEAD = 2,
-	POST = 3,
-	PUT = 4,
-	/* pathological */
-	CONNECT = 5,
-	OPTIONS = 6,
-	TRACE = 7,
-	/* WebDAV */
-	COPY = 8,
-	LOCK = 9,
-	MKCOL = 10,
-	MOVE = 11,
-	PROPFIND = 12,
-	PROPPATCH = 13,
-	SEARCH = 14,
-	UNLOCK = 15,
-	BIND = 16,
-	REBIND = 17,
-	UNBIND = 18,
-	ACL = 19,
-	/* subversion */
-	REPORT = 20,
-	MKACTIVITY = 21,
-	CHECKOUT = 22,
-	MERGE = 23,
-	/* upnp */
-	MSEARCH = 24,
-	NOTIFY = 25,
-	SUBSCRIBE = 26,
-	UNSUBSCRIBE = 27,
-	/* RFC-5789 */
-	PATCH = 28,
-	PURGE = 29,
-	/* CalDAV */
-	MKCALENDAR = 30,
-	/* RFC-2068, section 19.6.1.2 */
-	LINK = 31,
-	UNLINK = 32,
-	/* icecast */
-	SOURCE = 33,
-}
-
-enum HttpError : uint {
-	OK,
-	/* Callback-related errors */
-	CB_message_begin,
-	CB_url,
-	CB_header_field,
-	CB_header_value,
-	CB_headers_complete,
-	CB_body,
-	CB_message_complete,
-	CB_status,
-	CB_chunk_header,
-	CB_chunk_complete,
-	/* Parsing-related errors */
-	INVALID_EOF_STATE,
-	HEADER_OVERFLOW,
-	CLOSED_CONNECTION,
-	INVALID_VERSION,
-	INVALID_STATUS,
-	INVALID_METHOD,
-	INVALID_URL,
-	INVALID_HOST,
-	INVALID_PORT,
-	INVALID_PATH,
-	INVALID_QUERY_STRING,
-	INVALID_FRAGMENT,
-	LF_EXPECTED,
-	INVALID_HEADER_TOKEN,
-	INVALID_CONTENT_LENGTH,
-	UNEXPECTED_CONTENT_LENGTH,
-	INVALID_CHUNK_SIZE,
-	INVALID_CONSTANT,
-	INVALID_INTERNAL_STATE,
-	STRICT,
-	PAUSED,
-	UNKNOWN,
-}
-
-struct http_parser {
-	/** PRIVATE **/
-	uint state; // bitfield
-	uint nread; /* # bytes read in various scenarios */
-	ulong content_length; /* # bytes in body (0 if no Content-Length header) */
-
-	/** READ-ONLY **/
-	ushort http_major;
-	ushort http_minor;
-	// bitfield
-	uint status_code_method_http_errono_upgrade;
-	/** PUBLIC **/
-	void* data; /* A pointer to get hook to the "connection" or "socket" object */
-}
-
-struct http_parser_settings {
-	http_cb on_message_begin;
-	http_data_cb on_url;
-	http_data_cb on_status;
-	http_data_cb on_header_field;
-	http_data_cb on_header_value;
-	http_cb on_headers_complete;
-	http_data_cb on_body;
-	http_cb on_message_complete;
-	/* When on_chunk_header is called, the current chunk length is stored
-   * in parser->content_length.
-   */
-	http_cb on_chunk_header;
-	http_cb on_chunk_complete;
-}
-
-extern (C) pure @nogc nothrow void http_parser_init(http_parser* parser, HttpParserType type);
-
-extern (C) pure @nogc nothrow int http_should_keep_alive(const http_parser* parser);
-
-/* Return a string description of the given error */
-extern (C) pure @nogc nothrow immutable(char)* http_errno_description(HttpError err);
-
-/* Checks if this is the final chunk of the body. */
-extern (C) pure @nogc nothrow int http_body_is_final(const http_parser* parser);
-
-/* Executes the parser. Returns number of parsed bytes. Sets
-* `parser->http_errno` on error. */
-extern (C) pure @nogc nothrow size_t http_parser_execute(http_parser* parser,
-		const http_parser_settings* settings, const ubyte* data, size_t len);
-
-// extern (C) uint http_parser_flags(const http_parser* parser);
-
-uint http_parser_flags(const http_parser* parser) {
-	// return parser.status_code | (parser.method<<16) | (parser.http_errno << 24) | (parser.upgrade << 31);
-	return parser.status_code_method_http_errono_upgrade;
-}
-
-// =========== Public interface starts here =============
-
-public:
-
-class HttpException : Exception {
-	HttpError error;
-
-	pure @nogc nothrow this(HttpError error, string file = __FILE__,
-			size_t line = __LINE__, Throwable nextInChain = null) {
-		this.error = error;
-		immutable char* str = http_errno_description(error);
-		super(str[0 .. strlen(str)], file, line, nextInChain);
-	}
-}
-
-struct HttpParser(Interceptor) {
-	http_parser parser;
-	http_parser_settings settings;
-	Interceptor interceptor;
-	Throwable failure;
-	uint flags;
-
-	static generateCallback(string cName, string dName) {
-		import std.format;
-
-		return format(`
-			static if(__traits(hasMember, interceptor, "%2$s"))
-			{
-				extern(C) static int %1$s(http_parser* p) {
-					auto parser = cast(HttpParser*)p;
-					try {
-						parser.flags = http_parser_flags(p);
-						return parser.interceptor.%2$s(parser);
-					}
-					catch (Throwable t) {
-						parser.failure = t;
-						return 1;
-					}
-				}
-				settings.%1$s = &%1$s;
-			}
-		`, cName, dName);
-	}
-
-	static generateCallbackWithData(string cName, string dName) {
-		import std.format;
-
-		return format(`
-			static if(__traits(hasMember, interceptor, "%2$s"))
-			{
-				extern(C) static int %1$s(http_parser* p, const ubyte* at, size_t size) {
-					auto parser = cast(HttpParser*)p;
-					try {
-						parser.flags = http_parser_flags(p);
-						return parser.interceptor.%2$s(parser, at[0..size]);
-					}
-					catch (Throwable t) {
-						parser.failure = t;
-						return 1;
-					}
-				}
-				settings.%1$s = &%1$s;
-			}
-		`, cName, dName);
-	}
-
-	@property HttpError errorCode() pure @safe nothrow {
-		return cast(HttpError)((flags >> 24) & 0x7f);
-	}
-
-public:
-	alias interceptor this;
-
-	@property uint status() pure @safe nothrow {
-		return flags & 0xffff;
-	}
-
-	@property HttpMethod method() pure @safe nothrow {
-		return cast(HttpMethod)((flags >> 16) & 0xFF);
-	}
-
-	this(Interceptor interceptor, HttpParserType type) {
-		this.interceptor = interceptor;
-		http_parser_init(&parser, type);
-		mixin(generateCallback("on_message_begin", "onMessageBegin"));
-		mixin(generateCallbackWithData("on_url", "onUrl"));
-		mixin(generateCallbackWithData("on_status", "onStatus"));
-		mixin(generateCallbackWithData("on_body", "onBody"));
-		mixin(generateCallbackWithData("on_header_field", "onHeaderField"));
-		mixin(generateCallbackWithData("on_header_value", "onHeaderValue"));
-		mixin(generateCallback("on_headers_complete", "onHeadersComplete"));
-		mixin(generateCallback("on_message_complete", "onMessageComplete"));
-	}
-
-	@property bool shouldKeepAlive() pure nothrow {
-		return http_should_keep_alive(&parser) == 1;
-	}
-
-	@property ushort httpMajor() @safe pure nothrow {
-		return parser.http_major;
-	}
-
-	@property ushort httpMinor() @safe pure nothrow {
-		return parser.http_minor;
-	}
-
-	size_t execute(const(ubyte)[] chunk) {
-		size_t size = http_parser_execute(&parser, &settings, chunk.ptr, chunk.length);
-		flags = http_parser_flags(&parser);
-		if (errorCode) {
-			auto f = failure;
-			failure = null;
-			if (f is null)
-				f = new HttpException(errorCode);
-			throw f;
-		}
-		return size;
-	}
-
-	size_t execute(const(char)[] str) {
-		return execute(cast(const(ubyte)[]) str);
-	}
-}
-
-auto httpParser(Interceptor)(Interceptor interceptor, HttpParserType type) {
-	return HttpParser!Interceptor(interceptor, type);
-}

+ 0 - 273
frameworks/D/hunt/http/http/Processor.d

@@ -1,273 +0,0 @@
-/// An example "HTTP server" with poor usability but sensible performance
-///
-module http.Processor;
-
-
-
-import std.array, std.exception, std.format, std.algorithm.mutation, std.socket;
-import core.stdc.stdlib;
-import core.thread, core.atomic;
-import http.Parser;
-
-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;
-}
-
-struct HttpRequest {
-	HttpHeader[] headers;
-	HttpMethod method;
-	string uri;
-}
-
-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 {
-		url,
-		field,
-		value,
-		done
-	}
-
-	Appender!(char[]) outBuf;
-	HttpHeader[] headers; // buffer for headers
-	size_t header; // current header
-	string url; // url
-	alias Parser = HttpParser!HttpProcessor;
-	Parser parser;
-	ScratchPad pad;
-	HttpRequest request;
-	State state;
-	bool serving;
-  string resData;
-  long index1;
-  long index2;
-  long length1;
-  long length2;
-  void * keepAliveValue;
-  void * nokeepAliveValue;
-
-public:
-	TcpStream client;
-
-	this(TcpStream sock) {
-		serving = true;
-		client = sock;
-		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.received((ByteBuffer buffer) {
-			version(NO_HTTPPARSER) {
-				client.write(cast(ubyte[])ResponseData);
-			} else {
-				parser.execute(cast(ubyte[]) buffer.getRemaining());
-			}
-
-		})
-		.onClosed(() {
-			 //notifyClientClosed();
-		})
-		.onError((string msg) {
-			debug warning("Error: ", msg);
-		})
-		.start();
-	}
-
-	protected void notifyClientClosed() {
-		debug tracef("The connection[%s] is closed", client.remoteAddress());
-	}
-
-	void respondWith(string _body, uint status, HttpHeader[] 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(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) {
-	}
-
-	void onChunk(HttpRequest req, const(ubyte)[] chunk) {
-	}
-
-	void onComplete(HttpRequest req);
-
-	final int onMessageBegin(Parser* parser) {
-		outBuf.clear();
-		header = 0;
-		pad.reset();
-		state = State.url;
-		return 0;
-	}
-
-	final int onUrl(Parser* parser, const(ubyte)[] chunk) {
-		pad.put(chunk);
-		return 0;
-	}
-
-	final int onBody(Parser* parser, const(ubyte)[] chunk) {
-		onChunk(request, chunk);
-		return 0;
-	}
-
-	final int onHeaderField(Parser* parser, const(ubyte)[] chunk) {
-		final switch (state) {
-		case State.url:
-			url = pad.sliceStr;
-			break;
-		case State.value:
-			headers[header].value = pad.sliceStr;
-			header += 1;
-			if (headers.length <= header)
-				headers.length += 1;
-			break;
-		case State.field:
-		case State.done:
-			break;
-		}
-		state = State.field;
-		pad.put(chunk);
-		return 0;
-	}
-
-	final int onHeaderValue(Parser* parser, const(ubyte)[] chunk) {
-		if (state == State.field) {
-			headers[header].name = pad.sliceStr;
-		}
-		pad.put(chunk);
-		state = State.value;
-		return 0;
-	}
-
-	final int onHeadersComplete(Parser* parser) {
-		headers[header].value = pad.sliceStr;
-		header += 1;
-		request = HttpRequest(headers[0 .. header], parser.method, url);
-		onStart(request);
-		state = State.done;
-		return 0;
-	}
-
-	final int onMessageComplete(Parser* parser) {
-		import std.stdio;
-
-		if (state == State.done) {
-			try {
-				onComplete(request);
-			} catch(Exception ex) {
-				respondWith(ex.msg, 500);
-			}
-		}
-		if (!parser.shouldKeepAlive)
-			serving = false;
-		return 0;
-	}
-
-}
-
-// ==================================== IMPLEMENTATION DETAILS ==============================================
-private:
-
-struct ScratchPad {
-	ubyte* ptr;
-	size_t capacity;
-	size_t last, current;
-
-	this(size_t size) {
-		ptr = cast(ubyte*) malloc(size);
-		capacity = size;
-	}
-
-	void put(const(ubyte)[] slice) {
-		enforce(current + slice.length <= capacity, "HTTP headers too long");
-		ptr[current .. current + slice.length] = slice[];
-		current += slice.length;
-	}
-
-	const(ubyte)[] slice() {
-		auto data = ptr[last .. current];
-		last = current;
-		return data;
-	}
-
-	string sliceStr() {
-		return cast(string) slice;
-	}
-
-	void reset() {
-		current = 0;
-		last = 0;
-	}
-
-	@disable this(this);
-
-	~this() {
-		free(ptr);
-		ptr = null;
-	}
-}

+ 0 - 127
frameworks/D/hunt/http/http/Server.d

@@ -1,127 +0,0 @@
-module http.Server;
-
-
-
-import hunt.event;
-import hunt.io;
-import hunt.logging.ConsoleLogger;
-import hunt.system.Memory : totalCPUs;
-import hunt.util.DateTime;
-
-import std.array;
-import std.conv;
-import std.json;
-import std.socket;
-import std.string;
-import std.stdio;
-
-import http.Parser;
-import http.Processor;
-import std.experimental.allocator;
-
-shared static this() {
-	//DateTimeHelper.startClock();
-}
-
-import hunt.io.channel;
-
-/**
-*/
-abstract class AbstractTcpServer {
-	protected EventLoopGroup _group = null;
-	protected bool _isStarted = false;
-	protected Address _address;
-	protected int _workersCount;
-	TcpStreamOptions _tcpStreamoption;
-
-
-	this(Address address, int thread = (totalCPUs - 1), int workersCount = 0) {
-		this._address = address;
-		_tcpStreamoption = TcpStreamOptions.create();
-		_tcpStreamoption.bufferSize = 1024 * 2;
-		_tcpStreamoption.isKeepalive = false;
-		_group = new EventLoopGroup(cast(uint) thread);
-		this._workersCount = workersCount;
-	}
-
-	@property Address bindingAddress() {
-		return _address;
-	}
-
-	void start() {
-		if (_isStarted)
-			return;
-		_isStarted = true;
-
-		Socket server = new TcpSocket();
-		server.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
-		server.bind(new InternetAddress("0.0.0.0", 8080));
-		server.listen(8192);
-
-		trace("Launching http server");
-		debug {
-			_group.start(_tcpStreamoption.bufferSize);
-		} else {
-			_group.start(100, _tcpStreamoption.bufferSize);
-		}
-
-		if (_workersCount) {
-			defaultPoolThreads = _workersCount;
-			workerPool(); // Initilize worker poll
-		}
-		writefln("worker count: %d", _workersCount);
-		writefln("IO thread: %d", _group.size);
-
-		while (true) {
-			try {
-				version (HUNT_DEBUG)
-					trace("Waiting for server.accept()");
-
-				Socket socket = server.accept();
-				version (HUNT_DEBUG) {
-					infof("new connection from %s, fd=%d",
-							socket.remoteAddress.toString(), socket.handle());
-				}
-				// 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);
-				onConnectionAccepted(stream);
-			} catch (Exception e) {
-				warningf("Failure on accepting %s", e);
-				break;
-			}
-		}
-		_isStarted = false;
-	}
-
-	protected void onConnectionAccepted(TcpStream client);
-
-	void stop() {
-		if (!_isStarted)
-			return;
-		_isStarted = false;
-		_group.stop();
-	}
-}
-
-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);
-	}
-
-	this(Address address, int thread = (totalCPUs - 1)) {
-		super(address, thread);
-	}
-
-	override protected void onConnectionAccepted(TcpStream client) {
-		HttpProcessor httpProcessor = new T(client);
-		httpProcessor.run();
-	}
-
-}

+ 0 - 362
frameworks/D/hunt/http/http/UrlEncoded.d

@@ -1,362 +0,0 @@
-module http.UrlEncoded;
-
-
-
-import hunt.collection.List;
-import hunt.collection.MultiMap;
-import hunt.collection.StringBuffer;
-import hunt.Exceptions;
-import hunt.logging;
-import hunt.text.Charset;
-import hunt.text.Common;
-import hunt.text.StringBuilder;
-import hunt.util.TypeUtils;
-
-import std.conv;
-import std.array;
-
-
-/**
- * Handles coding of MIME "x-www-form-urlencoded".
- * <p>
- * This class handles the encoding and decoding for either the query string of a
- * URL or the _content of a POST HTTP request.
- * </p>
- * <b>Notes</b>
- * <p>
- * The UTF-8 charset is assumed, unless otherwise defined by either passing a
- * parameter or setting the "org.hunt.utils.UrlEncoding.charset" System
- * property.
- * </p>
- * <p>
- * The hashtable either contains string single values, vectors of string or
- * arrays of Strings.
- * </p>
- * <p>
- * This class is only partially synchronised. In particular, simple get
- * operations are not protected from concurrent updates.
- * </p>
- *
- * @see java.net.URLEncoder
- */
-class UrlEncoded  : MultiMap!string {
-
-    enum string ENCODING = StandardCharsets.UTF_8;
-
-
-    this() {
-    }
-
-    this(string query) {
-        decodeTo(query, this, ENCODING);
-    }
-
-    void decode(string query) {
-        decodeTo(query, this, ENCODING);
-    }
-
-    void decode(string query, string charset) {
-        decodeTo(query, this, charset);
-    }
-
-    /**
-     * Encode MultiMap with % encoding for UTF8 sequences.
-     *
-     * @return the MultiMap as a string with % encoding
-     */
-    string encode() {
-        return encode(ENCODING, false);
-    }
-
-    /**
-     * Encode MultiMap with % encoding for arbitrary string sequences.
-     *
-     * @param charset the charset to use for encoding
-     * @return the MultiMap as a string encoded with % encodings
-     */
-    string encode(string charset) {
-        return encode(charset, false);
-    }
-
-    /**
-     * Encode MultiMap with % encoding.
-     *
-     * @param charset            the charset to encode with
-     * @param equalsForNullValue if True, then an '=' is always used, even
-     *                           for parameters without a value. e.g. <code>"blah?a=&amp;b=&amp;c="</code>.
-     * @return the MultiMap as a string encoded with % encodings
-     */
-    string encode(string charset, bool equalsForNullValue) {
-        return encode(this, charset, equalsForNullValue);
-    }
-
-    /**
-     * Encode MultiMap with % encoding.
-     *
-     * @param map                the map to encode
-     * @param charset            the charset to use for encoding (uses default encoding if null)
-     * @param equalsForNullValue if True, then an '=' is always used, even
-     *                           for parameters without a value. e.g. <code>"blah?a=&amp;b=&amp;c="</code>.
-     * @return the MultiMap as a string encoded with % encodings.
-     */
-    static string encode(MultiMap!string map, string charset, bool equalsForNullValue) {
-        if (charset is null)
-            charset = ENCODING;
-
-        StringBuilder result = new StringBuilder(128);
-        bool delim = false;
-        foreach(string key, List!string list; map)
-        {
-            int s = list.size();
-
-            if (delim) {
-                result.append('&');
-            }
-
-            if (s == 0) {
-                result.append(encodeString(key, charset));
-                if (equalsForNullValue)
-                    result.append('=');
-            } else {
-                for (int i = 0; i < s; i++) {
-                    if (i > 0)
-                        result.append('&');
-                    string val = list.get(i);
-                    result.append(encodeString(key, charset));
-
-                    if (val != null) {
-                        if (val.length > 0) {
-                            result.append('=');
-                            result.append(encodeString(val, charset));
-                        } else if (equalsForNullValue)
-                            result.append('=');
-                    } else if (equalsForNullValue)
-                        result.append('=');
-                }
-            }
-            delim = true;
-        }
-        return result.toString();
-    }
-
-    /**
-     * Decoded parameters to Map.
-     *
-     * @param content the string containing the encoded parameters
-     * @param map     the MultiMap to put parsed query parameters into
-     * @param charset the charset to use for decoding
-     */
-    static void decodeTo(string content, MultiMap!string map, string charset = ENCODING) {
-        if (charset.empty)
-            charset = ENCODING;
-
-        synchronized (map) {
-            string key = null;
-            string value = null;
-            int mark = -1;
-            bool encoded = false;
-            for (int i = 0; i < content.length; i++) {
-                char c = content[i];
-                switch (c) {
-                    case '&':
-                        int l = i - mark - 1;
-                        value = l == 0 ? "" :
-                                (encoded ? decodeString(content, mark + 1, l) : content.substring(mark + 1, i));
-                        mark = i;
-                        encoded = false;
-                        if (key != null) {
-                            map.add(key, value);
-                        } else if (value != null && value.length > 0) {
-                            map.add(value, "");
-                        }
-                        key = null;
-                        value = null;
-                        break;
-                    case '=':
-                        if (key != null)
-                            break;
-                        key = encoded ? decodeString(content, mark + 1, i - mark - 1) : content.substring(mark + 1, i);
-                        mark = i;
-                        encoded = false;
-                        break;
-                    case '+':
-                        encoded = true;
-                        break;
-                    case '%':
-                        encoded = true;
-                        break;
-                    default: break;
-                }
-            }
-
-            int contentLen = cast(int)content.length;
-
-            if (key != null) {
-                int l =  contentLen - mark - 1;
-                value = l == 0 ? "" : (encoded ? decodeString(content, mark + 1, l) : content.substring(mark + 1));
-                version(HUNT_DEBUG) tracef("key=%s, value=%s", key, value);
-                map.add(key, value);
-            } else if (mark < contentLen) {
-                version(HUNT_DEBUG) tracef("empty value: content=%s, key=%s", content, key);
-                key = encoded
-                        ? decodeString(content, mark + 1, contentLen - mark - 1, charset)
-                        : content.substring(mark + 1);
-                if (!key.empty) {
-                    map.add(key, "");
-                }
-            } else {
-                warningf("No key found.");
-            }
-        }
-    }
-
-    /**
-     * Decode string with % encoding.
-     * This method makes the assumption that the majority of calls
-     * will need no decoding.
-     *
-     * @param encoded the encoded string to decode
-     * @return the decoded string
-     */
-    static string decodeString(string encoded) {
-        return decodeString(encoded, 0, cast(int)encoded.length);
-    }
-
-    /**
-     * Decode string with % encoding.
-     * This method makes the assumption that the majority of calls
-     * will need no decoding.
-     *
-     * @param encoded the encoded string to decode
-     * @param offset  the offset in the encoded string to decode from
-     * @param length  the length of characters in the encoded string to decode
-     * @param charset the charset to use for decoding
-     * @return the decoded 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) {
-                if (buffer is null) {
-                    buffer = new StringBuffer(length);
-                    buffer.append(encoded, offset, offset + i + 1);
-                } else
-                    buffer.append(c);
-            } else if (c == '+') {
-                if (buffer is null) {
-                    buffer = new StringBuffer(length);
-                    buffer.append(encoded, offset, offset + i);
-                }
-
-                buffer.append(' ');
-            } else if (c == '%') {
-                if (buffer is null) {
-                    buffer = new StringBuffer(length);
-                    buffer.append(encoded, offset, offset + i);
-                }
-
-                byte[] ba = new byte[length];
-                int n = 0;
-                while (c >= 0 && c <= 0xff) {
-                    if (c == '%') {
-                        if (i + 2 < length) {
-                            int o = offset + i + 1;
-                            i += 3;
-                            //ba[n] = cast(byte) TypeUtils.parseInt(encoded, o, 2, 16);
-                            n++;
-                        } else {
-                            ba[n++] = cast(byte) '?';
-                            i = length;
-                        }
-                    } else if (c == '+') {
-                        ba[n++] = cast(byte) ' ';
-                        i++;
-                    } else {
-                        ba[n++] = cast(byte) c;
-                        i++;
-                    }
-
-                    if (i >= length)
-                        break;
-                    c = encoded.charAt(offset + i);
-                }
-
-                i--;
-                buffer.append(cast(string)(ba[0 .. n]));
-
-            } else if (buffer !is null)
-                buffer.append(c);
-        }
-
-        if (buffer is null) {
-            if (offset == 0 && encoded.length == length)
-                return encoded;
-            return encoded.substring(offset, offset + length);
-        }
-
-        return buffer.toString();
-    }
-
-
-    /**
-     * Perform URL encoding.
-     *
-     * @param string the string to encode
-     * @return encoded string.
-     */
-    static string encodeString(string string) {
-        return encodeString(string, ENCODING);
-    }
-
-    /**
-     * Perform URL encoding.
-     *
-     * @param string  the string to encode
-     * @param charset the charset to use for encoding
-     * @return encoded string.
-     */
-    static string encodeString(string str, string charset) {
-        if (charset is null)
-            charset = ENCODING;
-        byte[] bytes = cast(byte[])str;
-        // bytes = string.getBytes(charset);
-
-        int len = cast(int)bytes.length;
-        byte[] encoded = new byte[bytes.length * 3];
-        warningf("encoded");
-        int n = 0;
-        bool noEncode = true;
-
-        for (int i = 0; i < len; i++) {
-            byte b = bytes[i];
-
-            if (b == ' ') {
-                noEncode = false;
-                encoded[n++] = cast(byte) '+';
-            } else if (b >= 'a' && b <= 'z' ||
-                    b >= 'A' && b <= 'Z' ||
-                    b >= '0' && b <= '9') {
-                encoded[n++] = b;
-            } else {
-                noEncode = false;
-                encoded[n++] = cast(byte) '%';
-                byte nibble = cast(byte) ((b & 0xf0) >> 4);
-                if (nibble >= 10)
-                    encoded[n++] = cast(byte) ('A' + nibble - 10);
-                else
-                    encoded[n++] = cast(byte) ('0' + nibble);
-                nibble = cast(byte) (b & 0xf);
-                if (nibble >= 10)
-                    encoded[n++] = cast(byte) ('A' + nibble - 10);
-                else
-                    encoded[n++] = cast(byte) ('0' + nibble);
-            }
-        }
-
-        if (noEncode)
-            return str;
-
-        return cast(string)(encoded[0 .. n]);
-    }
-}

+ 0 - 19
frameworks/D/hunt/hunt-dmd.dockerfile

@@ -1,19 +0,0 @@
-FROM dlangchina/dlang-dmd: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 git clone https://github.com/h2o/picohttpparser.git && \
-    cp -rf patches/Makefile picohttpparser && \
-    cd picohttpparser && \
-    make package && \
-    cd ..
-
-RUN dub upgrade --verbose
-RUN dub build --build=release --arch=x86_64 --compiler=dmd  -c=mmap -f
-
-EXPOSE 8080
-
-CMD ["./hunt-minihttp"]

+ 0 - 18
frameworks/D/hunt/hunt-http.dockerfile

@@ -1,18 +0,0 @@
-FROM dlangchina/dlang-ldc:latest
-
-ADD ./ /hunt
-WORKDIR /hunt
-
-RUN apt-get update -y && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/* && rm -rf /var/cache/apt/*
-
-RUN git clone https://github.com/nodejs/http-parser.git && \
-    cd http-parser && \
-    make package && \
-    cd ..
-
-RUN dub upgrade --verbose
-RUN dub build --build=release --arch=x86_64 --compiler=ldc2 -f
-
-EXPOSE 8080
-
-CMD ["./hunt-minihttp"]

+ 0 - 23
frameworks/D/hunt/hunt.dockerfile

@@ -1,23 +0,0 @@
-FROM dlangchina/dlang-ldc:latest
-
-ADD ./ /hunt
-WORKDIR /hunt
-
-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 && \
-    cd picohttpparser && \
-    make package && \
-    cd ..
-
-RUN dub upgrade --verbose
-RUN dub build --build=release --arch=x86_64 --compiler=ldc2 -c=minihttp -f
-
-EXPOSE 8080
-
-CMD ["./hunt-minihttp"]

+ 0 - 267
frameworks/D/hunt/mmap/DemoProcessor.d

@@ -1,267 +0,0 @@
-module DemoProcessor;
-
-// import stdx.data.json;
-import std.json;
-
-import hunt.database;
-import hunt.io;
-import http.Common;
-import http.Processor;
-import http.HttpURI;
-import http.UrlEncoded;
-import hunt.logging.ConsoleLogger : trace, warning, tracef;
-
-import std.algorithm;
-import std.array;
-import std.exception;
-import std.random;
-import std.string;
-
-version (POSTGRESQL) {
-    __gshared Database dbConnection;
-}
-
-enum HttpHeader textHeader = HttpHeader("Content-Type", "text/plain; charset=UTF-8");
-enum HttpHeader htmlHeader = HttpHeader("Content-Type", "text/html; charset=UTF-8");
-enum HttpHeader jsonHeader = HttpHeader("Content-Type", "application/json; charset=UTF-8");
-
-
-enum plaintextLength = "/plaintext".length;
-enum jsonLength = "/json".length;
-enum dbLength = "/db".length;
-enum fortunesLength = "/fortunes".length;
-
-class DemoProcessor : HttpProcessor {
-    version (POSTGRESQL) HttpURI uri;
-
-    this(TcpStream client) {
-        version (POSTGRESQL) uri = new HttpURI();
-        super(client);
-    }
-
-    override void onComplete(ref HttpRequest req) {
-        debug {
-            trace(req.uri());
-            trace(req.method());
-            trace(req.headers());
-        }
-
-        string path = req.uri;
-        // auto uri = new HttpURI(req.uri);
-        // uri.parse(req.uri);
-        // if(cmp(path, "/plaintext") == 0) {
-        //     respondWith("Hello, World!", 200, textHeader);
-        // } else if(cmp(path, "/json") == 0) {
-        //     JSONValue js = JSONValue(["message" : JSONValue("Hello, World!")]);
-        //     respondWith(js.toJSON(), 200, jsonHeader);
-        // } else {
-        //     respondWith404();
-        // }
-        if(path.length == plaintextLength) { // plaintext
-            respondWith("Hello, World!", 200, textHeader);
-        } else if(path.length == jsonLength) { // json
-            JSONValue js = JSONValue(["message" : JSONValue("Hello, World!")]);
-            respondWith(js.toJSON(), 200, jsonHeader);
-        } else {
-
-        version (POSTGRESQL) {
-            if(path.length == dbLength) {
-                respondSingleQuery();
-            } else if(path.length == fortunesLength) {
-                respondFortunes();
-            } else {
-                handleDbUpdate(path);
-            }
-
-        } 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) {
-        private void handleDbUpdate(string url) {
-            uri.parse(url);
-
-            switch(uri.getPath()) {
-            case "/queries":
-                UrlEncoded queriesMap = new UrlEncoded();
-                uri.decodeQueryTo(queriesMap);
-                int number = 1;
-                debug {
-                    trace(queriesMap.toString());
-                    if (!queriesMap.containsKey("queries")) {
-                        respondWith404();
-                        return;
-                    }
-
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                            warning(ex.msg);
-                        }
-                    }
-                } else {
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                        }
-                    }
-                }
-
-                respondMultipleQuery(number);
-                break;
-
-
-            case "/updates":
-                UrlEncoded queriesMap = new UrlEncoded();
-                uri.decodeQueryTo(queriesMap);
-                int number = 1;
-                debug {
-                    if (!queriesMap.containsKey("queries")) {
-                        respondWith404();
-                        return;
-                    }
-
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                            warning(ex.msg);
-                        }
-                    }
-                } else {
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                        }
-                    }
-                }
-                respondUpdates(number);
-                break;
-
-            default:
-                respondWith404();
-                break;
-            }
-        }
-
-
-        private void respondSingleQuery() {
-            int id = uniform(1, 10001);
-            string query = "SELECT id, 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 id, 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);
-        }
-
-        static string randerFortunes(FortuneModel[] data) {
-            Appender!string sb;
-            sb.put(`<!DOCTYPE html>
-<html>
-	<head>
-		<title>Fortunes</title>
-	</head>
-	<body>
-		<table>
-			<tr>
-				<th>id</th><th>message</th>
-			</tr>
-`);
-
-            foreach (FortuneModel f; data) {
-                string message = replace(f.message, ">", "&gt;");
-                message = replace(message, "<", "&lt;");
-                message = replace(message, "\"", "&quot;");
-                sb.put(format("			<tr>\n				<td>%d</td><td>%s</td>\n			</tr>\n", f.id, message));
-            }
-
-            sb.put("		</table>\n	</body>\n</html>");
-
-            return sb.data;
-        }
-
-        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 id, 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);
-        }
-    }
-}
-
-struct FortuneModel {
-    int id;
-    string message;
-}

+ 0 - 47
frameworks/D/hunt/mmap/app.d

@@ -1,47 +0,0 @@
-/*
- * Collie - An asynchronous event-driven network framework using Dlang development
- *
- * Copyright (C) 2015-2018  Shanghai Putao Technology Co., Ltd 
- *
- * Developer: Putao's Dlang team
- *
- * Licensed under the Apache-2.0 License.
- *
- */
-import std.getopt;
-import std.stdio;
-
-import hunt.database;
-import hunt.io;
-import hunt.system.Memory : totalCPUs;
-import http.Processor;
-import http.Server;
-import DemoProcessor;
-
-void main(string[] args) {
-	ushort port = 8080;
-	GetoptResult o = getopt(args, "port|p", "Port (default 8080)", &port);
-	if (o.helpWanted) {
-		defaultGetoptPrinter("A simple http server powered by Hunt!", o.options);
-		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);
-	}
-
-	AbstractTcpServer httpServer = new HttpServer!(DemoProcessor)("0.0.0.0", port, totalCPUs);
-	writefln("listening on http://%s", httpServer.bindingAddress.toString());
-	httpServer.start();
-}

+ 0 - 84
frameworks/D/hunt/mmap/http/Common.d

@@ -1,84 +0,0 @@
-module http.Common;
-
-
-public enum HttpParserType : uint {
-	request = 0,
-	response = 1,
-	both = 2
-}
-
-struct HttpHeader {
-	string name, value;
-}
-
-public enum HttpMethod : uint {
-	DELETE = 0,
-	GET = 1,
-	HEAD = 2,
-	POST = 3,
-	PUT = 4,
-	/* pathological */
-	CONNECT = 5,
-	OPTIONS = 6,
-	TRACE = 7,
-	/* WebDAV */
-	COPY = 8,
-	LOCK = 9,
-	MKCOL = 10,
-	MOVE = 11,
-	PROPFIND = 12,
-	PROPPATCH = 13,
-	SEARCH = 14,
-	UNLOCK = 15,
-	BIND = 16,
-	REBIND = 17,
-	UNBIND = 18,
-	ACL = 19,
-	/* subversion */
-	REPORT = 20,
-	MKACTIVITY = 21,
-	CHECKOUT = 22,
-	MERGE = 23,
-	/* upnp */
-	MSEARCH = 24,
-	NOTIFY = 25,
-	SUBSCRIBE = 26,
-	UNSUBSCRIBE = 27,
-	/* RFC-5789 */
-	PATCH = 28,
-	PURGE = 29,
-	/* CalDAV */
-	MKCALENDAR = 30,
-	/* RFC-2068, section 19.6.1.2 */
-	LINK = 31,
-	UNLINK = 32,
-	/* icecast */
-	SOURCE = 33,
-}
-
-enum HttpError : uint {
-	OK,
-	/* Parsing-related errors */
-	INVALID_EOF_STATE,
-	HEADER_OVERFLOW,
-	CLOSED_CONNECTION,
-	INVALID_VERSION,
-	INVALID_STATUS,
-	INVALID_METHOD,
-	INVALID_URL,
-	INVALID_HOST,
-	INVALID_PORT,
-	INVALID_PATH,
-	INVALID_QUERY_STRING,
-	INVALID_FRAGMENT,
-	LF_EXPECTED,
-	INVALID_HEADER_TOKEN,
-	INVALID_CONTENT_LENGTH,
-	UNEXPECTED_CONTENT_LENGTH,
-	INVALID_CHUNK_SIZE,
-	INVALID_CONSTANT,
-	INVALID_INTERNAL_STATE,
-	STRICT,
-	PAUSED,
-	UNKNOWN
-}

+ 0 - 1166
frameworks/D/hunt/mmap/http/HttpURI.d

@@ -1,1166 +0,0 @@
-module http.HttpURI;
-
-import hunt.collection.MultiMap;
-
-import hunt.Exceptions;
-import hunt.text.Charset;
-import hunt.text.Common;
-import hunt.text.StringBuilder;
-import hunt.util.TypeUtils;
-import http.UrlEncoded;
-
-import std.array;
-import std.conv;
-import std.string;
-
-import hunt.logging;
-
-
-/**
- * Http URI. Parse a HTTP URI from a string or byte array. Given a URI
- * <code>http://user@host:port/path/info;param?query#fragment</code> this class
- * will split it into the following undecoded optional elements:
- * <ul>
- * <li>{@link #getScheme()} - http:</li>
- * <li>{@link #getAuthority()} - //name@host:port</li>
- * <li>{@link #getHost()} - host</li>
- * <li>{@link #getPort()} - port</li>
- * <li>{@link #getPath()} - /path/info</li>
- * <li>{@link #getParam()} - param</li>
- * <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 
- * <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
- */
-class HttpURI {
-	private enum State {
-		START, HOST_OR_PATH, SCHEME_OR_PATH, HOST, IPV6, PORT, PATH, PARAM, QUERY, FRAGMENT, ASTERISK
-	}
-
-	private string _scheme;
-	private string _user;
-	private string _host;
-	private int _port;
-	private string _path;
-	private string _param;
-	private string _query;
-	private string _fragment;
-
-	string _uri;
-	string _decodedPath;
-
-	/**
-	 * Construct a normalized URI. Port is not set if it is the default port.
-	 * 
-	 * @param scheme
-	 *            the URI scheme
-	 * @param host
-	 *            the URI hose
-	 * @param port
-	 *            the URI port
-	 * @param path
-	 *            the URI path
-	 * @param param
-	 *            the URI param
-	 * @param query
-	 *            the URI query
-	 * @param fragment
-	 *            the URI fragment
-	 * @return the normalized URI
-	 */
-	static HttpURI createHttpURI(string scheme, string host, int port, string path, string param, string query,
-			string fragment) {
-		if (port == 80 && (scheme == "http"))
-			port = 0;
-		if (port == 443 && (scheme == "https"))
-			port = 0;
-		return new HttpURI(scheme, host, port, path, param, query, fragment);
-	}
-
-	this() {
-	}
-
-	this(string scheme, string host, int port, string path, string param, string query, string fragment) {
-		_scheme = scheme;
-		_host = host;
-		_port = port;
-		_path = path;
-		_param = param;
-		_query = query;
-		_fragment = fragment;
-	}
-
-	this(HttpURI uri) {
-		this(uri._scheme, uri._host, uri._port, uri._path, uri._param, uri._query, uri._fragment);
-		_uri = uri._uri;
-	}
-
-	this(string uri) {
-		_port = -1;
-		parse(State.START, uri);
-	}
-
-	// this(URI uri) {
-	// 	_uri = null;
-
-	// 	_scheme = uri.getScheme();
-	// 	_host = uri.getHost();
-	// 	if (_host == null && uri.getRawSchemeSpecificPart().startsWith("//"))
-	// 		_host = "";
-	// 	_port = uri.getPort();
-	// 	_user = uri.getUserInfo();
-	// 	_path = uri.getRawPath();
-
-	// 	_decodedPath = uri.getPath();
-	// 	if (_decodedPath != null) {
-	// 		int p = _decodedPath.lastIndexOf(';');
-	// 		if (p >= 0)
-	// 			_param = _decodedPath.substring(p + 1);
-	// 	}
-	// 	_query = uri.getRawQuery();
-	// 	_fragment = uri.getFragment();
-
-	// 	_decodedPath = null;
-	// }
-
-	this(string scheme, string host, int port, string pathQuery) {
-		_uri = null;
-
-		_scheme = scheme;
-		_host = host;
-		_port = port;
-
-		parse(State.PATH, pathQuery);
-
-	}
-
-	void parse(string uri) {
-		clear();
-		_uri = uri;
-		parse(State.START, uri);
-	}
-
-	/**
-	 * Parse according to https://tools.ietf.org/html/rfc7230#section-5.3
-	 * 
-	 * @param method
-	 *            the request method
-	 * @param uri
-	 *            the request uri
-	 */
-	void parseRequestTarget(string method, string uri) {
-		clear();
-		_uri = uri;
-
-		if (method == "CONNECT")
-			_path = uri;
-		else
-			parse(uri.startsWith("/") ? State.PATH : State.START, uri);
-	}
-
-	// deprecated("")
-	// void parseConnect(string uri) {
-	// 	clear();
-	// 	_uri = uri;
-	// 	_path = uri;
-	// }
-
-	void parse(string uri, int offset, int length) {
-		clear();
-		int end = offset + length;
-		_uri = uri.substring(offset, end);
-		parse(State.START, uri);
-	}
-
-	private void parse(State state, string uri) {
-		bool encoded = false;
-		int end = cast(int)uri.length;
-		int mark = 0;
-		int path_mark = 0;
-		char last = '/';
-		for (int i = 0; i < end; i++) {
-			char c = uri[i];
-
-			final switch (state) {
-			case State.START: {
-				switch (c) {
-				case '/':
-					mark = i;
-					state = State.HOST_OR_PATH;
-					break;
-				case ';':
-					mark = i + 1;
-					state = State.PARAM;
-					break;
-				case '?':
-					// assume empty path (if seen at start)
-					_path = "";
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-				case '#':
-					mark = i + 1;
-					state = State.FRAGMENT;
-					break;
-				case '*':
-					_path = "*";
-					state = State.ASTERISK;
-					break;
-
-				case '.':
-					path_mark = i;
-					state = State.PATH;
-					encoded = true;
-					break;
-
-				default:
-					mark = i;
-					if (_scheme == null)
-						state = State.SCHEME_OR_PATH;
-					else {
-						path_mark = i;
-						state = State.PATH;
-					}
-					break;
-				}
-
-				continue;
-			}
-
-			case State.SCHEME_OR_PATH: {
-				switch (c) {
-				case ':':
-					// must have been a scheme
-					_scheme = uri.substring(mark, i);
-					// Start again with scheme set
-					state = State.START;
-					break;
-
-				case '/':
-					// must have been in a path and still are
-					state = State.PATH;
-					break;
-
-				case ';':
-					// must have been in a path
-					mark = i + 1;
-					state = State.PARAM;
-					break;
-
-				case '?':
-					// must have been in a path
-					_path = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-
-				case '%':
-					// must have be in an encoded path
-					encoded = true;
-					state = State.PATH;
-					break;
-
-				case '#':
-					// must have been in a path
-					_path = uri.substring(mark, i);
-					state = State.FRAGMENT;
-					break;
-
-				default:
-					break;
-				}
-				continue;
-			}
-
-			case State.HOST_OR_PATH: {
-				switch (c) {
-				case '/':
-					_host = "";
-					mark = i + 1;
-					state = State.HOST;
-					break;
-
-				case '@':
-				case ';':
-				case '?':
-				case '#':
-					// was a path, look again
-					i--;
-					path_mark = mark;
-					state = State.PATH;
-					break;
-
-				case '.':
-					// it is a path
-					encoded = true;
-					path_mark = mark;
-					state = State.PATH;
-					break;
-
-				default:
-					// it is a path
-					path_mark = mark;
-					state = State.PATH;
-				}
-				continue;
-			}
-
-			case State.HOST: {
-				switch (c) {
-				case '/':
-					_host = uri.substring(mark, i);
-					path_mark = mark = i;
-					state = State.PATH;
-					break;
-				case ':':
-					if (i > mark)
-						_host = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.PORT;
-					break;
-				case '@':
-					if (_user != null)
-						throw new IllegalArgumentException("Bad authority");
-					_user = uri.substring(mark, i);
-					mark = i + 1;
-					break;
-
-				case '[':
-					state = State.IPV6;
-					break;
-					
-				default:
-					break;
-				}
-				break;
-			}
-
-			case State.IPV6: {
-				switch (c) {
-				case '/':
-					throw new IllegalArgumentException("No closing ']' for ipv6 in " ~ uri);
-				case ']':
-					c = uri.charAt(++i);
-					_host = uri.substring(mark, i);
-					if (c == ':') {
-						mark = i + 1;
-						state = State.PORT;
-					} else {
-						path_mark = mark = i;
-						state = State.PATH;
-					}
-					break;
-					
-				default:
-					break;
-				}
-
-				break;
-			}
-
-			case State.PORT: {
-				if (c == '@') {
-					if (_user != null)
-						throw new IllegalArgumentException("Bad authority");
-					// It wasn't a port, but a password!
-					_user = _host ~ ":" ~ uri.substring(mark, i);
-					mark = i + 1;
-					state = State.HOST;
-				} else if (c == '/') {
-					// _port = TypeUtils.parseInt(uri, mark, i - mark, 10);
-					_port = to!int(uri[mark .. i], 10);
-					path_mark = mark = i;
-					state = State.PATH;
-				}
-				break;
-			}
-
-			case State.PATH: {
-				switch (c) {
-				case ';':
-					mark = i + 1;
-					state = State.PARAM;
-					break;
-				case '?':
-					_path = uri.substring(path_mark, i);
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-				case '#':
-					_path = uri.substring(path_mark, i);
-					mark = i + 1;
-					state = State.FRAGMENT;
-					break;
-				case '%':
-					encoded = true;
-					break;
-				case '.':
-					if ('/' == last)
-						encoded = true;
-					break;
-					
-				default:
-					break;
-				}
-				break;
-			}
-
-			case State.PARAM: {
-				switch (c) {
-				case '?':
-					_path = uri.substring(path_mark, i);
-					_param = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-				case '#':
-					_path = uri.substring(path_mark, i);
-					_param = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.FRAGMENT;
-					break;
-				case '/':
-					encoded = true;
-					// ignore internal params
-					state = State.PATH;
-					break;
-				case ';':
-					// multiple parameters
-					mark = i + 1;
-					break;
-					
-				default:
-					break;
-				}
-				break;
-			}
-
-			case State.QUERY: {
-				if (c == '#') {
-					_query = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.FRAGMENT;
-				}
-				break;
-			}
-
-			case State.ASTERISK: {
-				throw new IllegalArgumentException("Bad character '*'");
-			}
-
-			case State.FRAGMENT: {
-				_fragment = uri.substring(mark, end);
-				i = end;
-				break;
-			}
-			}
-			last = c;
-		}
-
-		final switch (state) {
-		case State.START:
-			break;
-		case State.SCHEME_OR_PATH:
-			_path = uri.substring(mark, end);
-			break;
-
-		case State.HOST_OR_PATH:
-			_path = uri.substring(mark, end);
-			break;
-
-		case State.HOST:
-			if (end > mark)
-				_host = uri.substring(mark, end);
-			break;
-
-		case State.IPV6:
-			throw new IllegalArgumentException("No closing ']' for ipv6 in " ~ uri);
-
-		case State.PORT:
-			// _port = TypeUtils.parseInt(uri, mark, end - mark, 10);
-			_port = to!int(uri[mark .. end], 10);
-			break;
-
-		case State.ASTERISK:
-			break;
-
-		case State.FRAGMENT:
-			_fragment = uri.substring(mark, end);
-			break;
-
-		case State.PARAM:
-			_path = uri.substring(path_mark, end);
-			_param = uri.substring(mark, end);
-			break;
-
-		case State.PATH:
-			_path = uri.substring(path_mark, end);
-			break;
-
-		case State.QUERY:
-			_query = uri.substring(mark, end);
-			break;
-		}
-
-		if (!encoded) {
-			if (_param == null)
-				_decodedPath = _path;
-			else
-				_decodedPath = _path[0 .. _path.length - _param.length - 1];
-		}
-	}
-
-	string getScheme() {
-		return _scheme;
-	}
-
-	string getHost() {
-		// Return null for empty host to retain compatibility with java.net.URI
-		if (_host != null && _host.length == 0)
-			return null;
-		return _host;
-	}
-
-	int getPort() {
-		return _port;
-	}
-
-	/**
-	 * The parsed Path.
-	 * 
-	 * @return the path as parsed on valid URI. null for invalid URI.
-	 */
-	string getPath() {
-		return _path;
-	}
-
-	string getDecodedPath() {
-		if (_decodedPath.empty && !_path.empty)
-			_decodedPath = URIUtils.canonicalPath(URIUtils.decodePath(_path));
-		return _decodedPath;
-	}
-
-	string getParam() {
-		return _param;
-	}
-
-	string getQuery() {
-		return _query;
-	}
-
-	bool hasQuery() {
-		return _query != null && _query.length > 0;
-	}
-
-	string getFragment() {
-		return _fragment;
-	}
-
-	void decodeQueryTo(MultiMap!string parameters, string encoding = StandardCharsets.UTF_8) {
-		if (_query == _fragment)
-			return;
-
-		UrlEncoded.decodeTo(_query, parameters, encoding);
-	}
-
-	void clear() {
-		_uri = null;
-
-		_scheme = null;
-		_host = null;
-		_port = -1;
-		_path = null;
-		_param = null;
-		_query = null;
-		_fragment = null;
-
-		_decodedPath = null;
-	}
-
-	bool isAbsolute() {
-		return _scheme != null && _scheme.length > 0;
-	}
-
-	override
-	string toString() {
-		if (_uri is null) {
-			StringBuilder ot = new StringBuilder();
-
-			if (_scheme != null)
-				ot.append(_scheme).append(':');
-
-			if (_host != null) {
-				ot.append("//");
-				if (_user != null)
-					ot.append(_user).append('@');
-				ot.append(_host);
-			}
-
-			if (_port > 0)
-				ot.append(':').append(_port);
-
-			if (_path != null)
-				ot.append(_path);
-
-			if (_query != null)
-				ot.append('?').append(_query);
-
-			if (_fragment != null)
-				ot.append('#').append(_fragment);
-
-			if (ot.length > 0)
-				_uri = ot.toString();
-			else
-				_uri = "";
-		}
-		return _uri;
-	}
-
-	bool equals(Object o) {
-		if (o is this)
-			return true;
-		if (!(typeid(o) == typeid(HttpURI)))
-			return false;
-		return toString().equals(o.toString());
-	}
-
-	void setScheme(string scheme) {
-		_scheme = scheme;
-		_uri = null;
-	}
-
-	/**
-	 * @param host
-	 *            the host
-	 * @param port
-	 *            the port
-	 */
-	void setAuthority(string host, int port) {
-		_host = host;
-		_port = port;
-		_uri = null;
-	}
-
-	/**
-	 * @param path
-	 *            the path
-	 */
-	void setPath(string path) {
-		_uri = null;
-		_path = path;
-		_decodedPath = null;
-	}
-
-	/**
-	 * @param path
-	 *            the decoded path
-	 */
-	// void setDecodedPath(string path) {
-	// 	_uri = null;
-	// 	_path = URIUtils.encodePath(path);
-	// 	_decodedPath = path;
-	// }
-
-	void setPathQuery(string path) {
-		_uri = null;
-		_path = null;
-		_decodedPath = null;
-		_param = null;
-		_fragment = null;
-		if (path != null)
-			parse(State.PATH, path);
-	}
-
-	void setQuery(string query) {
-		_query = query;
-		_uri = null;
-	}
-
-	// URI toURI() {
-	// 	return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodestring(_query),
-	// 			_fragment);
-	// }
-
-	string getPathQuery() {
-		if (_query == null)
-			return _path;
-		return _path ~ "?" ~ _query;
-	}
-
-	bool hasAuthority() {
-		return _host != null;
-	}
-
-	string getAuthority() {
-		if (_port > 0)
-			return _host ~ ":" ~ to!string(_port);
-		return _host;
-	}
-
-	string getUser() {
-		return _user;
-	}
-
-}
-
-
-/**
- * Parse an authority string into Host and Port
- * <p>Parse a string in the form "host:port", handling IPv4 an IPv6 hosts</p>
- *
- */
-class URIUtils
-{
-	/* ------------------------------------------------------------ */
-    /* Decode a URI path and strip parameters
-     */
-    static string decodePath(string path) {
-        return decodePath(path, 0, cast(int)path.length);
-    }
-
-    /* ------------------------------------------------------------ */
-    /* Decode a URI path and strip parameters of UTF-8 path
-     */
-    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];
-                switch (c) {
-                    case '%':
-                        if (builder is null) {
-                            builder = new StringBuilder(path.length);
-                            builder.append(path, offset, i - offset);
-                        }
-                        if ((i + 2) < end) {
-                            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)));
-                                i += 5;
-                            } else {
-                                builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
-                                i += 2;
-                            }
-                        } else {
-                            throw new IllegalArgumentException("Bad URI % encoding");
-                        }
-
-                        break;
-
-                    case ';':
-                        if (builder is null) {
-                            builder = new StringBuilder(path.length);
-                            builder.append(path, offset, i - offset);
-                        }
-
-                        while (++i < end) {
-                            if (path[i] == '/') {
-                                builder.append('/');
-                                break;
-                            }
-                        }
-
-                        break;
-
-                    default:
-                        if (builder !is null)
-                            builder.append(c);
-                        break;
-                }
-            }
-
-            if (builder !is null)
-                return builder.toString();
-            if (offset == 0 && length == path.length)
-                return path;
-            return path.substring(offset, end);
-        } catch (Exception e) {
-            // System.err.println(path.substring(offset, offset + length) + " " + e);
-			error(e.toString);
-            return decodeISO88591Path(path, offset, length);
-        }
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /* Decode a URI path and strip parameters of ISO-8859-1 path
-     */
-    private static string decodeISO88591Path(string path, int offset, int length) {
-        StringBuilder builder = null;
-        int end = offset + length;
-        for (int i = offset; i < end; i++) {
-            char c = path[i];
-            switch (c) {
-                case '%':
-                    if (builder is null) {
-                        builder = new StringBuilder(path.length);
-                        builder.append(path, offset, i - offset);
-                    }
-                    if ((i + 2) < end) {
-                        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)));
-                            i += 5;
-                        } else {
-                            builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
-                            i += 2;
-                        }
-                    } else {
-                        throw new IllegalArgumentException("");
-                    }
-
-                    break;
-
-                case ';':
-                    if (builder is null) {
-                        builder = new StringBuilder(path.length);
-                        builder.append(path, offset, i - offset);
-                    }
-                    while (++i < end) {
-                        if (path[i] == '/') {
-                            builder.append('/');
-                            break;
-                        }
-                    }
-                    break;
-
-
-                default:
-                    if (builder !is null)
-                        builder.append(c);
-                    break;
-            }
-        }
-
-        if (builder !is null)
-            return builder.toString();
-        if (offset == 0 && length == path.length)
-            return path;
-        return path.substring(offset, end);
-    }
-
-	/* ------------------------------------------------------------ */
-
-    /**
-     * Convert a decoded path to a canonical form.
-     * <p>
-     * All instances of "." and ".." are factored out.
-     * </p>
-     * <p>
-     * Null is returned if the path tries to .. above its root.
-     * </p>
-     *
-     * @param path the path to convert, decoded, with path separators '/' and no queries.
-     * @return the canonical path, or null if path traversal above root.
-     */
-    static string canonicalPath(string path) {
-        if (path.empty)
-            return path;
-
-        bool slash = true;
-        int end = cast(int)path.length;
-        int i = 0;
-
-        loop:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '/':
-                    slash = true;
-                    break;
-
-                case '.':
-                    if (slash)
-                        break loop;
-                    slash = false;
-                    break;
-
-                default:
-                    slash = false;
-            }
-
-            i++;
-        }
-
-        if (i == end)
-            return path;
-
-        StringBuilder canonical = new StringBuilder(path.length);
-        canonical.append(path, 0, i);
-
-        int dots = 1;
-        i++;
-        while (i <= end) {
-            char c = i < end ? path[i] : '\0';
-            switch (c) {
-                case '\0':
-                case '/':
-                    switch (dots) {
-                        case 0:
-                            if (c != '\0')
-                                canonical.append(c);
-                            break;
-
-                        case 1:
-                            break;
-
-                        case 2:
-                            if (canonical.length < 2)
-                                return null;
-                            canonical.setLength(canonical.length - 1);
-                            canonical.setLength(canonical.lastIndexOf("/") + 1);
-                            break;
-
-                        default:
-                            while (dots-- > 0)
-                                canonical.append('.');
-                            if (c != '\0')
-                                canonical.append(c);
-                    }
-
-                    slash = true;
-                    dots = 0;
-                    break;
-
-                case '.':
-                    if (dots > 0)
-                        dots++;
-                    else if (slash)
-                        dots = 1;
-                    else
-                        canonical.append('.');
-                    slash = false;
-                    break;
-
-                default:
-                    while (dots-- > 0)
-                        canonical.append('.');
-                    canonical.append(c);
-                    dots = 0;
-                    slash = false;
-            }
-
-            i++;
-        }
-        return canonical.toString();
-    }
-
-
-    /* ------------------------------------------------------------ */
-
-    /**
-     * Convert a path to a cananonical form.
-     * <p>
-     * All instances of "." and ".." are factored out.
-     * </p>
-     * <p>
-     * Null is returned if the path tries to .. above its root.
-     * </p>
-     *
-     * @param path the path to convert (expects URI/URL form, encoded, and with path separators '/')
-     * @return the canonical path, or null if path traversal above root.
-     */
-    static string canonicalEncodedPath(string path) {
-        if (path.empty)
-            return path;
-
-        bool slash = true;
-        int end = cast(int)path.length;
-        int i = 0;
-
-        loop:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '/':
-                    slash = true;
-                    break;
-
-                case '.':
-                    if (slash)
-                        break loop;
-                    slash = false;
-                    break;
-
-                case '?':
-                    return path;
-
-                default:
-                    slash = false;
-            }
-
-            i++;
-        }
-
-        if (i == end)
-            return path;
-
-        StringBuilder canonical = new StringBuilder(path.length);
-        canonical.append(path, 0, i);
-
-        int dots = 1;
-        i++;
-        while (i <= end) {
-            char c = i < end ? path[i] : '\0';
-            switch (c) {
-                case '\0':
-                case '/':
-                case '?':
-                    switch (dots) {
-                        case 0:
-                            if (c != '\0')
-                                canonical.append(c);
-                            break;
-
-                        case 1:
-                            if (c == '?')
-                                canonical.append(c);
-                            break;
-
-                        case 2:
-                            if (canonical.length < 2)
-                                return null;
-                            canonical.setLength(canonical.length - 1);
-                            canonical.setLength(canonical.lastIndexOf("/") + 1);
-                            if (c == '?')
-                                canonical.append(c);
-                            break;
-                        default:
-                            while (dots-- > 0)
-                                canonical.append('.');
-                            if (c != '\0')
-                                canonical.append(c);
-                    }
-
-                    slash = true;
-                    dots = 0;
-                    break;
-
-                case '.':
-                    if (dots > 0)
-                        dots++;
-                    else if (slash)
-                        dots = 1;
-                    else
-                        canonical.append('.');
-                    slash = false;
-                    break;
-
-                default:
-                    while (dots-- > 0)
-                        canonical.append('.');
-                    canonical.append(c);
-                    dots = 0;
-                    slash = false;
-            }
-
-            i++;
-        }
-        return canonical.toString();
-    }
-
-
-
-    /* ------------------------------------------------------------ */
-
-    /**
-     * Convert a path to a compact form.
-     * All instances of "//" and "///" etc. are factored out to single "/"
-     *
-     * @param path the path to compact
-     * @return the compacted path
-     */
-    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;
-
-        loop:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '?':
-                    return path;
-                case '/':
-                    state++;
-                    if (state == 2)
-                        break loop;
-                    break;
-                default:
-                    state = 0;
-            }
-            i++;
-        }
-
-        if (state < 2)
-            return path;
-
-        StringBuilder buf = new StringBuilder(path.length);
-        buf.append(path, 0, i);
-
-        loop2:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '?':
-                    buf.append(path, i, end);
-                    break loop2;
-                case '/':
-                    if (state++ == 0)
-                        buf.append(c);
-                    break;
-                default:
-                    state = 0;
-                    buf.append(c);
-            }
-            i++;
-        }
-
-        return buf.toString();
-    }
-
-    /* ------------------------------------------------------------ */
-
-    /**
-     * @param uri URI
-     * @return True if the uri has a scheme
-     */
-    static bool hasScheme(string uri) {
-        for (int i = 0; i < uri.length; i++) {
-            char c = uri[i];
-            if (c == ':')
-                return true;
-            if (!(c >= 'a' && c <= 'z' ||
-                    c >= 'A' && c <= 'Z' ||
-                    (i > 0 && (c >= '0' && c <= '9' ||
-                            c == '.' ||
-                            c == '+' ||
-                            c == '-'))
-            ))
-                break;
-        }
-        return false;
-    }
-}

+ 0 - 202
frameworks/D/hunt/mmap/http/Parser.d

@@ -1,202 +0,0 @@
-/// Minimalistic low-overhead wrapper for nodejs/http-parser
-/// Used for benchmarks with simple server
-module http.Parser;
-
-import http.Common;
-
-import hunt.logging.ConsoleLogger;
-import std.conv;
-import std.range.primitives;
-import core.stdc.string;
-
-
-
-/* contains name and value of a header (name == NULL if is a continuing line
- * of a multiline header */
-struct phr_header {
-    const char *name;
-    size_t name_len;
-    const char *value;
-    size_t value_len;
-}
-
-/* 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, 
-	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, 
-	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, 
-	phr_header *headers, size_t *num_headers, size_t last_len);
-
-/* should be zero-filled before start */
-struct phr_chunked_decoder {
-    size_t bytes_left_in_chunk; /* number of bytes left in current chunk */
-    char consume_trailer;       /* if trailing headers should be consumed */
-    char _hex_count;
-    char _state;
-}
-
-/* the function rewrites the buffer given as (buf, bufsz) removing the chunked-
- * encoding headers.  When the function returns without an error, bufsz is
- * updated to the length of the decoded data available.  Applications should
- * repeatedly call the function while it returns -2 (incomplete) every time
- * supplying newly arrived data.  If the end of the chunked-encoded data is
- * found, the function returns a non-negative number indicating the number of
- * octets left undecoded at the tail of the supplied buffer.  Returns -1 on
- * error.
- */
-extern (C) pure @nogc nothrow ptrdiff_t phr_decode_chunked(phr_chunked_decoder *decoder, char *buf, size_t *bufsz);
-
-/* returns if the chunked decoder is in middle of chunked data */
-extern (C) pure @nogc nothrow int phr_decode_chunked_is_in_data(phr_chunked_decoder *decoder);
-
-
-// =========== Public interface starts here =============
-
-public:
-
-class HttpException : Exception {
-	HttpError error;
-
-	pure @nogc nothrow this(HttpError error, string file = __FILE__,
-			size_t line = __LINE__, Throwable nextInChain = null) {
-		this.error = error;
-		super("Http exception", file, line, nextInChain);
-	}
-}
-
-struct HttpParser(Interceptor) {
-	
-private {
-	Interceptor interceptor;
-	Throwable failure;
-	phr_header[50] _headers;
-	char *_method;
-	char *path;
-
-	int minor_version;
-	size_t buflen = 0, prevbuflen = 0, method_len, path_len, num_headers;
-}
-
-
-	alias interceptor this;
-
-	this(Interceptor interceptor) {
-		this.interceptor = interceptor;
-	}
-
-	@property bool status() pure @safe nothrow {
-		return failure is null;
-	}
-
-	string uri(bool canCopy=false)() {
-		static if(canCopy) {
-			return cast(string)path[0..path_len].dup;
-		} else {
-			return cast(string)path[0..path_len];
-		}
-	}
-
-	@property HttpMethod method() {
-		string s = cast(string)_method[0..method_len];
-		return to!HttpMethod(s);
-	}
-
-
-	HttpHeader[] headers(bool canCopy=false)() {
-		HttpHeader[] hs = new HttpHeader[num_headers];
-		
-		for(int i; i<num_headers; i++) {
-			phr_header* h = &_headers[i];
-			static if(canCopy) {
-				hs[i].name = cast(string)h.name[0..h.name_len].idup;
-				hs[i].value = cast(string)h.value[0..h.value_len].idup;
-			} else {
-				hs[i].name = cast(string)h.name[0..h.name_len];
-				hs[i].value = cast(string)h.value[0..h.value_len];
-			}
-		}
-
-		return hs;
-	}
-
-	@property bool shouldKeepAlive() pure nothrow {
-		return true;
-	}
-
-	@property ushort httpMajor() @safe pure nothrow {
-		return 1;
-	}
-
-	@property ushort httpMinor() @safe pure nothrow {
-		return cast(ushort)minor_version;
-	}
-
-	int execute(const(ubyte)[] str) {
-		return doexecute( str);
-	}
-
-	private int doexecute(const(ubyte)[] chunk) {
-		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, 
-					&path, &path_len,
-					&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 */
-			onMessageComplete();
-
-			if(pret < chunk.length) {
-				debug infof("try to parse next request");
-				pret += doexecute(chunk[pret .. $]); // try to parse next http request data
-			}
-
-			debug infof("pret=%d", pret);
-			return pret;
-		} else if(pret == -2) {
-			debug warning("parsing incomplete");
-			num_headers = 0;
-			// failure = new HttpException(HttpError.UNKNOWN);
-			// throw failure;
-
-			debug infof("pret=%d, chunk=%d", pret, chunk.length);
-			return 0;			
-		}
-
-		warning("wrong data format");
-		num_headers = 0;
-		failure = new HttpException(HttpError.UNKNOWN);
-		throw failure;
-	}
-
-	void onMessageComplete() {
-		// interceptor.onHeadersComplete();
-		debug {
-			tracef("method is %s", _method[0..method_len]);
-			tracef("path is %s", path[0..path_len]);
-			tracef("HTTP version is 1.%d", minor_version);
-			foreach(ref phr_header h; _headers[0..num_headers]) {
-				tracef("Header: %s = %s", h.name[0..h.name_len], h.value[0..h.value_len]);
-			}
-		}
-		interceptor.onMessageComplete();
-	}
-}
-
-auto httpParser(Interceptor)(Interceptor interceptor) {
-	return HttpParser!Interceptor(interceptor);
-}

+ 0 - 137
frameworks/D/hunt/mmap/http/Processor.d

@@ -1,137 +0,0 @@
-/// An example "HTTP server" with poor usability but sensible performance
-///
-module http.Processor;
-
-import std.conv;
-import std.array, std.exception, std.format, std.algorithm.mutation, std.socket;
-import core.stdc.stdlib;
-import core.thread, core.atomic;
-import http.Parser;
-
-import hunt.collection.ByteBuffer;
-import http.Common;
-import hunt.logging;
-import hunt.io;
-import hunt.util.DateTime;
-
-
-private	alias Parser = HttpParser!HttpProcessor;
-
-
-struct HttpRequest {
-	private Parser* parser;
-
-	HttpHeader[] headers(bool canCopy=false)() @property {
-		return parser.headers!canCopy();
-	}
-
-	HttpMethod method() @property {
-		return parser.method();
-	}
-
-	string uri(bool canCopy=false)() @property {
-		return parser.uri!(canCopy)();
-	}
-}
-
-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!";
-}
-
-abstract class HttpProcessor {
-	
-package:
-	Appender!(char[]) outBuf;
-	HttpHeader[] headers; // buffer for headers
-	Parser parser;
-	HttpRequest request;
-	bool serving;
-	
-public:
-	TcpStream client;
-
-	this(TcpStream sock) {
-		serving = true;
-		client = sock;
-		headers = new HttpHeader[1];
-		parser = httpParser(this);
-		request.parser = &parser;
-	}
-
-	void run() {
-		client.onReceived(delegate int (ubyte[] buffer) { 
-			version(NO_HTTPPARSER) {
-				client.write(cast(ubyte[])ResponseData);
-			} else {
-				int len = 0;
-				try {
-					len = parser.execute(buffer);
-				} catch(Exception ex) {
-					respondWith(ex.msg, 500);
-					len = cast(int)buffer.length;
-				}
-
-				return len;
-			}
-		})
-		.onClosed(() {
-			// notifyClientClosed();
-		})
-		.onError((string msg) { 
-			debug warning("Error: ", msg); 
-		})
-		.start();
-	}
-
-	protected void notifyClientClosed() {
-		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(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);
-
-
-	final int onBody(Parser* parser, const(ubyte)[] chunk) {
-		onChunk(request, chunk);
-		return 0;
-	}
-
-	final int onMessageComplete() {
-		try {
-			onComplete(request);
-		} catch(Exception ex) {
-			respondWith(ex.msg, 500);
-		}
-		if (!parser.shouldKeepAlive)
-			serving = false;
-		return 0;
-	}
-
-}

+ 0 - 122
frameworks/D/hunt/mmap/http/Server.d

@@ -1,122 +0,0 @@
-module http.Server;
-
-import hunt.event;
-import hunt.io;
-import hunt.logging.ConsoleLogger;
-import hunt.system.Memory : totalCPUs;
-import hunt.util.DateTime;
-
-import std.array;
-import std.conv;
-import std.json;
-import std.socket;
-import std.string;
-import std.stdio;
-
-import http.Parser;
-import http.Processor;
-
-shared static this() {
-	//DateTimeHelper.startClock();
-}
-
-import hunt.io.channel;
-
-/**
-*/
-abstract class AbstractTcpServer {
-	protected EventLoopGroup _group = null;
-	protected bool _isStarted = false;
-	protected Address _address;
-	protected int _workersCount;
-	TcpStreamOption _tcpStreamoption;
-
-	this(Address address, int thread = (totalCPUs - 1), int workersCount = 0) {
-		this._address = address;
-		_tcpStreamoption = TcpStreamOption.createOption();
-		_tcpStreamoption.bufferSize = 1024 * 2;
-		_tcpStreamoption.isKeepalive = false;
-		_group = new EventLoopGroup(cast(uint) thread);
-		this._workersCount = workersCount;
-	}
-
-	@property Address bindingAddress() {
-		return _address;
-	}
-
-	void start() {
-		if (_isStarted)
-			return;
-		_isStarted = true;
-
-		Socket server = new TcpSocket();
-		server.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
-		server.bind(new InternetAddress("0.0.0.0", 8080));
-		server.listen(8192);
-
-		trace("Launching server");
-		debug {
-			_group.start();
-		} else {
-			_group.start(100);
-		}
-
-		if (_workersCount) {
-			defaultPoolThreads = _workersCount;
-			workerPool(); // Initilize worker poll
-		}
-		writefln("worker count: %d", _workersCount);
-		writefln("IO thread: %d", _group.size);
-
-		while (true) {
-			try {
-				version (HUNT_DEBUG)
-					trace("Waiting for server.accept()");
-
-				Socket socket = server.accept();
-				version (HUNT_DEBUG) {
-					infof("new connection from %s, fd=%d",
-							socket.remoteAddress.toString(), socket.handle());
-				}
-				// EventLoop loop = _group.nextLoop();
-				EventLoop loop = _group.nextLoop(socket.handle);
-				TcpStream stream = new TcpStream(loop, socket, _tcpStreamoption);
-				onConnectionAccepted(stream);
-			} catch (Exception e) {
-				warningf("Failure on accepting %s", e);
-				break;
-			}
-		}
-		_isStarted = false;
-	}
-
-	protected void onConnectionAccepted(TcpStream client);
-
-	void stop() {
-		if (!_isStarted)
-			return;
-		_isStarted = false;
-		_group.stop();
-	}
-}
-
-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);
-	}
-
-	this(Address address, int thread = (totalCPUs - 1)) {
-		super(address, thread);
-	}
-
-	override protected void onConnectionAccepted(TcpStream client) {
-		HttpProcessor httpProcessor = new T(client);
-		httpProcessor.run();
-	}
-
-}

+ 0 - 361
frameworks/D/hunt/mmap/http/UrlEncoded.d

@@ -1,361 +0,0 @@
-module http.UrlEncoded;
-
-import hunt.collection.List;
-import hunt.collection.MultiMap;
-import hunt.collection.StringBuffer;
-import hunt.Exceptions;
-import hunt.logging;
-import hunt.text.Charset;
-import hunt.text.Common;
-import hunt.text.StringBuilder;
-import hunt.util.TypeUtils;
-
-import std.conv;
-import std.array;
-
-
-/**
- * Handles coding of MIME "x-www-form-urlencoded".
- * <p>
- * This class handles the encoding and decoding for either the query string of a
- * URL or the _content of a POST HTTP request.
- * </p>
- * <b>Notes</b>
- * <p>
- * The UTF-8 charset is assumed, unless otherwise defined by either passing a
- * parameter or setting the "org.hunt.utils.UrlEncoding.charset" System
- * property.
- * </p>
- * <p>
- * The hashtable either contains string single values, vectors of string or
- * arrays of Strings.
- * </p>
- * <p>
- * This class is only partially synchronised. In particular, simple get
- * operations are not protected from concurrent updates.
- * </p>
- *
- * @see java.net.URLEncoder
- */
-class UrlEncoded  : MultiMap!string { 
-    
-    enum string ENCODING = StandardCharsets.UTF_8;
-
-
-    this() {
-    }
-
-    this(string query) {
-        decodeTo(query, this, ENCODING);
-    }
-
-    void decode(string query) {
-        decodeTo(query, this, ENCODING);
-    }
-
-    void decode(string query, string charset) {
-        decodeTo(query, this, charset);
-    }
-
-    /**
-     * Encode MultiMap with % encoding for UTF8 sequences.
-     *
-     * @return the MultiMap as a string with % encoding
-     */
-    string encode() {
-        return encode(ENCODING, false);
-    }
-
-    /**
-     * Encode MultiMap with % encoding for arbitrary string sequences.
-     *
-     * @param charset the charset to use for encoding
-     * @return the MultiMap as a string encoded with % encodings
-     */
-    string encode(string charset) {
-        return encode(charset, false);
-    }
-
-    /**
-     * Encode MultiMap with % encoding.
-     *
-     * @param charset            the charset to encode with
-     * @param equalsForNullValue if True, then an '=' is always used, even
-     *                           for parameters without a value. e.g. <code>"blah?a=&amp;b=&amp;c="</code>.
-     * @return the MultiMap as a string encoded with % encodings
-     */
-    string encode(string charset, bool equalsForNullValue) {
-        return encode(this, charset, equalsForNullValue);
-    }
-
-    /**
-     * Encode MultiMap with % encoding.
-     *
-     * @param map                the map to encode
-     * @param charset            the charset to use for encoding (uses default encoding if null)
-     * @param equalsForNullValue if True, then an '=' is always used, even
-     *                           for parameters without a value. e.g. <code>"blah?a=&amp;b=&amp;c="</code>.
-     * @return the MultiMap as a string encoded with % encodings.
-     */
-    static string encode(MultiMap!string map, string charset, bool equalsForNullValue) {
-        if (charset is null)
-            charset = ENCODING;
-
-        StringBuilder result = new StringBuilder(128);
-
-        bool delim = false;
-        foreach(string key, List!string list; map)
-        {
-            int s = list.size();
-
-            if (delim) {
-                result.append('&');
-            }
-
-            if (s == 0) {
-                result.append(encodeString(key, charset));
-                if (equalsForNullValue)
-                    result.append('=');
-            } else {
-                for (int i = 0; i < s; i++) {
-                    if (i > 0)
-                        result.append('&');
-                    string val = list.get(i);
-                    result.append(encodeString(key, charset));
-
-                    if (val != null) {
-                        if (val.length > 0) {
-                            result.append('=');
-                            result.append(encodeString(val, charset));
-                        } else if (equalsForNullValue)
-                            result.append('=');
-                    } else if (equalsForNullValue)
-                        result.append('=');
-                }
-            }
-            delim = true;
-        }
-        return result.toString();
-    }
-
-    /**
-     * Decoded parameters to Map.
-     *
-     * @param content the string containing the encoded parameters
-     * @param map     the MultiMap to put parsed query parameters into
-     * @param charset the charset to use for decoding
-     */
-    static void decodeTo(string content, MultiMap!string map, string charset = ENCODING) {
-        if (charset.empty)
-            charset = ENCODING;
-
-        synchronized (map) {
-            string key = null;
-            string value = null;
-            int mark = -1;
-            bool encoded = false;
-            for (int i = 0; i < content.length; i++) {
-                char c = content[i];
-                switch (c) {
-                    case '&':
-                        int l = i - mark - 1;
-                        value = l == 0 ? "" :
-                                (encoded ? decodeString(content, mark + 1, l) : content.substring(mark + 1, i));
-                        mark = i;
-                        encoded = false;
-                        if (key != null) {
-                            map.add(key, value);
-                        } else if (value != null && value.length > 0) {
-                            map.add(value, "");
-                        }
-                        key = null;
-                        value = null;
-                        break;
-                    case '=':
-                        if (key != null)
-                            break;
-                        key = encoded ? decodeString(content, mark + 1, i - mark - 1) : content.substring(mark + 1, i);
-                        mark = i;
-                        encoded = false;
-                        break;
-                    case '+':
-                        encoded = true;
-                        break;
-                    case '%':
-                        encoded = true;
-                        break;
-                    default: break;
-                }
-            }
-
-            int contentLen = cast(int)content.length;
-
-            if (key != null) {
-                int l =  contentLen - mark - 1;
-                value = l == 0 ? "" : (encoded ? decodeString(content, mark + 1, l) : content.substring(mark + 1));
-                version(HUNT_DEBUG) tracef("key=%s, value=%s", key, value);
-                map.add(key, value);
-            } else if (mark < contentLen) {
-                version(HUNT_DEBUG) tracef("empty value: content=%s, key=%s", content, key);
-                key = encoded
-                        ? decodeString(content, mark + 1, contentLen - mark - 1, charset)
-                        : content.substring(mark + 1);
-                if (!key.empty) {
-                    map.add(key, "");
-                }
-            } else {
-                warningf("No key found.");
-            }
-        }
-    }
-
-    /**
-     * Decode string with % encoding.
-     * This method makes the assumption that the majority of calls
-     * will need no decoding.
-     *
-     * @param encoded the encoded string to decode
-     * @return the decoded string
-     */
-    static string decodeString(string encoded) {
-        return decodeString(encoded, 0, cast(int)encoded.length);
-    }
-
-    /**
-     * Decode string with % encoding.
-     * This method makes the assumption that the majority of calls
-     * will need no decoding.
-     *
-     * @param encoded the encoded string to decode
-     * @param offset  the offset in the encoded string to decode from
-     * @param length  the length of characters in the encoded string to decode
-     * @param charset the charset to use for decoding
-     * @return the decoded 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) {
-                if (buffer is null) {
-                    buffer = new StringBuffer(length);
-                    buffer.append(encoded, offset, offset + i + 1);
-                } else
-                    buffer.append(c);
-            } else if (c == '+') {
-                if (buffer is null) {
-                    buffer = new StringBuffer(length);
-                    buffer.append(encoded, offset, offset + i);
-                }
-
-                buffer.append(' ');
-            } else if (c == '%') {
-                if (buffer is null) {
-                    buffer = new StringBuffer(length);
-                    buffer.append(encoded, offset, offset + i);
-                }
-
-                byte[] ba = new byte[length];
-                int n = 0;
-                while (c >= 0 && c <= 0xff) {
-                    if (c == '%') {
-                        if (i + 2 < length) {
-                            int o = offset + i + 1;
-                            i += 3;
-                            ba[n] = cast(byte) TypeUtils.parseInt(encoded, o, 2, 16);
-                            n++;
-                        } else {
-                            ba[n++] = cast(byte) '?';
-                            i = length;
-                        }
-                    } else if (c == '+') {
-                        ba[n++] = cast(byte) ' ';
-                        i++;
-                    } else {
-                        ba[n++] = cast(byte) c;
-                        i++;
-                    }
-
-                    if (i >= length)
-                        break;
-                    c = encoded.charAt(offset + i);
-                }
-
-                i--;
-                buffer.append(cast(string)(ba[0 .. n]));
-
-            } else if (buffer !is null)
-                buffer.append(c);
-        }
-
-        if (buffer is null) {
-            if (offset == 0 && encoded.length == length)
-                return encoded;
-            return encoded.substring(offset, offset + length);
-        }
-
-        return buffer.toString();
-    }
-
-
-    /**
-     * Perform URL encoding.
-     *
-     * @param string the string to encode
-     * @return encoded string.
-     */
-    static string encodeString(string string) {
-        return encodeString(string, ENCODING);
-    }
-
-    /**
-     * Perform URL encoding.
-     *
-     * @param string  the string to encode
-     * @param charset the charset to use for encoding
-     * @return encoded string.
-     */
-    static string encodeString(string str, string charset) {
-        if (charset is null)
-            charset = ENCODING;
-        byte[] bytes = cast(byte[])str;
-        // bytes = string.getBytes(charset);
-
-        int len = cast(int)bytes.length;
-        byte[] encoded = new byte[bytes.length * 3];
-        int n = 0;
-        bool noEncode = true;
-
-        for (int i = 0; i < len; i++) {
-            byte b = bytes[i];
-
-            if (b == ' ') {
-                noEncode = false;
-                encoded[n++] = cast(byte) '+';
-            } else if (b >= 'a' && b <= 'z' ||
-                    b >= 'A' && b <= 'Z' ||
-                    b >= '0' && b <= '9') {
-                encoded[n++] = b;
-            } else {
-                noEncode = false;
-                encoded[n++] = cast(byte) '%';
-                byte nibble = cast(byte) ((b & 0xf0) >> 4);
-                if (nibble >= 10)
-                    encoded[n++] = cast(byte) ('A' + nibble - 10);
-                else
-                    encoded[n++] = cast(byte) ('0' + nibble);
-                nibble = cast(byte) (b & 0xf);
-                if (nibble >= 10)
-                    encoded[n++] = cast(byte) ('A' + nibble - 10);
-                else
-                    encoded[n++] = cast(byte) ('0' + nibble);
-            }
-        }
-
-        if (noEncode)
-            return str;
-
-        return cast(string)(encoded[0 .. n]);
-    }
-}

+ 0 - 50
frameworks/D/hunt/patches/Makefile

@@ -1,50 +0,0 @@
-#
-# Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
-#                         Shigeo Mitsunari
-#
-# The software is licensed under either the MIT License (below) or the Perl
-# license.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-CC?=gcc
-AR?=ar
-PROVE?=prove
-
-CFLAGS += -Wall -Wextra -Werror -O3
-
-all: package test
-
-test: test-bin
-	$(PROVE) -v ./test-bin
-
-test-bin: picohttpparser.c picotest/picotest.c test.c
-	$(CC) -Wall $(CFLAGS) $(LDFLAGS) -o $@ $^
-
-picohttpparser.o: picohttpparser.c picohttpparser.h Makefile
-	$(CC) $(CFLAGS) -c picohttpparser.c
-
-package: picohttpparser.o
-	$(AR) rcs libpicohttpparser.a picohttpparser.o
-
-clean:
-	rm -f test-bin
-
-.PHONY: test
-

+ 0 - 47
frameworks/D/hunt/pico/app.d

@@ -1,47 +0,0 @@
-/*
- * Collie - An asynchronous event-driven network framework using Dlang development
- *
- * Copyright (C) 2015-2018  Shanghai Putao Technology Co., Ltd
- *
- * Developer: Putao's Dlang team
- *
- * Licensed under the Apache-2.0 License.
- *
- */
-import std.getopt;
-import std.stdio;
-
-//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);
-	if (o.helpWanted) {
-		defaultGetoptPrinter("A mini-http server powered by Hunt!", o.options);
-		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);
-	//}
-
-	AbstractTcpServer httpServer = new HttpServer!(DemoProcessor)("0.0.0.0", port, totalCPUs);
-	writefln("listening on http://%s", httpServer.bindingAddress.toString());
-	httpServer.start();
-}

+ 0 - 85
frameworks/D/hunt/pico/http/Common.d

@@ -1,85 +0,0 @@
-module http.Common;
-
-
-
-public enum HttpParserType : uint {
-	request = 0,
-	response = 1,
-	both = 2
-}
-
-struct HttpHeader {
-	string name, value;
-}
-
-public enum HttpMethod : uint {
-	DELETE = 0,
-	GET = 1,
-	HEAD = 2,
-	POST = 3,
-	PUT = 4,
-	/* pathological */
-	CONNECT = 5,
-	OPTIONS = 6,
-	TRACE = 7,
-	/* WebDAV */
-	COPY = 8,
-	LOCK = 9,
-	MKCOL = 10,
-	MOVE = 11,
-	PROPFIND = 12,
-	PROPPATCH = 13,
-	SEARCH = 14,
-	UNLOCK = 15,
-	BIND = 16,
-	REBIND = 17,
-	UNBIND = 18,
-	ACL = 19,
-	/* subversion */
-	REPORT = 20,
-	MKACTIVITY = 21,
-	CHECKOUT = 22,
-	MERGE = 23,
-	/* upnp */
-	MSEARCH = 24,
-	NOTIFY = 25,
-	SUBSCRIBE = 26,
-	UNSUBSCRIBE = 27,
-	/* RFC-5789 */
-	PATCH = 28,
-	PURGE = 29,
-	/* CalDAV */
-	MKCALENDAR = 30,
-	/* RFC-2068, section 19.6.1.2 */
-	LINK = 31,
-	UNLINK = 32,
-	/* icecast */
-	SOURCE = 33,
-}
-
-enum HttpError : uint {
-	OK,
-	/* Parsing-related errors */
-	INVALID_EOF_STATE,
-	HEADER_OVERFLOW,
-	CLOSED_CONNECTION,
-	INVALID_VERSION,
-	INVALID_STATUS,
-	INVALID_METHOD,
-	INVALID_URL,
-	INVALID_HOST,
-	INVALID_PORT,
-	INVALID_PATH,
-	INVALID_QUERY_STRING,
-	INVALID_FRAGMENT,
-	LF_EXPECTED,
-	INVALID_HEADER_TOKEN,
-	INVALID_CONTENT_LENGTH,
-	UNEXPECTED_CONTENT_LENGTH,
-	INVALID_CHUNK_SIZE,
-	INVALID_CONSTANT,
-	INVALID_INTERNAL_STATE,
-	STRICT,
-	PAUSED,
-	UNKNOWN
-}

+ 0 - 253
frameworks/D/hunt/pico/http/DemoProcessor.d

@@ -1,253 +0,0 @@
-module http.DemoProcessor;
-
-
-
-// import stdx.data.json;
-import std.json;
-
-import hunt.io;
-import http.Common;
-import http.Processor;
-import http.HttpURI;
-import http.UrlEncoded;
-import hunt.logging.ConsoleLogger : trace, warning, tracef;
-
-import std.algorithm;
-import std.array;
-import std.exception;
-import std.random;
-import std.string;
-
-version (POSTGRESQL) {
-   // __gshared Database dbConnection;
-}
-
-enum HttpHeader textHeader = HttpHeader("Content-Type", "text/plain; charset=UTF-8");
-enum HttpHeader htmlHeader = HttpHeader("Content-Type", "text/html; charset=UTF-8");
-enum HttpHeader jsonHeader = HttpHeader("Content-Type", "application/json; charset=UTF-8");
-
-
-enum plaintextLength = "/plaintext".length;
-enum jsonLength = "/json".length;
-enum dbLength = "/db".length;
-enum fortunesLength = "/fortunes".length;
-
-class DemoProcessor : HttpProcessor {
-    version (POSTGRESQL) HttpURI uri;
-
-    this(TcpStream client) {
-        version (POSTGRESQL) uri = new HttpURI();
-        super(client);
-    }
-
-    override void onComplete(ref HttpRequest req) {
-
-        string path = req.uri;
-        if(path.length == plaintextLength) { // plaintext
-            respondWith(RET.TEXT, 200, textHeader);
-        } else if(path.length == jsonLength) { // json
-            //JSONValue js = JSONValue(["message" : JSONValue("Hello, World!")]);
-            respondWith(RET.JSON, 200, jsonHeader);
-        } else {
-
-        version (POSTGRESQL) {
-            if(path.length == dbLength) {
-                respondSingleQuery();
-            } else if(path.length == fortunesLength) {
-                respondFortunes();
-            } else {
-                handleDbUpdate(path);
-            }
-
-        } 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) {
-        private void handleDbUpdate(string url) {
-            uri.parse(url);
-
-            switch(uri.getPath()) {
-            case "/queries":
-                UrlEncoded queriesMap = new UrlEncoded();
-                uri.decodeQueryTo(queriesMap);
-                int number = 1;
-                debug {
-                    trace(queriesMap.toString());
-                    if (!queriesMap.containsKey("queries")) {
-                        respondWith404();
-                        return;
-                    }
-
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                            warning(ex.msg);
-                        }
-                    }
-                } else {
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                        }
-                    }
-                }
-
-                respondMultipleQuery(number);
-                break;
-
-
-            case "/updates":
-                UrlEncoded queriesMap = new UrlEncoded();
-                uri.decodeQueryTo(queriesMap);
-                int number = 1;
-                debug {
-                    if (!queriesMap.containsKey("queries")) {
-                        respondWith404();
-                        return;
-                    }
-
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                            warning(ex.msg);
-                        }
-                    }
-                } else {
-                    string v = queriesMap.getValue("queries", 0);
-                    if (!v.empty) {
-                        try {
-                            number = to!int(v);
-                        } catch (Exception ex) {
-                        }
-                    }
-                }
-                respondUpdates(number);
-                break;
-
-            default:
-                respondWith404();
-                break;
-            }
-        }
-
-
-        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);
-        }
-
-        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);
-        }
-
-        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);
-        }
-
-        static string randerFortunes(FortuneModel[] data) {
-            Appender!string sb;
-            sb.put(`<!DOCTYPE html>
-<html>
-	<head>
-		<title>Fortunes</title>
-	</head>
-	<body>
-		<table>
-			<tr>
-				<th>id</th><th>message</th>
-			</tr>
-`);
-
-            foreach (FortuneModel f; data) {
-                string message = replace(f.message, ">", "&gt;");
-                message = replace(message, "<", "&lt;");
-                message = replace(message, "\"", "&quot;");
-                sb.put(format("			<tr>\n				<td>%d</td><td>%s</td>\n			</tr>\n", f.id, message));
-            }
-
-            sb.put("		</table>\n	</body>\n</html>");
-
-            return sb.data;
-        }
-
-        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);
-        }
-    }
-}
-
-struct FortuneModel {
-    int id;
-    string message;
-}

+ 0 - 1167
frameworks/D/hunt/pico/http/HttpURI.d

@@ -1,1167 +0,0 @@
-module http.HttpURI;
-
-
-
-import hunt.collection.MultiMap;
-
-import hunt.Exceptions;
-import hunt.text.Charset;
-import hunt.text.Common;
-import hunt.text.StringBuilder;
-import hunt.util.TypeUtils;
-import http.UrlEncoded;
-
-import std.array;
-import std.conv;
-import std.string;
-
-import hunt.logging;
-
-
-/**
- * Http URI. Parse a HTTP URI from a string or byte array. Given a URI
- * <code>http://user@host:port/path/info;param?query#fragment</code> this class
- * will split it into the following undecoded optional elements:
- * <ul>
- * <li>{@link #getScheme()} - http:</li>
- * <li>{@link #getAuthority()} - //name@host:port</li>
- * <li>{@link #getHost()} - host</li>
- * <li>{@link #getPort()} - port</li>
- * <li>{@link #getPath()} - /path/info</li>
- * <li>{@link #getParam()} - param</li>
- * <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
- * <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
- */
-class HttpURI {
-	private enum State {
-		START, HOST_OR_PATH, SCHEME_OR_PATH, HOST, IPV6, PORT, PATH, PARAM, QUERY, FRAGMENT, ASTERISK
-	}
-
-	private string _scheme;
-	private string _user;
-	private string _host;
-	private int _port;
-	private string _path;
-	private string _param;
-	private string _query;
-	private string _fragment;
-
-	string _uri;
-	string _decodedPath;
-
-	/**
-	 * Construct a normalized URI. Port is not set if it is the default port.
-	 *
-	 * @param scheme
-	 *            the URI scheme
-	 * @param host
-	 *            the URI hose
-	 * @param port
-	 *            the URI port
-	 * @param path
-	 *            the URI path
-	 * @param param
-	 *            the URI param
-	 * @param query
-	 *            the URI query
-	 * @param fragment
-	 *            the URI fragment
-	 * @return the normalized URI
-	 */
-	static HttpURI createHttpURI(string scheme, string host, int port, string path, string param, string query,
-			string fragment) {
-		if (port == 80 && (scheme == "http"))
-			port = 0;
-		if (port == 443 && (scheme == "https"))
-			port = 0;
-		return new HttpURI(scheme, host, port, path, param, query, fragment);
-	}
-
-	this() {
-	}
-
-	this(string scheme, string host, int port, string path, string param, string query, string fragment) {
-		_scheme = scheme;
-		_host = host;
-		_port = port;
-		_path = path;
-		_param = param;
-		_query = query;
-		_fragment = fragment;
-	}
-
-	this(HttpURI uri) {
-		this(uri._scheme, uri._host, uri._port, uri._path, uri._param, uri._query, uri._fragment);
-		_uri = uri._uri;
-	}
-
-	this(string uri) {
-		_port = -1;
-		parse(State.START, uri);
-	}
-
-	// this(URI uri) {
-	// 	_uri = null;
-
-	// 	_scheme = uri.getScheme();
-	// 	_host = uri.getHost();
-	// 	if (_host == null && uri.getRawSchemeSpecificPart().startsWith("//"))
-	// 		_host = "";
-	// 	_port = uri.getPort();
-	// 	_user = uri.getUserInfo();
-	// 	_path = uri.getRawPath();
-
-	// 	_decodedPath = uri.getPath();
-	// 	if (_decodedPath != null) {
-	// 		int p = _decodedPath.lastIndexOf(';');
-	// 		if (p >= 0)
-	// 			_param = _decodedPath.substring(p + 1);
-	// 	}
-	// 	_query = uri.getRawQuery();
-	// 	_fragment = uri.getFragment();
-
-	// 	_decodedPath = null;
-	// }
-
-	this(string scheme, string host, int port, string pathQuery) {
-		_uri = null;
-
-		_scheme = scheme;
-		_host = host;
-		_port = port;
-
-		parse(State.PATH, pathQuery);
-
-	}
-
-	void parse(string uri) {
-		clear();
-		_uri = uri;
-		parse(State.START, uri);
-	}
-
-	/**
-	 * Parse according to https://tools.ietf.org/html/rfc7230#section-5.3
-	 *
-	 * @param method
-	 *            the request method
-	 * @param uri
-	 *            the request uri
-	 */
-	void parseRequestTarget(string method, string uri) {
-		clear();
-		_uri = uri;
-
-		if (method == "CONNECT")
-			_path = uri;
-		else
-			parse(uri.startsWith("/") ? State.PATH : State.START, uri);
-	}
-
-	// deprecated("")
-	// void parseConnect(string uri) {
-	// 	clear();
-	// 	_uri = uri;
-	// 	_path = uri;
-	// }
-
-	void parse(string uri, int offset, int length) {
-		clear();
-		int end = offset + length;
-		_uri = uri.substring(offset, end);
-		parse(State.START, uri);
-	}
-
-	private void parse(State state, string uri) {
-		bool encoded = false;
-		int end = cast(int)uri.length;
-		int mark = 0;
-		int path_mark = 0;
-		char last = '/';
-		for (int i = 0; i < end; i++) {
-			char c = uri[i];
-
-			final switch (state) {
-			case State.START: {
-				switch (c) {
-				case '/':
-					mark = i;
-					state = State.HOST_OR_PATH;
-					break;
-				case ';':
-					mark = i + 1;
-					state = State.PARAM;
-					break;
-				case '?':
-					// assume empty path (if seen at start)
-					_path = "";
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-				case '#':
-					mark = i + 1;
-					state = State.FRAGMENT;
-					break;
-				case '*':
-					_path = "*";
-					state = State.ASTERISK;
-					break;
-
-				case '.':
-					path_mark = i;
-					state = State.PATH;
-					encoded = true;
-					break;
-
-				default:
-					mark = i;
-					if (_scheme == null)
-						state = State.SCHEME_OR_PATH;
-					else {
-						path_mark = i;
-						state = State.PATH;
-					}
-					break;
-				}
-
-				continue;
-			}
-
-			case State.SCHEME_OR_PATH: {
-				switch (c) {
-				case ':':
-					// must have been a scheme
-					_scheme = uri.substring(mark, i);
-					// Start again with scheme set
-					state = State.START;
-					break;
-
-				case '/':
-					// must have been in a path and still are
-					state = State.PATH;
-					break;
-
-				case ';':
-					// must have been in a path
-					mark = i + 1;
-					state = State.PARAM;
-					break;
-
-				case '?':
-					// must have been in a path
-					_path = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-
-				case '%':
-					// must have be in an encoded path
-					encoded = true;
-					state = State.PATH;
-					break;
-
-				case '#':
-					// must have been in a path
-					_path = uri.substring(mark, i);
-					state = State.FRAGMENT;
-					break;
-
-				default:
-					break;
-				}
-				continue;
-			}
-
-			case State.HOST_OR_PATH: {
-				switch (c) {
-				case '/':
-					_host = "";
-					mark = i + 1;
-					state = State.HOST;
-					break;
-
-				case '@':
-				case ';':
-				case '?':
-				case '#':
-					// was a path, look again
-					i--;
-					path_mark = mark;
-					state = State.PATH;
-					break;
-
-				case '.':
-					// it is a path
-					encoded = true;
-					path_mark = mark;
-					state = State.PATH;
-					break;
-
-				default:
-					// it is a path
-					path_mark = mark;
-					state = State.PATH;
-				}
-				continue;
-			}
-
-			case State.HOST: {
-				switch (c) {
-				case '/':
-					_host = uri.substring(mark, i);
-					path_mark = mark = i;
-					state = State.PATH;
-					break;
-				case ':':
-					if (i > mark)
-						_host = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.PORT;
-					break;
-				case '@':
-					if (_user != null)
-						throw new IllegalArgumentException("Bad authority");
-					_user = uri.substring(mark, i);
-					mark = i + 1;
-					break;
-
-				case '[':
-					state = State.IPV6;
-					break;
-
-				default:
-					break;
-				}
-				break;
-			}
-
-			case State.IPV6: {
-				switch (c) {
-				case '/':
-					throw new IllegalArgumentException("No closing ']' for ipv6 in " ~ uri);
-				case ']':
-					c = uri.charAt(++i);
-					_host = uri.substring(mark, i);
-					if (c == ':') {
-						mark = i + 1;
-						state = State.PORT;
-					} else {
-						path_mark = mark = i;
-						state = State.PATH;
-					}
-					break;
-
-				default:
-					break;
-				}
-
-				break;
-			}
-
-			case State.PORT: {
-				if (c == '@') {
-					if (_user != null)
-						throw new IllegalArgumentException("Bad authority");
-					// It wasn't a port, but a password!
-					_user = _host ~ ":" ~ uri.substring(mark, i);
-					mark = i + 1;
-					state = State.HOST;
-				} else if (c == '/') {
-					// _port = TypeUtils.parseInt(uri, mark, i - mark, 10);
-					_port = to!int(uri[mark .. i], 10);
-					path_mark = mark = i;
-					state = State.PATH;
-				}
-				break;
-			}
-
-			case State.PATH: {
-				switch (c) {
-				case ';':
-					mark = i + 1;
-					state = State.PARAM;
-					break;
-				case '?':
-					_path = uri.substring(path_mark, i);
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-				case '#':
-					_path = uri.substring(path_mark, i);
-					mark = i + 1;
-					state = State.FRAGMENT;
-					break;
-				case '%':
-					encoded = true;
-					break;
-				case '.':
-					if ('/' == last)
-						encoded = true;
-					break;
-
-				default:
-					break;
-				}
-				break;
-			}
-
-			case State.PARAM: {
-				switch (c) {
-				case '?':
-					_path = uri.substring(path_mark, i);
-					_param = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.QUERY;
-					break;
-				case '#':
-					_path = uri.substring(path_mark, i);
-					_param = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.FRAGMENT;
-					break;
-				case '/':
-					encoded = true;
-					// ignore internal params
-					state = State.PATH;
-					break;
-				case ';':
-					// multiple parameters
-					mark = i + 1;
-					break;
-
-				default:
-					break;
-				}
-				break;
-			}
-
-			case State.QUERY: {
-				if (c == '#') {
-					_query = uri.substring(mark, i);
-					mark = i + 1;
-					state = State.FRAGMENT;
-				}
-				break;
-			}
-
-			case State.ASTERISK: {
-				throw new IllegalArgumentException("Bad character '*'");
-			}
-
-			case State.FRAGMENT: {
-				_fragment = uri.substring(mark, end);
-				i = end;
-				break;
-			}
-			}
-			last = c;
-		}
-
-		final switch (state) {
-		case State.START:
-			break;
-		case State.SCHEME_OR_PATH:
-			_path = uri.substring(mark, end);
-			break;
-
-		case State.HOST_OR_PATH:
-			_path = uri.substring(mark, end);
-			break;
-
-		case State.HOST:
-			if (end > mark)
-				_host = uri.substring(mark, end);
-			break;
-
-		case State.IPV6:
-			throw new IllegalArgumentException("No closing ']' for ipv6 in " ~ uri);
-
-		case State.PORT:
-			// _port = TypeUtils.parseInt(uri, mark, end - mark, 10);
-			_port = to!int(uri[mark .. end], 10);
-			break;
-
-		case State.ASTERISK:
-			break;
-
-		case State.FRAGMENT:
-			_fragment = uri.substring(mark, end);
-			break;
-
-		case State.PARAM:
-			_path = uri.substring(path_mark, end);
-			_param = uri.substring(mark, end);
-			break;
-
-		case State.PATH:
-			_path = uri.substring(path_mark, end);
-			break;
-
-		case State.QUERY:
-			_query = uri.substring(mark, end);
-			break;
-		}
-
-		if (!encoded) {
-			if (_param == null)
-				_decodedPath = _path;
-			else
-				_decodedPath = _path[0 .. _path.length - _param.length - 1];
-		}
-	}
-
-	string getScheme() {
-		return _scheme;
-	}
-
-	string getHost() {
-		// Return null for empty host to retain compatibility with java.net.URI
-		if (_host != null && _host.length == 0)
-			return null;
-		return _host;
-	}
-
-	int getPort() {
-		return _port;
-	}
-
-	/**
-	 * The parsed Path.
-	 *
-	 * @return the path as parsed on valid URI. null for invalid URI.
-	 */
-	string getPath() {
-		return _path;
-	}
-
-	string getDecodedPath() {
-		if (_decodedPath.empty && !_path.empty)
-			_decodedPath = URIUtils.canonicalPath(URIUtils.decodePath(_path));
-		return _decodedPath;
-	}
-
-	string getParam() {
-		return _param;
-	}
-
-	string getQuery() {
-		return _query;
-	}
-
-	bool hasQuery() {
-		return _query != null && _query.length > 0;
-	}
-
-	string getFragment() {
-		return _fragment;
-	}
-
-	void decodeQueryTo(MultiMap!string parameters, string encoding = StandardCharsets.UTF_8) {
-		if (_query == _fragment)
-			return;
-
-		UrlEncoded.decodeTo(_query, parameters, encoding);
-	}
-
-	void clear() {
-		_uri = null;
-
-		_scheme = null;
-		_host = null;
-		_port = -1;
-		_path = null;
-		_param = null;
-		_query = null;
-		_fragment = null;
-
-		_decodedPath = null;
-	}
-
-	bool isAbsolute() {
-		return _scheme != null && _scheme.length > 0;
-	}
-
-	override
-	string toString() {
-		if (_uri is null) {
-			StringBuilder ot = new StringBuilder();
-
-			if (_scheme != null)
-				ot.append(_scheme).append(':');
-
-			if (_host != null) {
-				ot.append("//");
-				if (_user != null)
-					ot.append(_user).append('@');
-				ot.append(_host);
-			}
-
-			if (_port > 0)
-				ot.append(':').append(_port);
-
-			if (_path != null)
-				ot.append(_path);
-
-			if (_query != null)
-				ot.append('?').append(_query);
-
-			if (_fragment != null)
-				ot.append('#').append(_fragment);
-
-			if (ot.length > 0)
-				_uri = ot.toString();
-			else
-				_uri = "";
-		}
-		return _uri;
-	}
-
-	bool equals(Object o) {
-		if (o is this)
-			return true;
-		if (!(typeid(o) == typeid(HttpURI)))
-			return false;
-		return toString().equals(o.toString());
-	}
-
-	void setScheme(string scheme) {
-		_scheme = scheme;
-		_uri = null;
-	}
-
-	/**
-	 * @param host
-	 *            the host
-	 * @param port
-	 *            the port
-	 */
-	void setAuthority(string host, int port) {
-		_host = host;
-		_port = port;
-		_uri = null;
-	}
-
-	/**
-	 * @param path
-	 *            the path
-	 */
-	void setPath(string path) {
-		_uri = null;
-		_path = path;
-		_decodedPath = null;
-	}
-
-	/**
-	 * @param path
-	 *            the decoded path
-	 */
-	// void setDecodedPath(string path) {
-	// 	_uri = null;
-	// 	_path = URIUtils.encodePath(path);
-	// 	_decodedPath = path;
-	// }
-
-	void setPathQuery(string path) {
-		_uri = null;
-		_path = null;
-		_decodedPath = null;
-		_param = null;
-		_fragment = null;
-		if (path != null)
-			parse(State.PATH, path);
-	}
-
-	void setQuery(string query) {
-		_query = query;
-		_uri = null;
-	}
-
-	// URI toURI() {
-	// 	return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodestring(_query),
-	// 			_fragment);
-	// }
-
-	string getPathQuery() {
-		if (_query == null)
-			return _path;
-		return _path ~ "?" ~ _query;
-	}
-
-	bool hasAuthority() {
-		return _host != null;
-	}
-
-	string getAuthority() {
-		if (_port > 0)
-			return _host ~ ":" ~ to!string(_port);
-		return _host;
-	}
-
-	string getUser() {
-		return _user;
-	}
-
-}
-
-
-/**
- * Parse an authority string into Host and Port
- * <p>Parse a string in the form "host:port", handling IPv4 an IPv6 hosts</p>
- *
- */
-class URIUtils
-{
-	/* ------------------------------------------------------------ */
-    /* Decode a URI path and strip parameters
-     */
-    static string decodePath(string path) {
-        return decodePath(path, 0, cast(int)path.length);
-    }
-
-    /* ------------------------------------------------------------ */
-    /* Decode a URI path and strip parameters of UTF-8 path
-     */
-    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];
-                switch (c) {
-                    case '%':
-                        if (builder is null) {
-                            builder = new StringBuilder(path.length);
-                            builder.append(path, offset, i - offset);
-                        }
-                        if ((i + 2) < end) {
-                            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)));
-                                i += 5;
-                            } else {
-                                //builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
-                                i += 2;
-                            }
-                        } else {
-                            throw new IllegalArgumentException("Bad URI % encoding");
-                        }
-
-                        break;
-
-                    case ';':
-                        if (builder is null) {
-                            builder = new StringBuilder(path.length);
-                            builder.append(path, offset, i - offset);
-                        }
-
-                        while (++i < end) {
-                            if (path[i] == '/') {
-                                builder.append('/');
-                                break;
-                            }
-                        }
-
-                        break;
-
-                    default:
-                        if (builder !is null)
-                            builder.append(c);
-                        break;
-                }
-            }
-
-            if (builder !is null)
-                return builder.toString();
-            if (offset == 0 && length == path.length)
-                return path;
-            return path.substring(offset, end);
-        } catch (Exception e) {
-            // System.err.println(path.substring(offset, offset + length) + " " + e);
-			error(e.toString);
-            return decodeISO88591Path(path, offset, length);
-        }
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /* Decode a URI path and strip parameters of ISO-8859-1 path
-     */
-    private static string decodeISO88591Path(string path, int offset, int length) {
-        StringBuilder builder = null;
-        int end = offset + length;
-        for (int i = offset; i < end; i++) {
-            char c = path[i];
-            switch (c) {
-                case '%':
-                    if (builder is null) {
-                        builder = new StringBuilder(path.length);
-                        builder.append(path, offset, i - offset);
-                    }
-                    if ((i + 2) < end) {
-                        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)));
-                            i += 5;
-                        } else {
-                            //builder.append(cast(byte) (0xff & (TypeUtils.convertHexDigit(u) * 16 + TypeUtils.convertHexDigit(path.charAt(i + 2)))));
-                            i += 2;
-                        }
-                    } else {
-                        throw new IllegalArgumentException("");
-                    }
-
-                    break;
-
-                case ';':
-                    if (builder is null) {
-                        builder = new StringBuilder(path.length);
-                        builder.append(path, offset, i - offset);
-                    }
-                    while (++i < end) {
-                        if (path[i] == '/') {
-                            builder.append('/');
-                            break;
-                        }
-                    }
-                    break;
-
-
-                default:
-                    if (builder !is null)
-                        builder.append(c);
-                    break;
-            }
-        }
-
-        if (builder !is null)
-            return builder.toString();
-        if (offset == 0 && length == path.length)
-            return path;
-        return path.substring(offset, end);
-    }
-
-	/* ------------------------------------------------------------ */
-
-    /**
-     * Convert a decoded path to a canonical form.
-     * <p>
-     * All instances of "." and ".." are factored out.
-     * </p>
-     * <p>
-     * Null is returned if the path tries to .. above its root.
-     * </p>
-     *
-     * @param path the path to convert, decoded, with path separators '/' and no queries.
-     * @return the canonical path, or null if path traversal above root.
-     */
-    static string canonicalPath(string path) {
-
-      warningf("canonicalPath ...............");
-        if (path.empty)
-            return path;
-
-        bool slash = true;
-        int end = cast(int)path.length;
-        int i = 0;
-
-        loop:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '/':
-                    slash = true;
-                    break;
-
-                case '.':
-                    if (slash)
-                        break loop;
-                    slash = false;
-                    break;
-
-                default:
-                    slash = false;
-            }
-
-            i++;
-        }
-
-        if (i == end)
-            return path;
-
-        StringBuilder canonical = new StringBuilder(path.length);
-        canonical.append(path, 0, i);
-
-        int dots = 1;
-        i++;
-        while (i <= end) {
-            char c = i < end ? path[i] : '\0';
-            switch (c) {
-                case '\0':
-                case '/':
-                    switch (dots) {
-                        case 0:
-                            if (c != '\0')
-                                canonical.append(c);
-                            break;
-
-                        case 1:
-                            break;
-
-                        case 2:
-                            if (canonical.length < 2)
-                                return null;
-                            canonical.setLength(canonical.length - 1);
-                            canonical.setLength(canonical.lastIndexOf("/") + 1);
-                            break;
-
-                        default:
-                            while (dots-- > 0)
-                                canonical.append('.');
-                            if (c != '\0')
-                                canonical.append(c);
-                    }
-
-                    slash = true;
-                    dots = 0;
-                    break;
-
-                case '.':
-                    if (dots > 0)
-                        dots++;
-                    else if (slash)
-                        dots = 1;
-                    else
-                        canonical.append('.');
-                    slash = false;
-                    break;
-
-                default:
-                    while (dots-- > 0)
-                        canonical.append('.');
-                    canonical.append(c);
-                    dots = 0;
-                    slash = false;
-            }
-
-            i++;
-        }
-        return canonical.toString();
-    }
-
-
-    /* ------------------------------------------------------------ */
-
-    /**
-     * Convert a path to a cananonical form.
-     * <p>
-     * All instances of "." and ".." are factored out.
-     * </p>
-     * <p>
-     * Null is returned if the path tries to .. above its root.
-     * </p>
-     *
-     * @param path the path to convert (expects URI/URL form, encoded, and with path separators '/')
-     * @return the canonical path, or null if path traversal above root.
-     */
-    static string canonicalEncodedPath(string path) {
-        if (path.empty)
-            return path;
-        bool slash = true;
-        int end = cast(int)path.length;
-        int i = 0;
-
-        loop:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '/':
-                    slash = true;
-                    break;
-
-                case '.':
-                    if (slash)
-                        break loop;
-                    slash = false;
-                    break;
-
-                case '?':
-                    return path;
-
-                default:
-                    slash = false;
-            }
-
-            i++;
-        }
-
-        if (i == end)
-            return path;
-
-        StringBuilder canonical = new StringBuilder(path.length);
-        canonical.append(path, 0, i);
-
-        int dots = 1;
-        i++;
-        while (i <= end) {
-            char c = i < end ? path[i] : '\0';
-            switch (c) {
-                case '\0':
-                case '/':
-                case '?':
-                    switch (dots) {
-                        case 0:
-                            if (c != '\0')
-                                canonical.append(c);
-                            break;
-
-                        case 1:
-                            if (c == '?')
-                                canonical.append(c);
-                            break;
-
-                        case 2:
-                            if (canonical.length < 2)
-                                return null;
-                            canonical.setLength(canonical.length - 1);
-                            canonical.setLength(canonical.lastIndexOf("/") + 1);
-                            if (c == '?')
-                                canonical.append(c);
-                            break;
-                        default:
-                            while (dots-- > 0)
-                                canonical.append('.');
-                            if (c != '\0')
-                                canonical.append(c);
-                    }
-
-                    slash = true;
-                    dots = 0;
-                    break;
-
-                case '.':
-                    if (dots > 0)
-                        dots++;
-                    else if (slash)
-                        dots = 1;
-                    else
-                        canonical.append('.');
-                    slash = false;
-                    break;
-
-                default:
-                    while (dots-- > 0)
-                        canonical.append('.');
-                    canonical.append(c);
-                    dots = 0;
-                    slash = false;
-            }
-
-            i++;
-        }
-        return canonical.toString();
-    }
-
-
-
-    /* ------------------------------------------------------------ */
-
-    /**
-     * Convert a path to a compact form.
-     * All instances of "//" and "///" etc. are factored out to single "/"
-     *
-     * @param path the path to compact
-     * @return the compacted path
-     */
-    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;
-
-        loop:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '?':
-                    return path;
-                case '/':
-                    state++;
-                    if (state == 2)
-                        break loop;
-                    break;
-                default:
-                    state = 0;
-            }
-            i++;
-        }
-
-        if (state < 2)
-            return path;
-
-        StringBuilder buf = new StringBuilder(path.length);
-        buf.append(path, 0, i);
-
-        loop2:
-        while (i < end) {
-            char c = path[i];
-            switch (c) {
-                case '?':
-                    buf.append(path, i, end);
-                    break loop2;
-                case '/':
-                    if (state++ == 0)
-                        buf.append(c);
-                    break;
-                default:
-                    state = 0;
-                    buf.append(c);
-            }
-            i++;
-        }
-
-        return buf.toString();
-    }
-
-    /* ------------------------------------------------------------ */
-
-    /**
-     * @param uri URI
-     * @return True if the uri has a scheme
-     */
-    static bool hasScheme(string uri) {
-        for (int i = 0; i < uri.length; i++) {
-            char c = uri[i];
-            if (c == ':')
-                return true;
-            if (!(c >= 'a' && c <= 'z' ||
-                    c >= 'A' && c <= 'Z' ||
-                    (i > 0 && (c >= '0' && c <= '9' ||
-                            c == '.' ||
-                            c == '+' ||
-                            c == '-'))
-            ))
-                break;
-        }
-        return false;
-    }
-}

+ 0 - 203
frameworks/D/hunt/pico/http/Parser.d

@@ -1,203 +0,0 @@
-/// Minimalistic low-overhead wrapper for nodejs/http-parser
-/// Used for benchmarks with simple server
-module http.Parser;
-
-
-
-import http.Common;
-
-import hunt.logging.ConsoleLogger;
-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 */
-struct phr_header {
-    const char *name;
-    size_t name_len;
-    const char *value;
-    size_t value_len;
-}
-
-/* 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,
-	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,
-	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,
-	phr_header *headers, size_t *num_headers, size_t last_len);
-
-/* should be zero-filled before start */
-struct phr_chunked_decoder {
-    size_t bytes_left_in_chunk; /* number of bytes left in current chunk */
-    char consume_trailer;       /* if trailing headers should be consumed */
-    char _hex_count;
-    char _state;
-}
-
-/* the function rewrites the buffer given as (buf, bufsz) removing the chunked-
- * encoding headers.  When the function returns without an error, bufsz is
- * updated to the length of the decoded data available.  Applications should
- * repeatedly call the function while it returns -2 (incomplete) every time
- * supplying newly arrived data.  If the end of the chunked-encoded data is
- * found, the function returns a non-negative number indicating the number of
- * octets left undecoded at the tail of the supplied buffer.  Returns -1 on
- * error.
- */
-extern (C) pure @nogc nothrow ptrdiff_t phr_decode_chunked(phr_chunked_decoder *decoder, char *buf, size_t *bufsz);
-
-/* returns if the chunked decoder is in middle of chunked data */
-extern (C) pure @nogc nothrow int phr_decode_chunked_is_in_data(phr_chunked_decoder *decoder);
-
-
-// =========== Public interface starts here =============
-
-public:
-
-class HttpException : Exception {
-	HttpError error;
-
-	pure @nogc nothrow this(HttpError error, string file = __FILE__,
-			size_t line = __LINE__, Throwable nextInChain = null) {
-		this.error = error;
-		super("Http exception", file, line, nextInChain);
-	}
-}
-
-struct HttpParser(Interceptor) {
-
-private {
-	Interceptor interceptor;
-	Throwable failure;
-	phr_header[50] _headers;
-	char *_method;
-	char *path;
-
-	int minor_version;
-	size_t buflen = 0, prevbuflen = 0, method_len, path_len, num_headers;
-}
-
-
-	alias interceptor this;
-
-	this(Interceptor interceptor) {
-		this.interceptor = interceptor;
-	}
-
-	@property bool status() pure @safe nothrow {
-		return failure is null;
-	}
-
-	string uri(bool canCopy=false)() {
-		static if(canCopy) {
-			return cast(string)path[0..path_len].dup;
-		} else {
-			return cast(string)path[0..path_len];
-		}
-	}
-
-	@property HttpMethod method() {
-		string s = cast(string)_method[0..method_len];
-		return to!HttpMethod(s);
-	}
-
-
-	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) {
-				hs[i].name = cast(string)h.name[0..h.name_len].idup;
-				hs[i].value = cast(string)h.value[0..h.value_len].idup;
-			} else {
-				hs[i].name = cast(string)h.name[0..h.name_len];
-				hs[i].value = cast(string)h.value[0..h.value_len];
-			}
-		}
-
-		return hs;
-	}
-
-	@property bool shouldKeepAlive() pure nothrow {
-		return true;
-	}
-
-	@property ushort httpMajor() @safe pure nothrow {
-		return 1;
-	}
-
-	@property ushort httpMinor() @safe pure nothrow {
-		return cast(ushort)minor_version;
-	}
-
-	int execute(const(ubyte)[] str) {
-		return doexecute( str);
-	}
-
-	private int doexecute(const(ubyte)[] chunk) {
-		debug trace(cast(string)chunk);
-
-		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,
-					&path, &path_len,
-					&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 */
-			onMessageComplete();
-
-			if(pret < chunk.length) {
-				debug infof("try to parse next request");
-				pret += doexecute(chunk[pret .. $]); // try to parse next http request data
-			}
-
-			debug infof("pret=%d", pret);
-			return pret;
-		} else if(pret == -2) {
-			debug warning("parsing incomplete");
-			num_headers = 0;
-			debug infof("pret=%d, chunk=%d", pret, chunk.length);
-			return 0;
-		}
-
-		warning("wrong data format");
-		num_headers = 0;
-		failure = new HttpException(HttpError.UNKNOWN);
-		throw failure;
-	}
-
-	void onMessageComplete() {
-		// interceptor.onHeadersComplete();
-		debug {
-			tracef("method is %s", _method[0..method_len]);
-			tracef("path is %s", path[0..path_len]);
-			tracef("HTTP version is 1.%d", minor_version);
-			foreach(ref phr_header h; _headers[0..num_headers]) {
-				tracef("Header: %s = %s", h.name[0..h.name_len], h.value[0..h.value_len]);
-			}
-		}
-		interceptor.onMessageComplete();
-	}
-}
-
-auto httpParser(Interceptor)(Interceptor interceptor) {
-	return HttpParser!Interceptor(interceptor);
-}

+ 0 - 239
frameworks/D/hunt/pico/http/Processor.d

@@ -1,239 +0,0 @@
-/// An example "HTTP server" with poor usability but sensible performance
-///
-module http.Processor;
-
-
-
-import std.conv;
-import std.array, std.exception, std.format, std.algorithm.mutation, std.socket;
-import core.stdc.stdlib;
-import core.thread, core.atomic;
-import http.Parser;
-
-import hunt.collection.ByteBuffer;
-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 hunt.io.IoError;
-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;
-
-	HttpHeader[] headers(bool canCopy=false)() @property {
-		return parser.headers!canCopy();
-	}
-
-	HttpMethod method() @property {
-		return parser.method();
-	}
-
-	string uri(bool canCopy=false)() @property {
-		return parser.uri!(canCopy)();
-	}
-}
-
-//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:
-	HttpHeader[] headers; // buffer for headers
-	Parser parser;
-	HttpRequest request;
-	bool serving;
-
-
-public:
-	TcpStream client;
-
-	this(TcpStream sock) {
-		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.received((ByteBuffer buffer) {
-			version(NO_HTTPPARSER) {
-				client.write(cast(ubyte[])ResponseData);
-			} else {
-				try {
-					int len =  parser.execute(cast(ubyte[]) buffer.getRemaining());
-					buffer.position(buffer.position() + len);
-				} catch(Exception ex) {
-					buffer.clear(); // drop all the  wrong data
-					//respondWith(ex.msg, 500);
-				}
-			}
-		})
-		.closed(() {
-			// notifyClientClosed();
-		})
-		.error((IoError msg) {
-			 warning("Error: ", msg.errorMsg());
-		})
-		.start();
-	}
-
-	protected void notifyClientClosed() {
-		debug tracef("The connection[%s] is closed", client.remoteAddress());
-	}
-
-	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 onChunk(ref HttpRequest req, const(ubyte)[] chunk) {
-		// TODO: Tasks pending completion - 5/16/2019, 5:40:18 PM
-		//
-	}
-
-	void onComplete(ref HttpRequest req);
-
-
-	final int onBody(Parser* parser, const(ubyte)[] chunk) {
-		onChunk(request, chunk);
-		return 0;
-	}
-
-	final int onMessageComplete() {
-		try {
-			onComplete(request);
-		} catch(Exception ex) {
-			//respondWith(ex.msg, 500);
-		}
-		if (!parser.shouldKeepAlive)
-			serving = false;
-		return 0;
-	}
-
-}

+ 0 - 133
frameworks/D/hunt/pico/http/Server.d

@@ -1,133 +0,0 @@
-module http.Server;
-
-
-
-import hunt.event;
-import hunt.io;
-import hunt.logging.ConsoleLogger;
-import hunt.system.Memory : totalCPUs;
-import hunt.util.DateTime;
-
-import std.array;
-import std.conv;
-import std.json;
-import std.socket;
-import std.string;
-import std.stdio;
-
-import http.Parser;
-import http.Processor;
-import hunt.io.channel.Common;
-
-shared static this() {
-	DateTimeHelper.startClock();
-}
-
-
-
-import hunt.io.channel;
-import std.experimental.allocator;
-/**
-*/
-abstract class AbstractTcpServer {
-	protected EventLoopGroup _group = null;
-	protected bool _isStarted = false;
-	protected Address _address;
-	protected int _workersCount;
-	TcpStreamOptions _tcpStreamoption;
-
-	this(Address address, int thread = (totalCPUs - 1), int workersCount = 0) {
-		this._address = address;
-		_tcpStreamoption = TcpStreamOptions.create();
-		_tcpStreamoption.bufferSize = 1024 * 4;
-		_tcpStreamoption.isKeepalive = false;
-		_group = new EventLoopGroup(cast(uint) thread);
-    //_group = theAllocator.make!EventLoopGroup(cast(uint) thread*2);
-		this._workersCount = workersCount;
-    //defaultPoolThreads(thread);
-	}
-
-	@property Address bindingAddress() {
-		return _address;
-	}
-
-	void start() {
-		if (_isStarted)
-			return;
-		_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(_tcpStreamoption.bufferSize);
-		} else {
-			_group.start(_tcpStreamoption.bufferSize);
-		}
-
-		if (_workersCount) {
-			defaultPoolThreads = _workersCount;
-			workerPool(); // Initilize worker poll
-		}
-		writefln("worker count: %d", _workersCount);
-		writefln("IO thread: %d", _group.size);
-
-		while (true) {
-			try {
-				version (HUNT_DEBUG)
-					trace("Waiting for server.accept()");
-
-				Socket socket = server.accept();
-				version (HUNT_DEBUG) {
-					infof("new connection from %s, fd=%d",
-							socket.remoteAddress.toString(), socket.handle());
-				}
-				// EventLoop loop = _group.nextLoop();
-				EventLoop loop = _group.nextLoop(socket.handle);
-        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);
-				break;
-			}
-		}
-		_isStarted = false;
-	}
-
-	protected void onConnectionAccepted(TcpStream client);
-
-	void stop() {
-		if (!_isStarted)
-			return;
-		_isStarted = false;
-		_group.stop();
-	}
-}
-
-alias ProcessorCreater = HttpProcessor delegate(TcpStream client);
-
-/**
-*/
-class HttpServer(T) : AbstractTcpServer if (is(T : HttpProcessor)) {
-
-	this(string ip, ushort port, int thread = (totalCPUs - 1)) {
-		super(theAllocator.make!InternetAddress(ip, port), thread);
-	}
-
-	this(Address address, int thread = (totalCPUs - 1)) {
-		super(address, thread);
-	}
-
-	override protected void onConnectionAccepted(TcpStream client) {
-		//HttpProcessor httpProcessor = new T(client);
-    HttpProcessor httpProcessor = theAllocator.make!T(client);
-		httpProcessor.run();
-	}
-
-}

+ 0 - 362
frameworks/D/hunt/pico/http/UrlEncoded.d

@@ -1,362 +0,0 @@
-module http.UrlEncoded;
-
-
-
-import hunt.collection.List;
-import hunt.collection.MultiMap;
-import hunt.collection.StringBuffer;
-import hunt.Exceptions;
-import hunt.logging;
-import hunt.text.Charset;
-import hunt.text.Common;
-import hunt.text.StringBuilder;
-import hunt.util.TypeUtils;
-
-import std.conv;
-import std.array;
-
-
-/**
- * Handles coding of MIME "x-www-form-urlencoded".
- * <p>
- * This class handles the encoding and decoding for either the query string of a
- * URL or the _content of a POST HTTP request.
- * </p>
- * <b>Notes</b>
- * <p>
- * The UTF-8 charset is assumed, unless otherwise defined by either passing a
- * parameter or setting the "org.hunt.utils.UrlEncoding.charset" System
- * property.
- * </p>
- * <p>
- * The hashtable either contains string single values, vectors of string or
- * arrays of Strings.
- * </p>
- * <p>
- * This class is only partially synchronised. In particular, simple get
- * operations are not protected from concurrent updates.
- * </p>
- *
- * @see java.net.URLEncoder
- */
-class UrlEncoded  : MultiMap!string {
-
-    enum string ENCODING = StandardCharsets.UTF_8;
-
-
-    this() {
-    }
-
-    this(string query) {
-        decodeTo(query, this, ENCODING);
-    }
-
-    void decode(string query) {
-        decodeTo(query, this, ENCODING);
-    }
-
-    void decode(string query, string charset) {
-        decodeTo(query, this, charset);
-    }
-
-    /**
-     * Encode MultiMap with % encoding for UTF8 sequences.
-     *
-     * @return the MultiMap as a string with % encoding
-     */
-    string encode() {
-        return encode(ENCODING, false);
-    }
-
-    /**
-     * Encode MultiMap with % encoding for arbitrary string sequences.
-     *
-     * @param charset the charset to use for encoding
-     * @return the MultiMap as a string encoded with % encodings
-     */
-    string encode(string charset) {
-        return encode(charset, false);
-    }
-
-    /**
-     * Encode MultiMap with % encoding.
-     *
-     * @param charset            the charset to encode with
-     * @param equalsForNullValue if True, then an '=' is always used, even
-     *                           for parameters without a value. e.g. <code>"blah?a=&amp;b=&amp;c="</code>.
-     * @return the MultiMap as a string encoded with % encodings
-     */
-    string encode(string charset, bool equalsForNullValue) {
-        return encode(this, charset, equalsForNullValue);
-    }
-
-    /**
-     * Encode MultiMap with % encoding.
-     *
-     * @param map                the map to encode
-     * @param charset            the charset to use for encoding (uses default encoding if null)
-     * @param equalsForNullValue if True, then an '=' is always used, even
-     *                           for parameters without a value. e.g. <code>"blah?a=&amp;b=&amp;c="</code>.
-     * @return the MultiMap as a string encoded with % encodings.
-     */
-    static string encode(MultiMap!string map, string charset, bool equalsForNullValue) {
-        if (charset is null)
-            charset = ENCODING;
-
-        StringBuilder result = new StringBuilder(128);
-        bool delim = false;
-        foreach(string key, List!string list; map)
-        {
-            int s = list.size();
-
-            if (delim) {
-                result.append('&');
-            }
-
-            if (s == 0) {
-                result.append(encodeString(key, charset));
-                if (equalsForNullValue)
-                    result.append('=');
-            } else {
-                for (int i = 0; i < s; i++) {
-                    if (i > 0)
-                        result.append('&');
-                    string val = list.get(i);
-                    result.append(encodeString(key, charset));
-
-                    if (val != null) {
-                        if (val.length > 0) {
-                            result.append('=');
-                            result.append(encodeString(val, charset));
-                        } else if (equalsForNullValue)
-                            result.append('=');
-                    } else if (equalsForNullValue)
-                        result.append('=');
-                }
-            }
-            delim = true;
-        }
-        return result.toString();
-    }
-
-    /**
-     * Decoded parameters to Map.
-     *
-     * @param content the string containing the encoded parameters
-     * @param map     the MultiMap to put parsed query parameters into
-     * @param charset the charset to use for decoding
-     */
-    static void decodeTo(string content, MultiMap!string map, string charset = ENCODING) {
-        if (charset.empty)
-            charset = ENCODING;
-
-        synchronized (map) {
-            string key = null;
-            string value = null;
-            int mark = -1;
-            bool encoded = false;
-            for (int i = 0; i < content.length; i++) {
-                char c = content[i];
-                switch (c) {
-                    case '&':
-                        int l = i - mark - 1;
-                        value = l == 0 ? "" :
-                                (encoded ? decodeString(content, mark + 1, l) : content.substring(mark + 1, i));
-                        mark = i;
-                        encoded = false;
-                        if (key != null) {
-                            map.add(key, value);
-                        } else if (value != null && value.length > 0) {
-                            map.add(value, "");
-                        }
-                        key = null;
-                        value = null;
-                        break;
-                    case '=':
-                        if (key != null)
-                            break;
-                        key = encoded ? decodeString(content, mark + 1, i - mark - 1) : content.substring(mark + 1, i);
-                        mark = i;
-                        encoded = false;
-                        break;
-                    case '+':
-                        encoded = true;
-                        break;
-                    case '%':
-                        encoded = true;
-                        break;
-                    default: break;
-                }
-            }
-
-            int contentLen = cast(int)content.length;
-
-            if (key != null) {
-                int l =  contentLen - mark - 1;
-                value = l == 0 ? "" : (encoded ? decodeString(content, mark + 1, l) : content.substring(mark + 1));
-                version(HUNT_DEBUG) tracef("key=%s, value=%s", key, value);
-                map.add(key, value);
-            } else if (mark < contentLen) {
-                version(HUNT_DEBUG) tracef("empty value: content=%s, key=%s", content, key);
-                key = encoded
-                        ? decodeString(content, mark + 1, contentLen - mark - 1, charset)
-                        : content.substring(mark + 1);
-                if (!key.empty) {
-                    map.add(key, "");
-                }
-            } else {
-                warningf("No key found.");
-            }
-        }
-    }
-
-    /**
-     * Decode string with % encoding.
-     * This method makes the assumption that the majority of calls
-     * will need no decoding.
-     *
-     * @param encoded the encoded string to decode
-     * @return the decoded string
-     */
-    static string decodeString(string encoded) {
-        return decodeString(encoded, 0, cast(int)encoded.length);
-    }
-
-    /**
-     * Decode string with % encoding.
-     * This method makes the assumption that the majority of calls
-     * will need no decoding.
-     *
-     * @param encoded the encoded string to decode
-     * @param offset  the offset in the encoded string to decode from
-     * @param length  the length of characters in the encoded string to decode
-     * @param charset the charset to use for decoding
-     * @return the decoded 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) {
-                if (buffer is null) {
-                    buffer = new StringBuffer(length);
-                    buffer.append(encoded, offset, offset + i + 1);
-                } else
-                    buffer.append(c);
-            } else if (c == '+') {
-                if (buffer is null) {
-                    buffer = new StringBuffer(length);
-                    buffer.append(encoded, offset, offset + i);
-                }
-
-                buffer.append(' ');
-            } else if (c == '%') {
-                if (buffer is null) {
-                    buffer = new StringBuffer(length);
-                    buffer.append(encoded, offset, offset + i);
-                }
-
-                byte[] ba = new byte[length];
-                int n = 0;
-                while (c >= 0 && c <= 0xff) {
-                    if (c == '%') {
-                        if (i + 2 < length) {
-                            int o = offset + i + 1;
-                            i += 3;
-                           // ba[n] = cast(byte) TypeUtils.parseInt(encoded, o, 2, 16);
-                            n++;
-                        } else {
-                            ba[n++] = cast(byte) '?';
-                            i = length;
-                        }
-                    } else if (c == '+') {
-                        ba[n++] = cast(byte) ' ';
-                        i++;
-                    } else {
-                        ba[n++] = cast(byte) c;
-                        i++;
-                    }
-
-                    if (i >= length)
-                        break;
-                    c = encoded.charAt(offset + i);
-                }
-
-                i--;
-                buffer.append(cast(string)(ba[0 .. n]));
-
-            } else if (buffer !is null)
-                buffer.append(c);
-        }
-
-        if (buffer is null) {
-            if (offset == 0 && encoded.length == length)
-                return encoded;
-            return encoded.substring(offset, offset + length);
-        }
-
-        return buffer.toString();
-    }
-
-
-    /**
-     * Perform URL encoding.
-     *
-     * @param string the string to encode
-     * @return encoded string.
-     */
-    static string encodeString(string string) {
-        return encodeString(string, ENCODING);
-    }
-
-    /**
-     * Perform URL encoding.
-     *
-     * @param string  the string to encode
-     * @param charset the charset to use for encoding
-     * @return encoded string.
-     */
-    static string encodeString(string str, string charset) {
-        if (charset is null)
-            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;
-        bool noEncode = true;
-
-        for (int i = 0; i < len; i++) {
-            byte b = bytes[i];
-
-            if (b == ' ') {
-                noEncode = false;
-                encoded[n++] = cast(byte) '+';
-            } else if (b >= 'a' && b <= 'z' ||
-                    b >= 'A' && b <= 'Z' ||
-                    b >= '0' && b <= '9') {
-                encoded[n++] = b;
-            } else {
-                noEncode = false;
-                encoded[n++] = cast(byte) '%';
-                byte nibble = cast(byte) ((b & 0xf0) >> 4);
-                if (nibble >= 10)
-                    encoded[n++] = cast(byte) ('A' + nibble - 10);
-                else
-                    encoded[n++] = cast(byte) ('0' + nibble);
-                nibble = cast(byte) (b & 0xf);
-                if (nibble >= 10)
-                    encoded[n++] = cast(byte) ('A' + nibble - 10);
-                else
-                    encoded[n++] = cast(byte) ('0' + nibble);
-            }
-        }
-
-        if (noEncode)
-            return str;
-
-        return cast(string)(encoded[0 .. n]);
-    }
-}