1 module dweb.utils;
2 
3 import std.conv;
4 import std.array;
5 import std.stdio;
6 import std.socket;
7 import dweb.view_engine : Options;
8 import dweb.server : HttpServer;
9 
10 public class Request{
11 	public string Method;
12 	public string Path;
13 	public string[string] Params;
14 	public string Body;
15 	public Header[] Headers;
16 }
17 
18 public class Response{
19 	private string Status;
20 	private Socket client;
21 	private Header[string] Headers;
22 	private char[] Body;
23 	public bool isSended;
24 	private HttpServer server;
25 	this(Socket client, HttpServer server){
26 		this.Status = "200 OK";
27 		this.client = client;
28 		this.Body = [];
29 		this.isSended = false;
30 		this.server = server;
31 	}
32 	public void setHeader(string Name, string Value){
33 		Header header;
34 		header.Name = Name;
35 		header.Value = Value;
36 		this.Headers[Name] = header;
37 	}
38 	public void setStatus(int status){
39 		this.Status = status.to!string();
40 	}
41 	public void write(string val){
42 		this.Body ~= val;
43 	}
44 	public void fhtml(string name){
45 		Header head;
46 		head.Name = "Content-Type";
47 		head.Value = "text/html; charset=utf-8";
48 		this.Headers[head.Name] = head;
49 		auto f = File(name, "r");
50 		string str;
51 		f.readf!"%s"(str);
52 		this.Body ~= str;
53 		f.close();
54 	}
55 	public void send(){
56 		char[] data = this.serializeResponse();
57 		ptrdiff_t sended = this.client.sendTo(data);
58 		this.isSended = true;
59 	}
60 	public void send(string b){
61 		this.Body ~= b.dup;
62 		char[] data = this.serializeResponse();
63 		ptrdiff_t sended = this.client.sendTo(data);
64 		this.isSended = true;
65 	}
66 	public void send(int b){
67 		this.Status = b.to!string();
68 		char[] data = this.serializeResponse();
69 		ptrdiff_t sended = this.client.sendTo(data);
70 		this.isSended = true;
71 	}
72 	private char[] serializeResponse(){
73 		string text = "HTTP/1.1 " ~ this.Status ~ "\r\n";
74 		Header head;
75 		head.Name = "Content-Length";
76 		head.Value ~= this.Body.length.to!string();
77 		this.Headers[head.Name] = head;
78 		
79 		foreach(header; this.Headers){
80 			text ~= header.Name ~ ": " ~ header.Value ~ "\r\n";
81 		}
82 		text ~= "\r\n";
83 		text ~= this.Body;
84 
85 		char[] res = cast(char[])text;
86 		return res;
87 	}
88 	public void render(string data, Options options = null){
89 		if(options !is null)
90 			this.server.view_engine.setOptions(options);
91 		this.Body ~= this.server.view_engine.render(data);
92 	}
93 	public void frender(string filename, Options options = null){
94 		if(options !is null)
95 			this.server.view_engine.setOptions(options);
96 		auto f = File(filename, "r");
97 		
98 		string str;
99 		f.readf!"%s"(str);
100 		f.close();
101 
102 		this.Body ~= this.server.view_engine.render(str);
103 	}
104 }
105 public struct Header{
106 	string Name;
107 	string Value;
108 }
109 
110 Request parseRequest(char[] buffer){
111 	Request req = new Request();
112 	string raw_path;
113 	char[] Name;
114 	char[] Value;
115 	ubyte mode; // 0 - name; 1 - value
116 	string rawtext = text(buffer);
117 	string[] raw = rawtext.split("\r\n");
118 	req.Method = raw[0].split(' ')[0];
119 	req.Path = raw[0].split(' ')[1].split("?")[0];
120 	raw_path = raw[0].split(' ')[1];
121 	string[] raw_ = raw[1 .. raw.length];
122 	uint last = 0;
123 	for(uint i = 0; i < raw_.length; i++){
124 		string raw_str = raw_[i];
125 		if(raw_str == ""){
126 			last = i + 1;
127 			break;
128 		}
129 		string[] s = raw_str.split(": ");
130 		if(s.length > 1){
131 			Header header;
132 			header.Name = s[0];
133 			header.Value = s[1];
134 			req.Headers ~= [header];
135 		}
136 	}
137 	if(last != 0){
138 		req.Body = raw_[last .. raw_.length].join("\r\n");
139 		if(req.Method == "GET" && raw_path.split("?").length > 1){
140 			string[] val = raw_path.split("?")[1].split("&");
141 
142 			foreach(v; val){
143 				string[] keyval = v.split("=");
144 				if(keyval.length <= 1){
145 					req.Params[keyval[0]] = "";
146 				}
147 				else if(keyval.length > 1){
148 					req.Params[keyval[0]] = keyval[1];
149 				}
150 			}
151 		}
152 	}
153 
154 	return req;
155 }
156 
157 
158 
159 bool containsKeyAssoc(TKey, TValue)(TKey need, TValue[TKey] arr){
160 	foreach(pair; arr.byPair){
161 		if(pair.key == need)
162 			return true;
163 	}
164 	return false;
165 }
166