1 /*
2  * Archttp - A highly performant web framework written in D.
3  *
4  * Copyright (C) 2021-2022 Kerisy.com
5  *
6  * Website: https://www.kerisy.com
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module archttp.HttpRequest;
13 
14 import geario.logging;
15 
16 import archttp.Url;
17 import archttp.HttpContext;
18 import archttp.HttpHeader;
19 import archttp.HttpRequestHandler;
20 
21 public import archttp.HttpMethod;
22 public import archttp.MultiPart;
23 
24 import std.uni : toLower;
25 
26 class HttpRequest
27 {
28     private
29     {
30         HttpMethod     _method;
31         Url            _uri;
32         string         _path;
33         string         _httpVersion = "HTTP/1.1";
34         string[string] _headers;
35         string         _body;
36 
37         HttpContext    _httpContext;
38         string[string] _cookies;
39         bool           _cookiesParsed;
40     }
41 
42     public
43     {
44         // string[string] query;
45         string[string] params;
46         string[string] fields;
47         MultiPart[] files;
48         HttpRequestMiddlewareHandler[] middlewareHandlers;
49     }
50 
51 public:
52 
53     ~ this()
54     {
55         reset();
56     }
57 
58     HttpRequest context(HttpContext context)
59     {
60         _httpContext = context;
61         return this;
62     }
63 
64     void method(HttpMethod method)
65     {
66         _method = method;
67     }
68 
69     void uri(Url uri)
70     {
71         _uri = uri;
72         _path = _uri.path;
73     }
74 
75     void path(string path)
76     {
77         _path = path;
78     }
79 
80     string ip()
81     {
82         return _httpContext.connection().RemoteAddress().toAddrString();
83     }
84 
85     string[string] cookies()
86     {
87         parseCookieWhenNeeded();
88 
89         return _cookies;
90     }
91 
92     string cookie(T = string)(string name)
93     {
94         import std.conv : to;
95 
96         parseCookieWhenNeeded();
97 
98         return _cookies.get(name, "").to!T;
99     }
100 
101     void parseCookieWhenNeeded()
102     {
103         if (_cookiesParsed)
104             return;
105 
106         _cookiesParsed = true;
107     
108 		string cookieString = header(HttpHeader.COOKIE);
109         
110         if (!cookieString.length)
111             return;
112         
113         import std.array : split;
114         import std.uri : decodeComponent;
115         import std.string : strip;
116         
117         foreach (part; cookieString.split(";"))
118         {
119             auto c = part.split("=");
120             _cookies[decodeComponent(c[0].strip)] = decodeComponent(c[1]);
121         }
122     }
123 
124     HttpRequest httpVersion(string httpVersion)
125     {
126         _httpVersion = httpVersion;
127         return this;
128     }
129 
130     HttpRequest header(string header, string value)
131     {
132         _headers[header.toLower] = value;
133         return this;
134     }
135 
136     HttpRequest body(string body)
137     {
138         _body = body;
139         return this;
140     }
141 
142     Url uri()
143     {
144         return _uri;
145     }
146 
147     string path()
148     {
149         return _path;
150     }
151 
152     HttpMethod method()
153     {
154         return _method;
155     }
156 
157     string httpVersion()
158     {
159         return _httpVersion;
160     }
161 
162     string header(string name)
163     {
164         return _headers.get(name.toLower, "");
165     }
166 
167     string[string] headers()
168     {
169         return _headers;
170     }
171 
172     string body()
173     {
174         return _body;
175     }
176 
177     string query(string key)
178     {
179         return _uri.queryParams[key].front;
180     }
181 
182     string param(string key)
183     {
184         return params.get(key, "");
185     }
186 
187     void reset()
188     {
189         _headers = null;
190         _body = null;
191         _httpVersion = null;
192         _cookies = null;
193         _cookiesParsed = false;
194 
195         // query = null;
196         params = null;
197         fields = null;
198         files = null;
199     }
200 }