1 module websocketd.request; 2 3 import std.conv : to; 4 import std.ascii : isWhite; 5 import std.algorithm : endsWith; 6 7 struct Request { 8 string method; 9 string path; 10 string httpVersion; 11 string[string] headers; 12 string message; 13 bool done = false; 14 15 static Request parse(ubyte[] bytes) { 16 static ubyte[] data = []; 17 static Request req = Request(); 18 19 data ~= bytes; 20 string message = (cast(char[])data).to!string; 21 if (!message.endsWith("\r\n\r\n")) 22 return req; 23 24 size_t i = 0; 25 string token = ""; 26 27 // get method 28 for (; i < message.length; i++) { 29 if (message[i] == ' ') 30 break; 31 token ~= message[i]; 32 } 33 i++; // skip whitespace 34 req.method = token; 35 token = ""; 36 37 // get path 38 for (; i < message.length; i++) { 39 if (message[i] == ' ') 40 break; 41 token ~= message[i]; 42 } 43 i++; 44 req.path = token; 45 token = ""; 46 47 // get version 48 for (; i < message.length; i++) { 49 if (message[i] == '\r') 50 break; 51 token ~= message[i]; 52 } 53 i++; // skip \r 54 if (message[i] != '\n') 55 return req; 56 i++; 57 req.httpVersion = token; 58 token = ""; 59 60 // get headers 61 string key = ""; 62 for (; i < message.length; i++) { 63 token = ""; 64 key = ""; 65 if (message[i] == '\r') 66 break; 67 for (; i < message.length; i++) { 68 if (message[i] == ':' || message[i].isWhite) 69 break; 70 token ~= message[i]; 71 } 72 i++; 73 key = token; 74 token = ""; 75 for (; i < message.length; i++) 76 if (!message[i].isWhite) 77 break; // ignore whitespace 78 for (; i < message.length; i++) { 79 if (message[i] == '\r') 80 break; 81 token ~= message[i]; 82 } 83 i++; 84 if (message[i] != '\n') 85 return req; 86 req.headers[key] = token; 87 } 88 89 i++; 90 if (message[i] != '\n') 91 return req; 92 i++; 93 94 req.message = message[i .. $]; 95 req.done = true; 96 Request ans = req; 97 req = Request.init; 98 data = []; 99 return ans; 100 } 101 }