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 assertThrown!MaxRedirectsException(rq.get("https://httpbin.org/absolute-redirect/3"));
157 
158 info("Check utf8 content");
159 globalLogLevel(LogLevel.info);
160 rq = Request();
161 rs = rq.get("http://httpbin.org/encoding/utf8");
162 assert(rs.code==200);
163 
164 info("Check chunked content");
165 globalLogLevel(LogLevel.info);
166 rq = Request();
167 rq.keepAlive = true;
168 rq.bufferSize = 16*1024;
169 rs = rq.get("http://httpbin.org/range/1024");
170 assert(rs.code==200);
171 assert(rs.responseBody.length==1024);
172 
173 info("Check basic auth");
174 globalLogLevel(LogLevel.info);
175 rq = Request();
176 rq.authenticator = new BasicAuthentication("user", "passwd");
177 rs = rq.get("http://httpbin.org/basic-auth/user/passwd");
178 assert(rs.code==200);
179 
180 globalLogLevel(LogLevel.info);
181 info("Check limits");
182 rq = Request();
183 rq.maxContentLength = 1;
184 assertThrown!RequestException(rq.get("http://httpbin.org/"));
185 rq = Request();
186 rq.maxHeadersLength = 1;
187 assertThrown!RequestException(rq.get("http://httpbin.org/"));
188 //
189 info("ftp post ", "ftp://speedtest.tele2.net/upload/TEST.TXT");
190 rs = rq.post("ftp://speedtest.tele2.net/upload/TEST.TXT", "test, ignore please\n".representation);
191 assert(rs.code == 226);
192 info("ftp get  ", "ftp://speedtest.tele2.net/nonexistent", ", in same session.");
193 rs = rq.get("ftp://speedtest.tele2.net/nonexistent");
194 assert(rs.code != 226);
195 info("ftp get  ", "ftp://speedtest.tele2.net/1KB.zip", ", in same session.");
196 rs = rq.get("ftp://speedtest.tele2.net/1KB.zip");
197 assert(rs.code == 226);
198 assert(rs.responseBody.length == 1024);
199 info("ftp post ", "ftp://speedtest.tele2.net/upload/TEST.TXT");
200 rs = rq.post("ftp://speedtest.tele2.net/upload/TEST.TXT", "another test, ignore please\n".representation);
201 assert(rs.code == 226);
202 info("ftp get  ", "ftp://ftp.iij.ad.jp/pub/FreeBSD/README.TXT");
203 rs = rq.get("ftp://ftp.iij.ad.jp/pub/FreeBSD/README.TXT");
204 assert(rs.code == 226);
205 info("testing ftp - done.");

Meta