app.d 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. //import vibe.vibe;
  2. // https://github.com/vibe-d/vibe.d/blob/master/source/vibe/vibe.d
  3. import vibe.core.core;
  4. import vibe.http.router;
  5. import vibe.http.server;
  6. import vibe.http.fileserver;
  7. import vibe.http.websockets;
  8. import vibe.core.log;
  9. import std.stdio;
  10. import std.string;
  11. //import std.array;
  12. import memcached4d;
  13. import std.conv : to;
  14. import tr;
  15. import mustache;
  16. alias MustacheEngine!(string) Mustache;
  17. import vibe.db.postgresql;
  18. import vibe.data.bson;
  19. //import vibe.data.json;
  20. // https://github.com/vibe-d/vibe.d/blob/master/source/vibe/vibe.d
  21. PostgresClient client;
  22. import std.file : read;
  23. import toml;
  24. TOMLDocument toml_s;
  25. /* test unproper arguments order */
  26. /* do not */
  27. /*
  28. alias test_key1 = int;
  29. alias test_key2 = int;
  30. string test_args_types_mismash(test_key1 x, test_key2 y){
  31. return ( to!string(x) ~ " + " ~ to!string(y) ~ " = " ~ to!string( x + y ) );
  32. }
  33. */
  34. /* do not */
  35. /*
  36. import std.typecons : Typedef;
  37. alias test_key5 = Typedef!int;
  38. alias test_key6 = Typedef!int;
  39. string test_args_types_mismash(test_key5 x, test_key6 y){
  40. return ( to!string(x) ~ " + " ~ to!string(y) ~ " = " ~ to!string( x + y ) );
  41. }
  42. */
  43. /* do like */
  44. import std.typecons : Typedef;
  45. alias test_key5 = Typedef!(int, int.init, "key5");
  46. alias test_key6 = Typedef!(int, int.init, "key6");
  47. string test_args_types_mismash(test_key5 x, test_key6 y){
  48. return ( to!string(x) ~ " + " ~ to!string(y) ~ " = " ~ to!string( x + y ) );
  49. }
  50. /* or - do like */
  51. struct test_key3 { int v; }
  52. struct test_key4 { int v; }
  53. string test_args_types_mismash2(test_key3 x, test_key4 y){
  54. return ( to!string(x.v) ~ " + " ~ to!string(y.v) ~ " = " ~ to!string( x.v + y.v ) );
  55. }
  56. void main(){
  57. auto settings = new HTTPServerSettings;
  58. settings.port = 8080;
  59. settings.bindAddresses = ["::1", "127.0.0.1"];
  60. //auto fsettings = new HTTPFileServerSettings;
  61. //fsettings.serverPathPrefix = "/static";
  62. auto router = new URLRouter;
  63. //router.get("/", &index);
  64. ////router.get("static/*", serverStaticFiles("public/", fsettings) );
  65. //router.get("/", staticTemplate!"index.html");
  66. router.get("/", serveStaticFile("public/index.html") );
  67. router.get("/ws", handleWebSockets(&ws_handle) );
  68. router.get("/test", &test);
  69. router.get("*", serveStaticFiles("public/"));
  70. //auto listener = listenHTTP(settings, &hello);
  71. auto listener = listenHTTP(settings, router);
  72. scope (exit){
  73. listener.stopListening();
  74. }
  75. logInfo("Please open http://127.0.0.1:8080/ in your browser.");
  76. runApplication();
  77. }
  78. void ws_handle(scope WebSocket sock){
  79. // simple echo server + :)
  80. while(sock.connected){
  81. auto msg = sock.receiveText();
  82. sock.send(msg ~ " :)");
  83. }
  84. }
  85. /*
  86. void index(HTTPServerRequest req, HTTPServerResponse res){
  87. res.writeBody("Hello, World!");
  88. }
  89. */
  90. /*
  91. void hello(HTTPServerRequest req, HTTPServerResponse res){
  92. res.writeBody("Hello, World!");
  93. }
  94. */
  95. string s_toml_db = "database";
  96. string s_toml_db_host = "host";
  97. string s_toml_db_port = "port";
  98. string s_toml_db_name = "dbname";
  99. string s_toml_db_user = "user";
  100. string s_toml_db_pass = "pass";
  101. string s_toml_db_conn_timeout = "connect_timeout";
  102. string s_toml_db_conn_num = "connections_number";
  103. bool are_valid_config_values(ref TOMLDocument toml_s){
  104. string invalid_settings = "invalid settings: ";
  105. string grumpy = " :(";
  106. string invalid_group = " group ";
  107. string invalid_key = " key" ~ grumpy;
  108. bool invalid_toml_group(string group){
  109. writeln(invalid_settings ~ group ~ invalid_group ~ grumpy); return false;
  110. }
  111. bool invalid_toml_value(string group, string key){
  112. writeln(invalid_settings ~ group ~ invalid_group ~ key ~ invalid_key ~ grumpy); return false;
  113. }
  114. if((s_toml_db in toml_s) != null){
  115. auto toml_db = toml_s[s_toml_db];
  116. if((s_toml_db_host in toml_db) != null){
  117. if(toml_db[s_toml_db_host].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_host); }
  118. }else{ return invalid_toml_value(s_toml_db, s_toml_db_host); }
  119. if((s_toml_db_port in toml_db) != null){
  120. if(toml_db[s_toml_db_port].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_port); }
  121. }else{ return invalid_toml_value(s_toml_db, s_toml_db_port); }
  122. if((s_toml_db_name in toml_db) != null){
  123. if(toml_db[s_toml_db_name].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_name); }
  124. }else{ return invalid_toml_value(s_toml_db, s_toml_db_name); }
  125. if((s_toml_db_user in toml_db) != null){
  126. if(toml_db[s_toml_db_user].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_user); }
  127. }else{ return invalid_toml_value(s_toml_db, s_toml_db_user); }
  128. if((s_toml_db_pass in toml_db) != null){
  129. if(toml_db[s_toml_db_pass].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_pass); }
  130. }else{ return invalid_toml_value(s_toml_db, s_toml_db_pass); }
  131. if((s_toml_db_conn_timeout in toml_db) != null){
  132. if(toml_db[s_toml_db_conn_timeout].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_conn_timeout); }
  133. }else{ return invalid_toml_value(s_toml_db, s_toml_db_conn_timeout); }
  134. if((s_toml_db_conn_num in toml_db) != null){
  135. if(toml_db[s_toml_db_conn_num].type == TOMLType.INTEGER){}else{ return invalid_toml_value(s_toml_db, s_toml_db_conn_num); }
  136. }else{ return invalid_toml_value(s_toml_db, s_toml_db_conn_num); }
  137. }else{ return invalid_toml_group(s_toml_db); }
  138. return true;
  139. }
  140. void test_pg_conn_driver(){
  141. client.pickConnection( (scope conn){
  142. immutable result = conn.execStatement(
  143. "SELECT 123 as first_num, 567 as second_num, 'abc'::text as third_text " ~
  144. "UNION ALL " ~
  145. "SELECT 890, 233, 'fgh'::text as third_text",
  146. ValueFormat.BINARY
  147. );
  148. assert(result[0]["second_num"].as!PGinteger == 567);
  149. assert(result[1]["third_text"].as!PGtext == "fgh");
  150. foreach (val; rangify(result[0])){
  151. writeln("Found entry: ", val.as!Bson.toJson);
  152. }
  153. } );
  154. }
  155. void test(HTTPServerRequest req, HTTPServerResponse res){
  156. auto cache = memcachedConnect("127.0.0.1:11211");
  157. /* test unproper arguments order */
  158. /* do not */
  159. /*
  160. test_key1 x = 5;
  161. test_key2 y = 2;
  162. //string r1 = test_args_types_mismash(x, y); // proper arguments order
  163. string r1 = test_args_types_mismash(y, x); // unproper - this compiles but we got logic error bug in runtime.. :( use struct for compiler check this..
  164. writeln("r1 = ", r1);
  165. */
  166. /* do not */
  167. /*
  168. test_key5 x = 5;
  169. test_key6 y = 2;
  170. //string r3 = test_args_types_mismash(x, y); // proper arguments order
  171. string r3 = test_args_types_mismash(y, x); // unproper - this compiles but we got logic error bug in runtime.. :( use struct for compiler check this..
  172. writeln("r3 = ", r3);
  173. */
  174. /* do like */
  175. test_key5 x = 5;
  176. test_key6 y = 2;
  177. string r3 = test_args_types_mismash(x, y); // proper arguments order
  178. //string r3 = test_args_types_mismash(y, x); // unproper - this not compiles
  179. writeln("r3 = ", r3);
  180. /* or - do like */
  181. test_key3 x2 = test_key3(5);
  182. test_key4 y2 = test_key4(2);
  183. string r2 = test_args_types_mismash2(x2, y2); // proper arguments order
  184. //string r2 = test_args_types_mismash2(y2, x2); // unproper - this not compiles
  185. writeln("r2 = ", r2);
  186. Language Lang = Language.uk;
  187. writeln("tr 1 = ", Tr(Lang, TKey.hello));
  188. writeln("tr 2 = ", Tr(Lang, TKey.welcome, ["username"], 0) );
  189. writeln("tr 3 = ", Tr(Lang, TKey.apples, [], 1) );
  190. writeln("tr 3 = ", Tr(Lang, TKey.apples, [], 2) ) ;
  191. writeln("tr 3 = ", Tr(Lang, TKey.apples, [], 5) );
  192. writeln("tr 4 = ", Tr(Lang, TKey.apples_n_oranges, ["6", "7"], 0) );
  193. writeln("get test1 = ", cache.get!string("test1"));
  194. string v1 = "value1 = 🔥🦀";
  195. if(cache.store("test1", v1) == RETURN_STATE.SUCCESS ){
  196. writeln("stored successfully");
  197. writeln("get stored: ", cache.get!string("test1") );
  198. }else{
  199. writeln("not stored");
  200. }
  201. string result = cache.get!string("test1");
  202. writeln("get test1 = ", result);
  203. writeln(cache.del("test1"));
  204. toml_s = parseTOML(cast(string)read("settings.toml"));
  205. if( are_valid_config_values(toml_s) ){}else{ return; }
  206. // https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING
  207. // https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
  208. //client = new PostgresClient("host=localhost port=5432 dbname=mydb user=username password=pass connect_timeout=5", 100);
  209. client = new PostgresClient( "host=" ~ toml_s[s_toml_db][s_toml_db_host].str() ~
  210. " port=" ~ toml_s[s_toml_db][s_toml_db_port].str() ~
  211. " dbname=" ~ toml_s[s_toml_db][s_toml_db_name].str() ~
  212. " user=" ~ toml_s[s_toml_db][s_toml_db_user].str() ~
  213. " password=" ~ toml_s[s_toml_db][s_toml_db_pass].str() ~
  214. " connect_timeout=" ~ toml_s[s_toml_db][s_toml_db_conn_timeout].str(),
  215. cast(uint) toml_s[s_toml_db][s_toml_db_conn_num].integer() );
  216. test_pg_conn_driver();
  217. Mustache mustache2;
  218. auto context2 = new Mustache.Context;
  219. mustache2.path = "priv/folder2";
  220. mustache2.ext = "dtl";
  221. context2["param2"] = "blah blah blah ";
  222. Mustache mustache;
  223. auto context = new Mustache.Context;
  224. mustache.path = "priv";
  225. mustache.ext = "dtl";
  226. //context.useSection("boolean");
  227. //assert(mustache.renderString(" {{#boolean}}YES{{/boolean}}\n {{#boolean}}GOOD{{/boolean}}\n", context) == " YES\n GOOD\n");
  228. //{{escaped_html_tags}}
  229. //{{{not_escaped_html_tags}}}
  230. //{{#repo}}<b>{{name}}</b>{{/repo}}
  231. //{{^repo}}No repos :({{/repo}}
  232. // to
  233. //No repos :(
  234. context["lang"] = "en";
  235. context["number1"] = 42;
  236. context.useSection("maybe1");
  237. context["part1"] = mustache2.render("part1", context2);
  238. context["result1"] = "Hello, World!\n" ~ result;
  239. res.headers["Content-Type"] = "text/html; charset=utf-8";
  240. //res.writeBody("Hello, World!\n" ~ result);
  241. res.writeBody( mustache.render("main", context) );
  242. }