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;
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 = -1; // seconds
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 canUpgrade = true;
109         bool enableCors = false; // CORS support
110         string allowOrigin = "*";
111         string allowMethods = "*";
112         string allowHeaders = "*";
113         // DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
114     }
115 
116     struct HttpsConf {
117         bool enabled = false;
118         string protocol;
119         string keyStore;
120         string keyStoreType;
121         string keyStorePassword;
122     }
123 
124     struct RouteConf {
125         RouteGroupConfig[] groups;
126     }
127 
128     struct LoggingConfig {
129         string level = "all";
130         string path;
131         string file = "";
132         bool disableConsole = false;
133         string maxSize = "8M";
134         uint maxNum = 8;
135     }
136 
137     // struct MemcacheConf {
138     //     bool enabled = false;
139     //     string servers;
140     // }
141 
142     struct RedisConf {
143         bool enabled = false;
144         string host = "127.0.0.1";
145         string password = "";
146         ushort database = 0;
147         ushort port = 6379;
148         uint timeout = 5000;
149         RedisPoolConf pool;
150         RedisClusterConf cluster;
151     }
152 
153     struct RedisPoolConf {
154         bool enabled = false;
155 
156         int maxWaitQueueSize = -1;
157         uint idleTimeout = 30000; // millisecond
158         uint maxPoolSize = 20;
159         uint minPoolSize = 5;
160         uint maxLifetime = 2000000;
161         uint connectionTimeout = 15000;
162         int waitTimeout = 15000; // -1: forever
163         uint maxConnection = 20;
164         uint minConnection = 5;        
165     }
166 
167     struct RedisClusterConf {
168         bool enabled = false;
169         string[] nodes;
170         uint redirections = 5;
171     }
172 
173     struct QueueConf {
174         bool enabled = false;
175         // Drivers: "memeory", "redis", "null"
176         string driver = null;
177     }
178 
179     struct TaskConf {
180         bool enabled = false;
181         uint workerThreads = 4;
182     }
183 
184     struct GrpcConf {
185         GrpcServerConf server;
186         GrpcClientConf[] clientChannels;
187     }
188 
189     struct UploadConf {
190         string path = "/tmp";
191         long maxSize = 4 * 1024 * 1024;
192     }
193 
194     struct MailSmtpConf {
195         string host;
196         string channel;
197         ushort port;
198         string protocol;
199         string user;
200         string password;
201     }
202 
203     struct MailConf {
204         MailSmtpConf smtp;
205     }
206 
207     struct DbPoolConf {
208         string name = "";
209         int minIdle = 5;
210         int idleTimeout = 30000;
211         int maxPoolSize = 20;
212         int minPoolSize = 5;
213         int maxLifetime = 2000000;
214         int connectionTimeout = 30000;
215         int maxConnection = 20;
216         int minConnection = 5;
217         int maxWaitQueueSize = -1;
218     }
219 
220     struct DatabaseConf {
221         
222         string url() {
223             string s = format("%s://%s:%s@%s:%d/%s?prefix=%s&charset=%s",
224                     driver, username, password, host, port, database, prefix, charset);
225             return s;
226         }
227 
228         string driver = "postgresql";
229         string host = "localhost";
230         ushort port = 5432;
231         string database = "test";
232         string username = "root";
233         string password = "";
234         string charset = "utf8";
235         string prefix = "";
236         bool enabled = false;
237 
238         DbPoolConf pool;
239     }
240 
241     struct DateConf {
242         string format;
243         string timeZone;
244     }
245 
246     struct CornConf {
247         string noon;
248     }
249 
250     struct ServiceConf {
251         string address = "127.0.0.1";
252         ushort port = 8080;
253         int workerThreads = 2;
254         string password;
255     }
256 
257     struct RpcConf {
258         bool enabled = true;
259         ServiceConf service;
260     }
261 
262     struct View {
263         string path = "./resources/views/";
264         string ext = ".html";
265         uint arrayDepth = 3;
266     }
267 
268     struct TraceConf {
269         bool enable = false;
270         bool b3Required = true;
271         TraceService service;
272         string zipkin = "http://127.0.0.1:9411/api/v2/spans";
273     }
274 
275     struct TraceService {
276         string host;
277         ushort port;
278     }
279 
280     DatabaseConf database;
281     ApplicationConf application;
282     AuthConf auth;
283     StaticFilesConf staticfiles;
284     CookieConf cookie;
285     SessionConf session;
286     CacheConf cache;
287     HttpConf http;
288     HttpsConf https;
289     RouteConf route;
290     QueueConf queue;
291     TaskConf task;
292     RedisConf redis;
293     GrpcConf grpc;
294     LoggingConfig logging;
295     UploadConf upload;
296     CornConf cron;
297     DateConf date;
298     MailConf mail;
299     RpcConf rpc;
300     View view;
301     TraceConf trace;
302 
303     // MultipartOptions multipartConfig() {
304     //     if (_multipartConfig is null) {
305     //         string path = buildPath(DEFAULT_TEMP_PATH, upload.path);
306     //         if (!path.exists()) {
307     //             // for Exception now?
308     //             path.mkdirRecurse();
309     //         }
310     //         _multipartConfig = new MultipartOptions(path, upload.maxSize, upload.maxSize, 50);
311     //     }
312     //     return _multipartConfig;
313     // }
314 
315     // private MultipartOptions _multipartConfig;
316 
317     this() {
318         http.workerThreads = totalCPUs * 4;
319         http.ioThreads = totalCPUs;
320         task.workerThreads = totalCPUs;
321         upload.path = DEFAULT_TEMP_PATH;
322         view.path = DEFAULT_TEMPLATE_PATH;
323         application.langLocation = DEFAULT_LANGUAGE_PATH;
324     }
325 }
326 
327 /**
328  * 
329  */
330 struct GrpcServerConf {
331     bool enabled = false;
332     uint workerThreads = 4;
333     string host = "127.0.0.1";
334     ushort port = 50051;
335 }
336 
337 /**
338  * 
339  */
340 struct GrpcClientConf {
341     string name="unnamed";
342     string host = "127.0.0.1";
343     ushort port = 50051;
344     uint timeout = 15000;
345 }
346 
347 /**
348  * 
349  */
350 struct RouteGroupConfig {
351     string name;
352     string type;
353     string value;
354     string guard = DEFAULT_GURAD_NAME;
355 }
356 
357 
358 import core.sync.rwmutex;
359 
360 import std.array;
361 import std.file;
362 import std.path;
363 import std.exception : basicExceptionCtors;
364 
365 /** 
366  * 
367  */
368 class ConfigNotFoundException : Exception {
369     mixin basicExceptionCtors;
370 }
371 
372 // ConfigManager configManager() {
373 //     return _manger;
374 // }
375 
376 // shared static this() {
377 //     _manger = new ConfigManager();
378 // }
379 
380 // private:
381 // __gshared ConfigManager _manger;