1 /**
2 * Copyright © Yurai Web Framework 2021
3 * License: MIT (https://github.com/YuraiWeb/yurai/blob/main/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 */
6 module yurai.controllers.controller;
7 
8 import yurai.core;
9 import yurai.controllers.status;
10 import yurai.controllers.controlleraction;
11 import yurai.controllers.controlleractionset;
12 import yurai.external.iserver;
13 
14 ///
15 public class Controller
16 {
17   private:
18   IHttpRequest _request;
19   IHttpResponse _response;
20   IServer _server;
21   ControllerActionSet[string] _actions;
22 
23   void createMissingActionSet(string method)
24   {
25     import std.string : toLower;
26 
27     method = method.toLower;
28 
29     if (method !in _actions)
30     {
31       _actions[method] = new ControllerActionSet;
32     }
33   }
34 
35   public:
36   this(IHttpRequest request, IHttpResponse response)
37   {
38     _request = request;
39     _response = response;
40     _server = _request.server;
41   }
42 
43   final:
44   @property
45   {
46     IHttpRequest request() { return _request; }
47 
48     IHttpResponse response() { return _response; }
49 
50     IServer server() { return _server; }
51   }
52 
53   void mapMandatoryAction(string method, ControllerAction action)
54   {
55     import std.string : toLower;
56 
57     createMissingActionSet(method);
58 
59     _actions[method.toLower].mandatoryAction = action;
60   }
61 
62   void mapDefaultAction(string method, ControllerAction action)
63   {
64     import std.string : toLower;
65 
66     createMissingActionSet(method);
67 
68     _actions[method.toLower].defaultAction = action;
69   }
70 
71   void mapRoutedAction(string method, string name, ControllerAction action)
72   {
73     import std.string : toLower;
74 
75     createMissingActionSet(method);
76 
77     _actions[method.toLower].mapRoutedAction(name.toLower, action);
78   }
79 
80   Status json(T)(T o, bool pretty = true)
81   {
82     auto s = serializeJson(o, pretty);
83 
84     return jsonString(s);
85   }
86 
87   Status jsonString(string jsonString)
88   {
89     response.contentType = "application/json; charset=UTF-8";
90 
91     response.writeBody(jsonString);
92 
93     return Status.end;
94   }
95 
96   Status handle()
97   {
98     string actionRoute;
99 
100     if (_request.path.length < 2)
101     {
102       actionRoute = "/";
103     }
104     else
105     {
106       actionRoute = _request.path[1];
107     }
108 
109     if (!_actions)
110     {
111       return Status.notFound;
112     }
113 
114     import std.string : toLower;
115 
116     auto methodActions = _actions.get(_request.method.toLower, null);
117 
118     if (!methodActions)
119     {
120       return Status.notFound;
121     }
122 
123     if (methodActions.mandatoryAction)
124     {
125       ControllerAction mandatoryAction = methodActions.mandatoryAction;
126       Status mandatoryResult = mandatoryAction();
127 
128       if (mandatoryResult != Status.success)
129       {
130         return mandatoryResult;
131       }
132     }
133 
134     if (actionRoute == "/" && methodActions.defaultAction)
135     {
136       ControllerAction defaultAction = methodActions.defaultAction;
137       Status defaultResult = defaultAction();
138 
139       return defaultResult;
140     }
141 
142     ControllerAction routedAction = methodActions.getRoutedAction(actionRoute);
143 
144     if (routedAction)
145     {
146       Status routedResult = routedAction();
147 
148       return routedResult;
149     }
150 
151     return Status.notFound;
152   }
153 }