1 /*
2  * Hunt - A high-level D Programming Language Web framework that encourages rapid development and clean, pragmatic design.
3  *
4  * Copyright (C) 2015-2019, HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.framework.config.ApplicationConfig;
13 
14 import hunt.framework.Init;
15 import hunt.framework.auth.AuthOptions;
16 
17 import std.exception;
18 import std.format;
19 import std.parallelism : totalCPUs;
20 import std.process;
21 import std.socket : Address, parseAddress;
22 import std.string;
23 
24 import hunt.http.MultipartOptions;
25 import hunt.logging.ConsoleLogger;
26 import hunt.util.Configuration;
27 
28 
29 // @Configuration("hunt")
30 @ConfigurationFile("application")
31 class ApplicationConfig {
32     struct ApplicationConf {
33         string name = "Hunt Application";
34         string baseUrl = "http://localhost:8080";
35         string defaultCookieDomain = "localhost";
36         string defaultLanguage = "en-US";
37         string languages = "zh-CN,en-US";
38         string secret = "CD6CABB1123C86EDAD9";
39         string encoding = "utf-8";
40         int staticFileCacheMinutes = 30;
41         string langLocation = "./translations";
42     }
43 
44     struct AuthConf {
45         string loginUrl = "/";
46         string successUrl = "/";
47         string unauthorizedUrl = "";
48 
49         string basicRealm = "Secure Area";
50 
51         // AuthenticationScheme: basic, bear/jwt
52         string guardScheme = "jwt";
53 
54         // the max inactive interval. The time unit is second.
55         int tokenExpiration = DEFAULT_TOKEN_EXPIRATION*24*60*60; 
56         
57         int shiroTokenExpiration = 30*1000;
58     }
59 
60     /** Config for static files */
61     struct StaticFilesConf {
62         bool enabled = true;
63         // default root path
64         string location = DEFAULT_STATIC_FILES_LACATION;
65         bool canList = true;
66         int cacheTime = 30;
67     }
68     
69     struct CacheConf {
70         string adapter = "memory";
71         string prefix = "";
72 
73         bool useSecondLevelCache = false;
74         uint maxEntriesLocalHeap = 10000;
75         bool eternal = false;
76         uint timeToIdleSeconds = 3600;
77         uint timeToLiveSeconds = 10;
78         bool overflowToDisk = true;
79         bool diskPersistent = true;
80         uint diskExpiryThreadIntervalSeconds = 120;
81         uint maxEntriesLocalDisk = 10000;
82     }
83 
84     struct CookieConf {
85         string domain = "";
86         string path = "/";
87         int expires = 3600;
88         bool secure = false;
89         bool httpOnly = true;
90     }
91 
92     struct SessionConf {
93         // string storage = "memory";
94         // string args = "/tmp";
95         string prefix = "huntsession_";
96         uint expire = 3600; // in seconds
97     }
98 
99     struct HttpConf {
100         string address = "0.0.0.0";
101         string path = DEFAULT_STATIC_FILES_LACATION;
102         ushort port = 8080;
103         uint workerThreads = 4;
104         uint ioThreads = 2;
105         size_t keepAliveTimeOut = 30;
106         size_t maxHeaderSize = 64 * 1024;
107         int cacheControl;
108         bool enableCors = false; // CORS support
109         string allowOrigin = "*";
110         string allowMethods = "*";
111         string allowHeaders = "*";
112         // DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
113     }
114 
115     struct HttpsConf {
116         bool enabled = false;
117         string protocol;
118         string keyStore;
119         string keyStoreType;
120         string keyStorePassword;
121     }
122 
123     struct RouteConf {
124         RouteGroupConfig[] groups;
125     }
126 
127     struct LoggingConfig {
128         string level = "all";
129         string path;
130         string file = "";
131         bool disableConsole = false;
132         string maxSize = "8M";
133         uint maxNum = 8;
134     }
135 
136     // struct MemcacheConf {
137     //     bool enabled = false;
138     //     string servers;
139     // }
140 
141     struct RedisConf {
142         bool enabled = false;
143         string host = "127.0.0.1";
144         string password = "";
145         ushort database = 0;
146         ushort port = 6379;
147         uint timeout = 5000;
148         RedisPoolConf pool;
149         RedisClusterConf cluster;
150     }
151 
152     struct RedisPoolConf {
153         bool enabled = false;
154 
155         bool blockOnExhausted = true;
156         uint idleTimeout = 30000; // millisecond
157         uint maxPoolSize = 20;
158         uint minPoolSize = 5;
159         uint maxLifetime = 2000000;
160         uint connectionTimeout = 15000;
161         int waitTimeout = 15000; // -1: forever
162         uint maxConnection = 20;
163         uint minConnection = 5;        
164     }
165 
166     struct RedisClusterConf {
167         bool enabled = false;
168         string[] nodes;
169         uint redirections = 5;
170     }
171 
172     struct QueueConf {
173         bool enabled = false;
174         // Drivers: "memeory", "redis", "null"
175         string driver = null;
176     }
177 
178     struct TaskConf {
179         bool enabled = false;
180         uint workerThreads = 4;
181     }
182 
183     struct GrpcConf {
184         GrpcServerConf server;
185         GrpcClientConf[] clientChannels;
186     }
187 
188     struct UploadConf {
189         string path = "/tmp";
190         long maxSize = 4 * 1024 * 1024;
191     }
192 
193     struct MailSmtpConf {
194         string host;
195         string channel;
196         ushort port;
197         string protocol;
198         string user;
199         string password;
200     }
201 
202     struct MailConf {
203         MailSmtpConf smtp;
204     }
205 
206     struct DbPoolConf {
207         string name = "";
208         int minIdle = 5;
209         int idleTimeout = 30000;
210         int maxPoolSize = 20;
211         int minPoolSize = 5;
212         int maxLifetime = 2000000;
213         int connectionTimeout = 30000;
214         int maxConnection = 20;
215         int minConnection = 5;
216     }
217 
218     struct DatabaseConf {
219         
220         string url() {
221             string s = format("%s://%s:%s@%s:%d/%s?prefix=%s&charset=%s",
222                     driver, username, password, host, port, database, prefix, charset);
223             return s;
224         }
225 
226         string driver = "postgresql";
227         string host = "localhost";
228         ushort port = 5432;
229         string database = "test";
230         string username = "root";
231         string password = "";
232         string charset = "utf8";
233         string prefix = "";
234         bool enabled = false;
235 
236         DbPoolConf pool;
237     }
238 
239     struct DateConf {
240         string format;
241         string timeZone;
242     }
243 
244     struct CornConf {
245         string noon;
246     }
247 
248     struct ServiceConf {
249         string address = "127.0.0.1";
250         ushort port = 8080;
251         int workerThreads = 2;
252         string password;
253     }
254 
255     struct RpcConf {
256         bool enabled = true;
257         ServiceConf service;
258     }
259 
260     struct View {
261         string path = "./resources/views/";
262         string ext = ".html";
263         uint arrayDepth = 3;
264     }
265 
266     struct TraceConf {
267         bool enable = false;
268         bool b3Required = true;
269         TraceService service;
270         string zipkin = "http://127.0.0.1:9411/api/v2/spans";
271     }
272 
273     struct TraceService {
274         string host;
275         ushort port;
276     }
277 
278     DatabaseConf database;
279     ApplicationConf application;
280     AuthConf auth;
281     StaticFilesConf staticfiles;
282     CookieConf cookie;
283     SessionConf session;
284     CacheConf cache;
285     HttpConf http;
286     HttpsConf https;
287     RouteConf route;
288     QueueConf queue;
289     TaskConf task;
290     RedisConf redis;
291     GrpcConf grpc;
292     LoggingConfig logging;
293     UploadConf upload;
294     CornConf cron;
295     DateConf date;
296     MailConf mail;
297     RpcConf rpc;
298     View view;
299     TraceConf trace;
300 
301     MultipartOptions multipartConfig() {
302         if (_multipartConfig is null) {
303             string path = buildPath(DEFAULT_TEMP_PATH, upload.path);
304             if (!path.exists()) {
305                 // for Exception now?
306                 path.mkdirRecurse();
307             }
308             _multipartConfig = new MultipartOptions(path, upload.maxSize, upload.maxSize, 50);
309         }
310         return _multipartConfig;
311     }
312 
313     private MultipartOptions _multipartConfig;
314 
315     this() {
316         http.workerThreads = totalCPUs * 4;
317         http.ioThreads = totalCPUs;
318         task.workerThreads = totalCPUs;
319         upload.path = DEFAULT_TEMP_PATH;
320         view.path = DEFAULT_TEMPLATE_PATH;
321         application.langLocation = DEFAULT_LANGUAGE_PATH;
322     }
323 }
324 
325 /**
326  * 
327  */
328 struct GrpcServerConf {
329     bool enabled = false;
330     uint workerThreads = 4;
331     string host = "127.0.0.1";
332     ushort port = 50051;
333 }
334 
335 /**
336  * 
337  */
338 struct GrpcClientConf {
339     string name="unnamed";
340     string host = "127.0.0.1";
341     ushort port = 50051;
342     uint timeout = 15000;
343 }
344 
345 /**
346  * 
347  */
348 struct RouteGroupConfig {
349     string name;
350     string type;
351     string value;
352 }
353 
354 
355 import core.sync.rwmutex;
356 
357 import std.array;
358 import std.file;
359 import std.path;
360 import std.exception : basicExceptionCtors;
361 
362 /** 
363  * 
364  */
365 class ConfigNotFoundException : Exception {
366     mixin basicExceptionCtors;
367 }
368 
369 // ConfigManager configManager() {
370 //     return _manger;
371 // }
372 
373 // shared static this() {
374 //     _manger = new ConfigManager();
375 // }
376 
377 // private:
378 // __gshared ConfigManager _manger;