@@ -33,13 +33,10 @@ pub suberror URIParseError {
3333} derive (Show )
3434
3535///|
36- async fn perform_request (
36+ fn resolve_url (
3737 uri : String ,
38- meth : RequestMethod ,
39- headers : Map [String , String ],
40- body : & @io .Data ,
4138 port ? : Int ,
42- ) -> (Response , & @io . Data ) {
39+ ) -> (Protocol , Int , String , String ) raise {
4340 guard uri .find ("://" ) is Some (protocol_len ) else { raise InvalidFormat }
4441 let protocol = match uri [:protocol_len ] {
4542 "http" => Http
@@ -61,6 +58,18 @@ async fn perform_request(
6158 (uri .to_string (), "/" )
6259 }
6360 let path = if path == "" { "/" } else { path }
61+ (protocol , port , host , path )
62+ }
63+
64+ ///|
65+ async fn perform_request (
66+ uri : String ,
67+ meth : RequestMethod ,
68+ headers : Map [String , String ],
69+ body : & @io .Data ,
70+ port ? : Int ,
71+ ) -> (Response , & @io .Data ) {
72+ let (protocol , port , host , path ) = resolve_url (uri , port ?)
6473 let client = Client ::connect (host , headers ~, protocol ~, port ~)
6574 defer client .close ()
6675 client ..request (meth , path )..write (body )
@@ -107,3 +116,93 @@ pub async fn post(
107116) -> (Response , & @io .Data ) {
108117 perform_request (uri , Post , headers , content , port ?)
109118}
119+
120+ ///|
121+ /// Similar to `@http.get`, but allow reading response body streamingly.
122+ /// A pair `(response, client)` will be returned,
123+ /// where `response` is the response header from the server,
124+ /// and `client` is the HTTP client that performs the request.
125+ /// `client` can be used to read the content of response body via `@io.Reader`,
126+ /// see `@http.Client` for more details.
127+ ///
128+ /// Note that the returned client must be manually closed via `.close()`
129+ /// to close the underlying connection used for the request.
130+ pub async fn get_stream (
131+ uri : String ,
132+ headers ? : Map [String , String ] = {},
133+ port ? : Int ,
134+ body ? : & @io .Data = b "" ,
135+ ) -> (Response , Client ) {
136+ let (protocol , port , host , path ) = resolve_url (uri , port ?)
137+ let client = Client ::connect (host , headers ~, protocol ~, port ~)
138+ try {
139+ client ..request (Get , path )..write (body )
140+ let response = client .end_request ()
141+ (response , client )
142+ } catch {
143+ err => {
144+ client .close ()
145+ raise err
146+ }
147+ }
148+ }
149+
150+ ///|
151+ /// Similar to `@http.put`, but allow writing request body streamingly.
152+ /// The return value `client` is the HTTP client that performs the request,
153+ /// it can be used to write the content of request body via `@io.Writer`.
154+ /// Notice that writing to `@http.Client` is buffered,
155+ /// so if you need to send data to the server immediately, `.flush()` must be called.
156+ /// After writing all the content, `.end_request()` must be called
157+ /// to complete the request and obtain response from the server.
158+ /// After that, the response body from the server can be obtained
159+ /// by using `client` as a `@io.Reader`. See `@http.Client` for more details.
160+ ///
161+ /// Note that the returned `client` must be manually closed via `.close()`
162+ /// to close the underlying connection used for the request.
163+ pub async fn put_stream (
164+ uri : String ,
165+ headers ? : Map [String , String ] = {},
166+ port ? : Int ,
167+ ) -> Client {
168+ let (protocol , port , host , path ) = resolve_url (uri , port ?)
169+ let client = Client ::connect (host , headers ~, protocol ~, port ~)
170+ try client .request (Put , path ) catch {
171+ err => {
172+ client .close ()
173+ raise err
174+ }
175+ } noraise {
176+ _ => client
177+ }
178+ }
179+
180+ ///|
181+ /// Similar to `@http.post`, but allow writing request body streamingly.
182+ /// The return value `client` is the HTTP client that performs the request,
183+ /// it can be used to write the content of request body via `@io.Writer`.
184+ /// Notice that writing to `@http.Client` is buffered,
185+ /// so if you need to send data to the server immediately, `.flush()` must be called.
186+ /// After writing all the content, `.end_request()` must be called
187+ /// to complete the request and obtain response from the server.
188+ /// After that, the response body from the server can be obtained
189+ /// by using `client` as a `@io.Reader`. See `@http.Client` for more details.
190+ ///
191+ /// Note that the returned `client` must be manually closed via `.close()`
192+ /// to close the underlying connection used for the request.
193+ pub async fn post_stream (
194+ uri : String ,
195+ headers ? : Map [String , String ] = {},
196+ port ? : Int ,
197+ ) -> Client {
198+ let (protocol , port , host , path ) = resolve_url (uri , port ?)
199+ let client = Client ::connect (host , headers ~, protocol ~, port ~)
200+ try client .request (Post , path ) catch {
201+ err => {
202+ client .close ()
203+ raise err
204+ }
205+ } noraise {
206+ _ => client
207+ }
208+ }
0 commit comments