1 module hunt.http.routing.impl.RoutingContextImpl;
2 
3 import hunt.http.routing.impl.RouterImpl;
4 
5 import hunt.http.routing.handler;
6 import hunt.http.routing.Router;
7 import hunt.http.routing.RouterManager;
8 import hunt.http.routing.RoutingContext;
9 
10 import hunt.http.HttpConnection;
11 import hunt.http.HttpMetaData;
12 import hunt.http.HttpOutputStream;
13 
14 import hunt.http.server.HttpServerContext;
15 import hunt.http.server.HttpServerRequest;
16 import hunt.http.server.HttpServerResponse;
17 import hunt.http.server.HttpSession;
18 
19 import hunt.collection;
20 import hunt.concurrency.Promise;
21 import hunt.Exceptions;
22 import hunt.Functions;
23 import hunt.io.BufferUtils;
24 import hunt.logging;
25 import hunt.stream.Common;
26 import hunt.util.Common;
27 
28 import std.algorithm;
29 import std.container;
30 import std.string;
31 import std.variant;
32 
33 /**
34  * 
35  */
36 class RoutingContextImpl : RoutingContext {
37     private HttpServerRequest request;
38     private NavigableSet!(RouterMatchResult) routers;
39     private RouterMatchResult current;
40     private HttpSessionHandler httpSessionHandler;
41     private Variant[string] _attributes;
42     // private TemplateHandlerSPI templateHandlerSPI = TemplateHandlerSPILoader.getInstance().getTemplateHandlerSPI();
43     private bool asynchronousRead = false;
44     // private  ConcurrentLinkedDeque<Promise<?>> handlerPromiseQueue;
45     private HttpServerContext _context;
46     private string _groupName = "default";
47 
48     this(HttpServerContext context, NavigableSet!(RouterMatchResult) routers) {
49         _context = context;
50         request = _context.httpRequest();
51         this.routers = routers;
52     }
53 
54     override Variant getAttribute(string key) {
55         return _attributes.get(key, Variant());
56     }
57 
58     override void setAttribute(string key, Variant value) {
59         _attributes[key] = value;
60     }
61 
62     override Variant removeAttribute(string key) {
63         Variant v = _attributes[key];
64         _attributes.remove(key);
65         return v;
66     }
67 
68     override Variant[string] getAttributes() {
69         return _attributes;
70     }
71 
72     override HttpServerRequest getRequest() {
73         return request;
74     }
75 
76     override HttpServerResponse getResponse() {
77         return _context.httpResponse();
78     }
79 
80     override void response(HttpServerResponse response) {
81         _context.httpResponse = response;
82     }
83 
84     // override
85     // HttpResponse getAsyncResponse() {
86     //     return request.getAsyncResponse();
87     // }
88 
89     override OutputStream outputStream() {
90         return _context.outputStream();
91     }
92 
93     override string getRouterParameter(string name) {
94         if(current is null) {
95             throw new Exception("Call next() first.");
96         }
97         return current.getParameters().get(name);
98     }
99 
100     // override
101     // RoutingContext onContent(Action1!ByteBuffer handler) {
102     //     getRequest().onContent(handler);
103     //     asynchronousRead = true;
104     //     return this;
105     // }
106 
107     // override
108     // RoutingContext onContentComplete(Action1!HttpRequest handler) {
109     //     getRequest().onContentComplete(handler);
110     //     asynchronousRead = true;
111     //     return this;
112     // }
113 
114     // override
115     // RoutingContext onMessageComplete(Action1!HttpRequest handler) {
116     //     getRequest().onMessageComplete(handler);
117     //     asynchronousRead = true;
118     //     return this;
119     // }
120 
121     override bool isAsynchronousRead() {
122         return asynchronousRead;
123     }
124 
125     override void enableAsynchronousRead() {
126         asynchronousRead = true;
127     }
128 
129     override void next() {
130         current = routers.pollFirst();
131         if (current is null) {
132             version(HUNT_HTTP_DEBUG) warning("No router found.");
133             return;
134         }
135 
136         Router r = current.getRouter();
137         version (HUNT_HTTP_DEBUG) {
138             infof("current router: %d", r.getId());
139         }
140 
141         Map!(string, string) routeParameters = current.getParameters();
142         if(routeParameters !is null) {
143             foreach(string key, string value; routeParameters) {
144                 // if(key.startsWith("param")) continue;
145                 version(HUNT_HTTP_DEBUG) tracef("Adding route parameters, name=%s, value=%s", key, value);
146                 request.putQueryParameter(key, value);
147             }
148         }
149 
150         r.handle(this);
151         return;
152     }
153 
154     override bool hasNext() {
155         return !routers.isEmpty();
156     }
157 
158     // override
159     // <T> RoutingContext complete(Promise<T> promise) {
160     //     ConcurrentLinkedDeque<Promise<T>> queue = createHandlerPromiseQueueIfAbsent();
161     //     queue.push(promise);
162     //     return this;
163     // }
164 
165     // override
166     // <T> bool next(Promise<T> promise) {
167     //     return complete(promise).next();
168     // }
169 
170     // override
171     // <T> void succeed(T t) {
172     //     Optional.ofNullable(handlerPromiseQueue)
173     //             .map(ConcurrentLinkedDeque::pop)
174     //             .map(p -> (Promise<T>) p)
175     //             .ifPresent(p -> p.succeeded(t));
176     // }
177 
178     // override
179     // void fail(Throwable x) {
180     //     Optional.ofNullable(handlerPromiseQueue)
181     //             .map(ConcurrentLinkedDeque::pop)
182     //             .ifPresent(p -> p.failed(x));
183     // }
184 
185     // private <T> ConcurrentLinkedDeque<Promise<T>> createHandlerPromiseQueueIfAbsent() {
186     //     if (handlerPromiseQueue == null) {
187     //         handlerPromiseQueue = new ConcurrentLinkedDeque<>();
188     //     }
189     //     return (ConcurrentLinkedDeque) handlerPromiseQueue;
190     // }
191 
192     override HttpConnection httpConnection() {
193         return _context.connection();
194     }
195 
196     override int getConnectionId() {
197         return _context.getConnectionId();
198     }
199 
200     void close() {
201         _context.end();
202     }
203 
204     override string getParameter(string name) {
205         // if(httpRequestBody is null) {
206         //     return null;
207         // } else {
208         //     return httpRequestBody.getParameter(name);
209         // }
210         return getRequest().getParameter(name);
211     }
212 
213     override List!string getParameterValues(string name) {
214         // if(httpRequestBody is null)
215         //     return new EmptyList!string();
216         // else
217         //     return httpRequestBody.getParameterValues(name);
218         return getRequest().getParameterValues(name);
219     }
220 
221     override Map!(string, List!string) getParameterMap() {
222         // if(httpRequestBody is null)
223         //     return null;
224         // else
225         //     return httpRequestBody.getParameterMap();
226 
227         return getRequest().getParameterMap();
228     }
229 
230     // override
231     // Collection!Part getParts() {
232     //     // return Optional.ofNullable(httpRequestBody)
233     //     //                .map(HttpServerRequest::getParts)
234     //     //                .orElse(Collections.emptyList());
235     //     if(httpRequestBody is null)
236     //         return null;
237     //     else
238     //         return httpRequestBody.getParts();
239     // }
240 
241     // override
242     // Part getPart(string name) {
243     //     // return Optional.ofNullable(httpRequestBody)
244     //     //                .map(s -> s.getPart(name))
245     //     //                .orElse(null);
246     //     if(httpRequestBody is null)
247     //         return null;
248     //     else
249     //         return httpRequestBody.getPart(name);
250     // }
251 
252     // override
253     // InputStream getInputStream() {
254     //     return Optional.ofNullable(httpRequestBody)
255     //                    .map(HttpServerRequest::getInputStream)
256     //                    .orElse(null);
257     // }
258 
259     // override
260     // BufferedReader getBufferedReader() {
261     //     return Optional.ofNullable(httpRequestBody)
262     //                    .map(HttpServerRequest::getBufferedReader)
263     //                    .orElse(null);
264     // }
265 
266     override string getStringBody(string charset) {
267         // if(httpRequestBody is null)
268         //     return request.getStringBody(charset);
269         // else
270         //     return httpRequestBody.getStringBody(charset);
271 
272         return getRequest().getStringBody(charset);
273     }
274 
275     override string getStringBody() {
276         // if(httpRequestBody is null)
277         //     return request.getStringBody();
278         // else
279         //     return httpRequestBody.getStringBody();
280         return getRequest().getStringBody();
281     }
282 
283     // override
284     // <T> T getJsonBody(Class<T> clazz) {
285     //     return Optional.ofNullable(httpRequestBody)
286     //                    .map(s -> s.getJsonBody(clazz))
287     //                    .orElseGet(() -> request.getJsonBody(clazz));
288     // }
289 
290     // override
291     // <T> T getJsonBody(GenericTypeReference<T> typeReference) {
292     //     return Optional.ofNullable(httpRequestBody)
293     //                    .map(s -> s.getJsonBody(typeReference))
294     //                    .orElseGet(() -> request.getJsonBody(typeReference));
295 
296     // }
297 
298     // override
299     // JsonObject getJsonObjectBody() {
300     //     return Optional.ofNullable(httpRequestBody)
301     //                    .map(HttpServerRequest::getJsonObjectBody)
302     //                    .orElseGet(request::getJsonObjectBody);
303     // }
304 
305     // override
306     // JsonArray getJsonArrayBody() {
307     //     return Optional.ofNullable(httpRequestBody)
308     //                    .map(HttpServerRequest::getJsonArrayBody)
309     //                    .orElseGet(request::getJsonArrayBody);
310     // }
311 
312     // override void setHttpBody(HttpServerRequest requestBody) {
313     //     this.httpRequestBody = requestBody;
314     // }
315 
316     override HttpSession getSessionById(string id) {
317         if (httpSessionHandler is null) {
318             return null;
319         } else {
320             return httpSessionHandler.getSessionById(id);
321         }
322     }
323 
324     override HttpSession getSession() {
325         if (httpSessionHandler is null) {
326             return null;
327         } else {
328             return httpSessionHandler.getSession();
329         }
330     }
331 
332     override HttpSession getSession(bool create) {
333         if (httpSessionHandler is null) {
334             return null;
335         } else {
336             return httpSessionHandler.getSession(create);
337         }
338     }
339 
340     override HttpSession getAndCreateSession(int maxAge) {
341         if (httpSessionHandler is null) {
342             return null;
343         } else {
344             return httpSessionHandler.getAndCreateSession(maxAge);
345         }
346     }
347 
348     override int getSessionSize() {
349         if (httpSessionHandler is null) {
350             return 0;
351         } else {
352             return httpSessionHandler.getSessionSize();
353         }
354     }
355 
356     override bool removeSessionById(string id) {
357         if (httpSessionHandler is null) {
358             return false;
359         } else {
360             return httpSessionHandler.removeSessionById(id);
361         }
362     }
363 
364     override bool removeSession() {
365         if (httpSessionHandler is null) {
366             return false;
367         } else {
368             return httpSessionHandler.removeSession;
369         }
370     }
371 
372     override bool updateSession(HttpSession httpSession) {
373         if (httpSessionHandler is null) {
374             return false;
375         } else {
376             return httpSessionHandler.updateSession(httpSession);
377         }
378     }
379 
380     override bool isRequestedSessionIdFromURL() {
381         if (httpSessionHandler is null) {
382             return false;
383         } else {
384             return httpSessionHandler.isRequestedSessionIdFromURL();
385         }
386     }
387 
388     override bool isRequestedSessionIdFromCookie() {
389         if (httpSessionHandler is null) {
390             return false;
391         } else {
392             return httpSessionHandler.isRequestedSessionIdFromCookie();
393         }
394     }
395 
396     override string getRequestedSessionId() {
397         if (httpSessionHandler is null) {
398             return null;
399         } else {
400             return httpSessionHandler.getRequestedSessionId();
401         }
402     }
403 
404     override string getSessionIdParameterName() {
405         if (httpSessionHandler is null) {
406             return null;
407         } else {
408             return httpSessionHandler.getSessionIdParameterName();
409         }
410     }
411 
412     void setHttpSessionHandler(HttpSessionHandler httpSessionHandler) {
413         this.httpSessionHandler = httpSessionHandler;
414     }
415 
416     // override
417     // void renderTemplate(string resourceName, Object scope) {
418     //     templateHandlerSPI.renderTemplate(this, resourceName, scope);
419     // }
420 
421     // override
422     // void renderTemplate(string resourceName, Object[] scopes) {
423     //     templateHandlerSPI.renderTemplate(this, resourceName, scopes);
424     // }
425 
426     // override
427     // void renderTemplate(string resourceName, List<Object> scopes) {
428     //     templateHandlerSPI.renderTemplate(this, resourceName, scopes);
429     // }
430 
431     override RoutingContext write(string value) {
432         _context.write(value);
433         return this;
434     }
435 
436     override RoutingContext write(byte[] b, int off, int len) {
437         _context.write(b, off, len);
438         return this;
439     }
440 
441     override RoutingContext end() {
442         _context.end();
443         return this;
444     }
445 
446     override void flush() {
447         _context.flush();
448     }
449 
450     override bool isCommitted() {
451         return _context.isCommitted();
452     }
453 
454     override string groupName() {
455         return _groupName;
456     }
457     
458     override void groupName(string name) {
459         _groupName = name;
460     }
461 }