1 module requests.request; 2 import requests.http; 3 import requests.ftp; 4 import requests.streams; 5 import requests.base; 6 import requests.uri; 7 8 import std.datetime; 9 import std.conv; 10 import std.experimental.logger; 11 import std.format; 12 import requests.utils; 13 14 15 /** 16 This is simplest interface to both http and ftp protocols. 17 Request has methods get, post and exec which routed to proper concrete handler (http or ftp, etc). 18 To enable some protocol-specific featutes you have to use protocol interface directly (see docs for HTTPRequest or FTPRequest) 19 */ 20 public struct Request { 21 private { 22 URI _uri; 23 HTTPRequest _http; // route all http/https requests here 24 FTPRequest _ftp; // route all ftp requests here 25 string _method; 26 } 27 /// Set timeout on IO operation. 28 /// $(B v) - timeout value 29 /// 30 @property void timeout(Duration v) pure @nogc nothrow { 31 _http.timeout = v; 32 _ftp.timeout = v; 33 } 34 /// Set http keepAlive value 35 /// $(B v) - use keepalive requests - $(B true), or not - $(B false) 36 @property void keepAlive(bool v) pure @nogc nothrow { 37 _http.keepAlive = v; 38 } 39 /// Set limit on HTTP redirects 40 /// $(B v) - limit on redirect depth 41 @property void maxRedirects(uint v) pure @nogc nothrow { 42 _http.maxRedirects = v; 43 } 44 /// Set maximum content lenth both for http and ftp requests 45 /// $(B v) - maximum content length in bytes. When limit reached - throw RequestException 46 @property void maxContentLength(size_t v) pure @nogc nothrow { 47 _http.maxContentLength = v; 48 _ftp.maxContentLength = v; 49 } 50 /// Set maximum length for HTTP headers 51 /// $(B v) - maximum length of the HTTP response. When limit reached - throw RequestException 52 @property void maxHeadersLength(size_t v) pure @nogc nothrow { 53 _http.maxHeadersLength = v; 54 } 55 /// Set IO buffer size for http and ftp requests 56 /// $(B v) - buffer size in bytes. 57 @property void bufferSize(size_t v) { 58 _http.bufferSize = v; 59 _ftp.bufferSize = v; 60 } 61 /// Set verbosity for HTTP or FTP requests. 62 /// $(B v) - verbosity level (0 - no output, 1 - headers to stdout, 2 - headers and body progress to stdout). default = 0. 63 @property void verbosity(uint v) { 64 _http.verbosity = v; 65 _ftp.verbosity = v; 66 } 67 /// Set authenticator for http requests. 68 /// $(B v) - Auth instance. 69 @property void authenticator(Auth v) { 70 _http.authenticator = v; 71 _ftp.authenticator = v; 72 } 73 /// set proxy property. 74 /// $(B v) - full url to proxy. 75 @property void proxy(string v) { 76 _http.proxy = v; 77 _ftp.proxy = v; 78 } 79 /// Set Cookie for http requests. 80 /// $(B v) - array of cookie. 81 @property void cookie(Cookie[] v) pure @nogc nothrow { 82 _http.cookie = v; 83 } 84 /// Get Cookie for http requests. 85 /// $(B v) - array of cookie. 86 @property Cookie[] cookie() pure @nogc nothrow { 87 return _http.cookie; 88 } 89 /// 90 /// set "streaming" property 91 /// Params: 92 /// v = value to set (true - use streaming) 93 /// 94 @property void useStreaming(bool v) pure @nogc nothrow { 95 _http.useStreaming = v; 96 _ftp.useStreaming = v; 97 } 98 /// 99 /// get length og actually received content. 100 /// this value increase over time, while we receive data 101 /// 102 @property long contentReceived() pure @nogc nothrow { 103 final switch ( _uri.scheme ) { 104 case "http", "https": 105 return _http.contentReceived; 106 case "ftp": 107 return _ftp.contentReceived; 108 } 109 } 110 /// get contentLength of the responce 111 @property long contentLength() pure @nogc nothrow { 112 final switch ( _uri.scheme ) { 113 case "http", "https": 114 return _http.contentLength; 115 case "ftp": 116 return _ftp.contentLength; 117 } 118 } 119 @property void sslSetVerifyPeer(bool v) { 120 _http.sslSetVerifyPeer(v); 121 } 122 @property void sslSetKeyFile(string path, SSLOptions.filetype type = SSLOptions.filetype.pem) pure @safe nothrow @nogc { 123 _http.sslSetKeyFile(path, type); 124 } 125 @property void sslSetCertFile(string path, SSLOptions.filetype type = SSLOptions.filetype.pem) pure @safe nothrow @nogc { 126 _http.sslSetCertFile(path, type); 127 } 128 @property void sslSetCaCert(string path) pure @safe nothrow @nogc { 129 _http.sslSetCaCert(path); 130 } 131 @property auto sslOptions() { 132 return _http.sslOptions(); 133 } 134 @property auto bind(string v) { 135 _http.bind(v); 136 _ftp.bind(v); 137 } 138 /// Add headers to request 139 /// Params: 140 /// headers = headers to send. 141 void addHeaders(in string[string] headers) { 142 _http.addHeaders(headers); 143 } 144 void clearHeaders() { 145 _http.clearHeaders(); 146 } 147 /// Execute GET for http and retrieve file for FTP. 148 /// You have to provide at least $(B uri). All other arguments should conform to HTTPRequest.get or FTPRequest.get depending on the URI scheme. 149 /// 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) 150 /// you will receive Exception("Operation not supported for ftp") 151 /// 152 Response get(A...)(string uri, A args) { 153 if ( uri ) { 154 _uri = URI(uri); 155 } 156 _method = "GET"; 157 final switch ( _uri.scheme ) { 158 case "http", "https": 159 _http.uri = _uri; 160 static if (__traits(compiles, _http.get(null, args))) { 161 return _http.get(null, args); 162 } else { 163 throw new Exception("Operation not supported for http"); 164 } 165 case "ftp": 166 static if (args.length == 0) { 167 return _ftp.get(uri); 168 } else { 169 throw new Exception("Operation not supported for ftp"); 170 } 171 } 172 } 173 /// Execute POST for http and STOR file for FTP. 174 /// You have to provide $(B uri) and data. Data should conform to HTTPRequest.post or FTPRequest.post depending on the URI scheme. 175 /// When arguments do not conform scheme you will receive Exception("Operation not supported for ftp") 176 /// 177 Response post(A...)(string uri, A args) { 178 if ( uri ) { 179 _uri = URI(uri); 180 } 181 _method = "POST"; 182 final switch ( _uri.scheme ) { 183 case "http", "https": 184 _http.uri = _uri; 185 static if (__traits(compiles, _http.post(null, args))) { 186 return _http.post(null, args); 187 } else { 188 throw new Exception("Operation not supported for http"); 189 } 190 case "ftp": 191 static if (__traits(compiles, _ftp.post(uri, args))) { 192 return _ftp.post(uri, args); 193 } else { 194 throw new Exception("Operation not supported for ftp"); 195 } 196 } 197 } 198 Response exec(string method="GET", A...)(string uri, A args) { 199 _method = method; 200 _uri = URI(uri); 201 _http.uri = _uri; 202 return _http.exec!(method)(null, args); 203 } 204 205 string toString() const { 206 return "Request(%s, %s)".format(_method, _uri.uri()); 207 } 208 string format(string fmt) const { 209 final switch(_uri.scheme) { 210 case "http", "https": 211 return _http.format(fmt); 212 case "ftp": 213 return _ftp.format(fmt); 214 } 215 } 216 }