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