Request

This is simplest interface to both http and ftp protocols. Request has methods get, post and exec which routed to proper concrete handler (http or ftp, etc). To enable some protocol-specific featutes you have to use protocol interface directly (see docs for HTTPRequest or FTPRequest)

Members

Functions

exec
Response exec(A args)
Undocumented in source. Be warned that the author may not have intended to support it.
get
Response get(string uri, A args)

Execute GET for http and retrieve file for FTP. You have to provide at least uri. All other arguments should conform to HTTPRequest.get or FTPRequest.get depending on the URI scheme. When arguments do not conform scheme (for example you try to call get("ftp://somehost.net/pub/README", {"a":"b"}) which doesn't make sense) you will receive Exception("Operation not supported for ftp")

post
Response post(string uri, A args)

Execute POST for http and STOR file for FTP. You have to provide uri and data. Data should conform to HTTPRequest.post or FTPRequest.post depending on the URI scheme. When arguments do not conform scheme you will receive Exception("Operation not supported for ftp")

Properties

authenticator
Auth authenticator [@property setter]

Set authenticator for http requests. v - Auth instance.

bufferSize
size_t bufferSize [@property setter]

Set IO buffer size for http and ftp requests v - buffer size in bytes.

contentLength
long contentLength [@property getter]
Undocumented in source. Be warned that the author may not have intended to support it.
contentReceived
long contentReceived [@property getter]
Undocumented in source. Be warned that the author may not have intended to support it.
cookie
Cookie[] cookie [@property setter]

Set Cookie for http requests. v - array of cookie.

cookie
Cookie[] cookie [@property getter]

Get Cookie for http requests. v - array of cookie.

keepAlive
bool keepAlive [@property setter]

Set http keepAlive value v - use keepalive requests - true, or not - false

maxContentLength
size_t maxContentLength [@property setter]

Set maximum content lenth both for http and ftp requests v - maximum content length in bytes. When limit reached - throw RequestException

maxHeadersLength
size_t maxHeadersLength [@property setter]

Set maximum length for HTTP headers v - maximum length of the HTTP response. When limit reached - throw RequestException

maxRedirects
uint maxRedirects [@property setter]

Set limit on HTTP redirects v - limit on redirect depth

timeout
Duration timeout [@property setter]

Set timeout on IO operation. v - timeout value

useStreaming
bool useStreaming [@property setter]
Undocumented in source. Be warned that the author may not have intended to support it.
verbosity
uint verbosity [@property setter]

Set verbosity for HTTP or FTP requests. v - verbosity level (0 - no output, 1 - headers to stdout, 2 - headers and body progress to stdout). default = 0.

Examples

1 import std.algorithm;
2 import std.range;
3 import std.array;
4 import std.json;
5 import std.stdio;
6 import std.string;
7 import std.exception;
8 
9 globalLogLevel(LogLevel.info);
10 
11 infof("testing Request");
12 Request rq;
13 Response rs;
14 //
15 rs = rq.get("https://httpbin.org/");
16 assert(rs.code==200);
17 assert(rs.responseBody.length > 0);
18 rs = rq.get("http://httpbin.org/get", ["c":" d", "a":"b"]);
19 assert(rs.code == 200);
20 auto json = parseJSON(rs.responseBody.data).object["args"].object;
21 assert(json["c"].str == " d");
22 assert(json["a"].str == "b");
23 
24 globalLogLevel(LogLevel.info);
25 rq = Request();
26 rq.keepAlive = true;
27 // handmade json
28 info("Check POST json");
29 rs = rq.post("http://httpbin.org/post?b=x", `{"a":"☺ ", "c":[1,2,3]}`, "application/json");
30 assert(rs.code==200);
31 json = parseJSON(rs.responseBody.data).object["args"].object;
32 assert(json["b"].str == "x");
33 json = parseJSON(rs.responseBody.data).object["json"].object;
34 assert(json["a"].str == "☺ ");
35 assert(json["c"].array.map!(a=>a.integer).array == [1,2,3]);
36 {
37     import std.file;
38     import std.path;
39     auto tmpd = tempDir();
40     auto tmpfname = tmpd ~ dirSeparator ~ "request_test.txt";
41     auto f = File(tmpfname, "wb");
42     f.rawWrite("abcdefgh\n12345678\n");
43     f.close();
44     // files
45     globalLogLevel(LogLevel.info);
46     info("Check POST files");
47     PostFile[] files = [
48     {fileName: tmpfname, fieldName:"abc", contentType:"application/octet-stream"}, 
49     {fileName: tmpfname}
50     ];
51     rs = rq.post("http://httpbin.org/post", files);
52     assert(rs.code==200);
53     info("Check POST chunked from file.byChunk");
54     f = File(tmpfname, "rb");
55     rs = rq.post("http://httpbin.org/post", f.byChunk(3), "application/octet-stream");
56     assert(rs.code==200);
57     auto data = parseJSON(rs.responseBody.data).object["data"].str;
58     assert(data=="abcdefgh\n12345678\n");
59     f.close();
60 }
61 {
62     // string
63     info("Check POST utf8 string");
64     rs = rq.post("http://httpbin.org/post", "привiт, свiт!", "application/octet-stream");
65     assert(rs.code==200);
66     auto data = parseJSON(rs.responseBody.data).object["data"].str;
67     assert(data=="привiт, свiт!");
68 }
69 // ranges
70 {
71     info("Check POST chunked from lineSplitter");
72     auto s = lineSplitter("one,\ntwo,\nthree.");
73     rs = rq.exec!"POST"("http://httpbin.org/post", s, "application/octet-stream");
74     assert(rs.code==200);
75     auto data = parseJSON(rs.responseBody.toString).object["data"].str;
76     assert(data=="one,two,three.");
77 }
78 {
79     info("Check POST chunked from array");
80     auto s = ["one,", "two,", "three."];
81     rs = rq.post("http://httpbin.org/post", s, "application/octet-stream");
82     assert(rs.code==200);
83     auto data = parseJSON(rs.responseBody.data).object["data"].str;
84     assert(data=="one,two,three.");
85 }
86 {
87     info("Check POST chunked using std.range.chunks()");
88     auto s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
89     rs = rq.post("http://httpbin.org/post", s.representation.chunks(10), "application/octet-stream");
90     assert(rs.code==200);
91     auto data = parseJSON(rs.responseBody.data).object["data"].str;
92     assert(data==s);
93 }
94 // associative array
95 rs = rq.post("http://httpbin.org/post", ["a":"b ", "c":"d"]);
96 assert(rs.code==200);
97 auto form = parseJSON(rs.responseBody.data).object["form"].object;
98 assert(form["a"].str == "b ");
99 assert(form["c"].str == "d");
100 info("Check HEAD");
101 rs = rq.exec!"HEAD"("http://httpbin.org/");
102 assert(rs.code==200);
103 info("Check DELETE");
104 rs = rq.exec!"DELETE"("http://httpbin.org/delete");
105 assert(rs.code==200);
106 info("Check PUT");
107 rs = rq.exec!"PUT"("http://httpbin.org/put",  `{"a":"b", "c":[1,2,3]}`, "application/json");
108 assert(rs.code==200);
109 info("Check PATCH");
110 rs = rq.exec!"PATCH"("http://httpbin.org/patch", "привiт, свiт!", "application/octet-stream");
111 assert(rs.code==200);
112 
113 info("Check compressed content");
114 globalLogLevel(LogLevel.info);
115 rq = Request();
116 rq.keepAlive = true;
117 rs = rq.get("http://httpbin.org/gzip");
118 assert(rs.code==200);
119 info("gzip - ok");
120 rs = rq.get("http://httpbin.org/deflate");
121 assert(rs.code==200);
122 info("deflate - ok");
123 
124 info("Check redirects");
125 globalLogLevel(LogLevel.info);
126 rq = Request();
127 rq.keepAlive = true;
128 rs = rq.get("http://httpbin.org/relative-redirect/2");
129 assert((cast(HTTPResponse)rs).history.length == 2);
130 assert((cast(HTTPResponse)rs).code==200);
131 
132 info("Check cookie");
133 rq = Request();
134 rs = rq.get("http://httpbin.org/cookies/set?A=abcd&b=cdef");
135 assert(rs.code == 200);
136 json = parseJSON(rs.responseBody.data).object["cookies"].object;
137 assert(json["A"].str == "abcd");
138 assert(json["b"].str == "cdef");
139 auto cookie = rq.cookie();
140 foreach(c; rq.cookie) {
141     final switch(c.attr) {
142         case "A":
143             assert(c.value == "abcd");
144             break;
145         case "b":
146             assert(c.value == "cdef");
147             break;
148     }
149 }
150 rs = rq.get("http://httpbin.org/absolute-redirect/2");
151 assert((cast(HTTPResponse)rs).history.length == 2);
152 assert((cast(HTTPResponse)rs).code==200);
153 //    rq = Request();
154 rq.maxRedirects = 2;
155 rq.keepAlive = false;
156 rs = rq.get("https://httpbin.org/absolute-redirect/3");
157 assert((cast(HTTPResponse)rs).history.length == 2);
158 assert((cast(HTTPResponse)rs).code==302);
159 
160 info("Check utf8 content");
161 globalLogLevel(LogLevel.info);
162 rq = Request();
163 rs = rq.get("http://httpbin.org/encoding/utf8");
164 assert(rs.code==200);
165 
166 info("Check chunked content");
167 globalLogLevel(LogLevel.info);
168 rq = Request();
169 rq.keepAlive = true;
170 rq.bufferSize = 16*1024;
171 rs = rq.get("http://httpbin.org/range/1024");
172 assert(rs.code==200);
173 assert(rs.responseBody.length==1024);
174 
175 info("Check basic auth");
176 globalLogLevel(LogLevel.info);
177 rq = Request();
178 rq.authenticator = new BasicAuthentication("user", "passwd");
179 rs = rq.get("http://httpbin.org/basic-auth/user/passwd");
180 assert(rs.code==200);
181 
182 globalLogLevel(LogLevel.info);
183 info("Check limits");
184 rq = Request();
185 rq.maxContentLength = 1;
186 assertThrown!RequestException(rq.get("http://httpbin.org/"));
187 rq = Request();
188 rq.maxHeadersLength = 1;
189 assertThrown!RequestException(rq.get("http://httpbin.org/"));
190 //
191 info("ftp post ", "ftp://speedtest.tele2.net/upload/TEST.TXT");
192 rs = rq.post("ftp://speedtest.tele2.net/upload/TEST.TXT", "test, ignore please\n".representation);
193 assert(rs.code == 226);
194 info("ftp get  ", "ftp://speedtest.tele2.net/nonexistent", ", in same session.");
195 rs = rq.get("ftp://speedtest.tele2.net/nonexistent");
196 assert(rs.code != 226);
197 info("ftp get  ", "ftp://speedtest.tele2.net/1KB.zip", ", in same session.");
198 rs = rq.get("ftp://speedtest.tele2.net/1KB.zip");
199 assert(rs.code == 226);
200 assert(rs.responseBody.length == 1024);
201 info("ftp get  ", "ftp://ftp.uni-bayreuth.de/README");
202 rs = rq.get("ftp://ftp.uni-bayreuth.de/README");
203 assert(rs.code == 226);
204 info("ftp post ", "ftp://speedtest.tele2.net/upload/TEST.TXT");
205 rs = rq.post("ftp://speedtest.tele2.net/upload/TEST.TXT", "another test, ignore please\n".representation);
206 assert(rs.code == 226);
207 info("ftp get  ", "ftp://ftp.iij.ad.jp/pub/FreeBSD/README.TXT");
208 rs = rq.get("ftp://ftp.iij.ad.jp/pub/FreeBSD/README.TXT");
209 assert(rs.code == 226);
210 info("testing ftp - done.");

Meta