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 text(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 		this.send();
93 	}
94 }
95 public struct Header{
96 	string Name;
97 	string Value;
98 }
99 
100 Request parseRequest(char[] buffer){
101 	Request req = new Request();
102 	string raw_path;
103 	char[] Name;
104 	char[] Value;
105 	ubyte mode; // 0 - name; 1 - value
106 	string rawtext = text(buffer);
107 	string[] raw = rawtext.split("\r\n");
108 	req.Method = raw[0].split(' ')[0];
109 	req.Path = raw[0].split(' ')[1].split("?")[0];
110 	raw_path = raw[0].split(' ')[1];
111 	string[] raw_ = raw[1 .. raw.length];
112 	uint last = 0;
113 	for(uint i = 0; i < raw_.length; i++){
114 		string raw_str = raw_[i];
115 		if(raw_str == ""){
116 			last = i + 1;
117 			break;
118 		}
119 		string[] s = raw_str.split(": ");
120 		if(s.length > 1){
121 			Header header;
122 			header.Name = s[0];
123 			header.Value = s[1];
124 			req.Headers ~= [header];
125 		}
126 	}
127 	if(last != 0){
128 		req.Body = raw_[last .. raw_.length].join("\r\n");
129 		if(req.Method == "GET" && raw_path.split("?").length > 1){
130 			string[] val = raw_path.split("?")[1].split("&");
131 
132 			foreach(v; val){
133 				string[] keyval = v.split("=");
134 				if(keyval.length <= 1){
135 					req.Params[keyval[0]] = "";
136 				}
137 				else if(keyval.length > 1){
138 					req.Params[keyval[0]] = keyval[1];
139 				}
140 			}
141 		}
142 	}
143 
144 	return req;
145 }
146 
147 
148 
149 bool containsKeyAssoc(TKey, TValue)(TKey need, TValue[TKey] arr){
150 	foreach(pair; arr.byPair){
151 		if(pair.key == need)
152 			return true;
153 	}
154 	return false;
155 }
156