@@ -28,13 +28,13 @@ pub enum HttpMethod {
2828#[ derive( Debug , Clone ) ]
2929pub struct MultipartPart {
3030 /// The field name for this part.
31- pub name : String ,
31+ pub ( crate ) name : String ,
3232 /// The part's data.
33- pub data : bytes:: Bytes ,
33+ pub ( crate ) data : bytes:: Bytes ,
3434 /// Optional filename for this part.
35- pub filename : Option < String > ,
35+ pub ( crate ) filename : Option < String > ,
3636 /// Optional MIME content type (e.g. `"application/json"`).
37- pub content_type : Option < String > ,
37+ pub ( crate ) content_type : Option < String > ,
3838}
3939
4040impl MultipartPart {
@@ -49,42 +49,68 @@ impl MultipartPart {
4949 }
5050
5151 /// Set the filename for this part.
52- pub fn filename ( mut self , filename : impl Into < String > ) -> Self {
52+ #[ inline]
53+ pub fn with_filename ( mut self , filename : impl Into < String > ) -> Self {
5354 self . filename = Some ( filename. into ( ) ) ;
5455 self
5556 }
5657
5758 /// Set the MIME content type for this part.
58- pub fn content_type ( mut self , content_type : impl Into < String > ) -> Self {
59+ #[ inline]
60+ pub fn with_content_type ( mut self , content_type : impl Into < String > ) -> Self {
5961 self . content_type = Some ( content_type. into ( ) ) ;
6062 self
6163 }
64+
65+ /// Returns the field name for this part.
66+ #[ inline]
67+ pub fn name ( & self ) -> & str {
68+ & self . name
69+ }
70+
71+ /// Returns the raw bytes of this part.
72+ #[ inline]
73+ pub fn data ( & self ) -> & bytes:: Bytes {
74+ & self . data
75+ }
76+
77+ /// Returns the filename, if any.
78+ #[ inline]
79+ pub fn filename ( & self ) -> Option < & str > {
80+ self . filename . as_deref ( )
81+ }
82+
83+ /// Returns the MIME content type, if any.
84+ #[ inline]
85+ pub fn content_type ( & self ) -> Option < & str > {
86+ self . content_type . as_deref ( )
87+ }
6288}
6389
6490/// An outgoing HTTP request.
6591#[ derive( Debug , Clone ) ]
6692pub struct HttpRequest {
6793 /// HTTP method.
68- pub method : HttpMethod ,
94+ pub ( crate ) method : HttpMethod ,
6995
7096 /// Absolute URL string (e.g. `"http://localhost:8080/v0.4/traces"`).
71- pub url : String ,
97+ pub ( crate ) url : String ,
7298
7399 /// Request headers as a list of (name, value) pairs.
74100 ///
75101 /// Vec preserves insertion order and allows duplicate header names,
76102 /// both of which are valid in HTTP.
77- pub headers : Vec < ( String , String ) > ,
103+ pub ( crate ) headers : Vec < ( String , String ) > ,
78104
79105 /// Request body bytes. Empty for requests with no body.
80- pub body : bytes:: Bytes ,
106+ pub ( crate ) body : bytes:: Bytes ,
81107
82108 /// Per-request timeout. Overrides the client-level timeout if set.
83- pub timeout : Option < Duration > ,
109+ pub ( crate ) timeout : Option < Duration > ,
84110
85111 /// Multipart form-data parts. When non-empty, the request is sent as
86112 /// multipart/form-data and `body` is ignored.
87- pub multipart_parts : Vec < MultipartPart > ,
113+ pub ( crate ) multipart_parts : Vec < MultipartPart > ,
88114}
89115
90116impl HttpRequest {
@@ -101,10 +127,86 @@ impl HttpRequest {
101127 }
102128 }
103129
104- /// Add a multipart part to this request. When any parts are present, the
105- /// request is sent as multipart/form-data and `body` is ignored.
106- pub fn add_multipart_part ( & mut self , part : MultipartPart ) {
130+ /// Append a header to this request.
131+ #[ inline]
132+ pub fn with_header ( mut self , name : impl Into < String > , value : impl Into < String > ) -> Self {
133+ self . headers . push ( ( name. into ( ) , value. into ( ) ) ) ;
134+ self
135+ }
136+
137+ /// Set the request body.
138+ #[ inline]
139+ pub fn with_body ( mut self , body : impl Into < bytes:: Bytes > ) -> Self {
140+ self . body = body. into ( ) ;
141+ self
142+ }
143+
144+ /// Set the per-request timeout, overriding the client-level timeout.
145+ #[ inline]
146+ pub fn with_timeout ( mut self , timeout : Duration ) -> Self {
147+ self . timeout = Some ( timeout) ;
148+ self
149+ }
150+
151+ /// Append a multipart part to this request.
152+ #[ inline]
153+ pub fn with_multipart_part ( mut self , part : MultipartPart ) -> Self {
107154 self . multipart_parts . push ( part) ;
155+ self
156+ }
157+
158+ /// Returns the HTTP method.
159+ #[ inline]
160+ pub fn method ( & self ) -> HttpMethod {
161+ self . method
162+ }
163+
164+ /// Returns the request URL.
165+ #[ inline]
166+ pub fn url ( & self ) -> & str {
167+ & self . url
168+ }
169+
170+ /// Returns the request headers.
171+ #[ inline]
172+ pub fn headers ( & self ) -> & [ ( String , String ) ] {
173+ & self . headers
174+ }
175+
176+ /// Returns the request body.
177+ #[ inline]
178+ pub fn body ( & self ) -> & bytes:: Bytes {
179+ & self . body
180+ }
181+
182+ /// Returns the per-request timeout override, if set.
183+ #[ inline]
184+ pub fn timeout ( & self ) -> Option < Duration > {
185+ self . timeout
186+ }
187+
188+ /// Returns the multipart parts.
189+ #[ inline]
190+ pub fn multipart_parts ( & self ) -> & [ MultipartPart ] {
191+ & self . multipart_parts
192+ }
193+
194+ /// Returns a mutable reference to the headers list.
195+ #[ inline]
196+ pub fn headers_mut ( & mut self ) -> & mut Vec < ( String , String ) > {
197+ & mut self . headers
198+ }
199+
200+ /// Returns a mutable reference to the request body.
201+ #[ inline]
202+ pub fn body_mut ( & mut self ) -> & mut bytes:: Bytes {
203+ & mut self . body
204+ }
205+
206+ /// Returns a mutable reference to the multipart parts list.
207+ #[ inline]
208+ pub fn multipart_parts_mut ( & mut self ) -> & mut Vec < MultipartPart > {
209+ & mut self . multipart_parts
108210 }
109211}
110212
@@ -126,7 +228,7 @@ mod tests {
126228 fn request_with_headers_and_body ( ) {
127229 let mut req = HttpRequest :: new ( HttpMethod :: Post , "http://localhost/data" . to_owned ( ) ) ;
128230 req. headers
129- . push ( ( "Content-Type" . to_string ( ) , "application/json" . to_owned ( ) ) ) ;
231+ . push ( ( "Content-Type" . to_owned ( ) , "application/json" . to_owned ( ) ) ) ;
130232 req. body = bytes:: Bytes :: from_static ( b"{\" key\" :\" value\" }" ) ;
131233 req. timeout = Some ( Duration :: from_secs ( 10 ) ) ;
132234
@@ -140,4 +242,16 @@ mod tests {
140242 assert_eq ! ( HttpMethod :: Get , HttpMethod :: Get ) ;
141243 assert_ne ! ( HttpMethod :: Get , HttpMethod :: Post ) ;
142244 }
245+
246+ #[ test]
247+ fn test_multipart_part_builder ( ) {
248+ let part = MultipartPart :: new ( "name" , bytes:: Bytes :: from_static ( b"data" ) )
249+ . with_filename ( "test.txt" )
250+ . with_content_type ( "text/plain" ) ;
251+
252+ assert_eq ! ( part. name, "name" ) ;
253+ assert_eq ! ( part. data. as_ref( ) , b"data" ) ;
254+ assert_eq ! ( part. filename. as_deref( ) , Some ( "test.txt" ) ) ;
255+ assert_eq ! ( part. content_type. as_deref( ) , Some ( "text/plain" ) ) ;
256+ }
143257}
0 commit comments