1 module arsd.xmlhttp; 2 3 // UNTESTED 4 5 // the idea here is to provide http functionality simulating the browser's interface for some potential code sharing 6 7 /+ 8 9 import arsd.cgi; 10 import arsd.dom; 11 12 enum ReadyState { 13 UNSENT = 0, 14 OPENED = 1, 15 HEADERS_RECEIVED = 2, 16 LOADING = 3, 17 DONE = 4 18 } 19 20 class XMLHttpRequest { 21 HTTP http; 22 23 void open(string method, string url, bool async = false, string user = null, string password = null) { 24 import std.string; 25 26 http = HTTP(url); 27 http.method = to!(HTTP.Method)(method.toLower()); 28 if(user !is null) 29 http.setAuthentication(user, password); 30 } 31 32 void send(in void[] data = null) { 33 http.perform(); 34 } 35 36 void send(FormData data) { 37 setRequestHeader("Content-Type", "multipart/form-data; boundary=" ~ data.boundary); 38 send(data.toBytes()); 39 } 40 41 void setRequestHeader(string header, string value) { 42 43 } 44 45 void overrideMimeType(string mime) { 46 47 } 48 49 void abort() {} 50 string getAllResponseHeaders() {} 51 string getResponssHeader(string name) {} 52 53 // Dynamic response; 54 string responseText; 55 Document responseXML; 56 int status; 57 string statusText; 58 59 string responseType; // settable 60 ulong timeout; // settable 61 // upload??????? 62 bool withCredentials; 63 64 ReadyState readyState; 65 onreadystatechange 66 } 67 68 +/ 69 70 // see also: arsd.cgi.encodeVariables 71 /// Creates a multipart/form-data object that is suitable for file uploads and other kinds of POST 72 class FormData { 73 struct MimePart { 74 string name; 75 const(void)[] data; 76 string contentType; 77 string filename; 78 } 79 80 MimePart[] parts; 81 82 void append(string key, in void[] value, string contentType = null, string filename = null) { 83 parts ~= MimePart(key, value, contentType, filename); 84 } 85 86 private string boundary = "0016e64be86203dd36047610926a"; // FIXME 87 88 ubyte[] toBytes() { 89 string data; 90 91 foreach(part; parts) { 92 data ~= "--" ~ boundary ~ "\r\n"; 93 data ~= "Content-Disposition: form-data; name=\""~part.name~"\""; 94 if(part.filename !is null) 95 data ~= "; filename=\""~part.filename~"\""; 96 data ~= "\r\n"; 97 if(part.contentType !is null) 98 data ~= "Content-Type: " ~ part.contentType ~ "\r\n"; 99 data ~= "\r\n"; 100 101 data ~= cast(string) part.data; 102 103 data ~= "\r\n"; 104 } 105 106 data ~= "--" ~ boundary ~ "--\r\n"; 107 108 return cast(ubyte[]) data; 109 } 110 } 111 112 void main() { 113 auto data = new FormData(); 114 data.append("archive", "YOUR DATA", "application/octet-stream", "arbitrary_filename"); 115 116 import std.stdio; 117 writeln(cast(string) data.toBytes()); 118 }