1010//! ```
1111//! # fn main() -> http_types::Result<()> {
1212//! #
13- //! use http_types::Response;
14- //! use http_types::security::{ TimingAllowOrigin, TimingOrigin} ;
13+ //! use http_types::{ Response, Url} ;
14+ //! use http_types::security::TimingAllowOrigin;
1515//!
1616//! let mut origins = TimingAllowOrigin::new();
17- //! origins.push(TimingOrigin::Wildcard );
17+ //! origins.push(Url::parse("https://example.com")? );
1818//!
1919//! let mut res = Response::new(200);
2020//! origins.apply(&mut res);
2121//!
2222//! let origins = TimingAllowOrigin::from_headers(res)?.unwrap();
2323//! let origin = origins.iter().next().unwrap();
24- //! assert_eq!(origin, &TimingOrigin::Wildcard );
24+ //! assert_eq!(origin, &Url::parse("https://example.com")? );
2525//! #
2626//! # Ok(()) }
2727//! ```
@@ -42,30 +42,31 @@ use std::slice;
4242/// ```
4343/// # fn main() -> http_types::Result<()> {
4444/// #
45- /// use http_types::Response;
46- /// use http_types::security::{ TimingAllowOrigin, TimingOrigin} ;
45+ /// use http_types::{ Response, Url} ;
46+ /// use http_types::security::TimingAllowOrigin;
4747///
4848/// let mut origins = TimingAllowOrigin::new();
49- /// origins.push(TimingOrigin::Wildcard );
49+ /// origins.push(Url::parse("https://example.com")? );
5050///
5151/// let mut res = Response::new(200);
5252/// origins.apply(&mut res);
5353///
5454/// let origins = TimingAllowOrigin::from_headers(res)?.unwrap();
5555/// let origin = origins.iter().next().unwrap();
56- /// assert_eq!(origin, &TimingOrigin::Wildcard );
56+ /// assert_eq!(origin, &Url::parse("https://example.com")? );
5757/// #
5858/// # Ok(()) }
5959/// ```
6060#[ derive( Clone , Eq , PartialEq ) ]
6161pub struct TimingAllowOrigin {
62- origins : Vec < TimingOrigin > ,
62+ origins : Vec < Url > ,
63+ wildcard : bool ,
6364}
6465
6566impl TimingAllowOrigin {
6667 /// Create a new instance of `AllowOrigin`.
6768 pub fn new ( ) -> Self {
68- Self { origins : vec ! [ ] }
69+ Self { origins : vec ! [ ] , wildcard : false , }
6970 }
7071
7172 /// Create an instance of `AllowOrigin` from a `Headers` instance.
@@ -79,25 +80,26 @@ impl TimingAllowOrigin {
7980 None => return Ok ( None ) ,
8081 } ;
8182
83+ let mut wildcard = false ;
8284 let mut origins = vec ! [ ] ;
8385 for header in headers {
8486 for origin in header. as_str ( ) . split ( ',' ) {
8587 match origin. trim_start ( ) {
86- "*" => origins . push ( TimingOrigin :: Wildcard ) ,
88+ "*" => wildcard = true ,
8789 r#""null""# => continue ,
8890 origin => {
8991 let url = Url :: parse ( origin) . status ( 400 ) ?;
90- origins. push ( TimingOrigin :: Url ( url) ) ;
92+ origins. push ( url) ;
9193 }
9294 }
9395 }
9496 }
9597
96- Ok ( Some ( Self { origins } ) )
98+ Ok ( Some ( Self { origins, wildcard } ) )
9799 }
98100
99101 /// Append an origin to the list of origins.
100- pub fn push ( & mut self , origin : impl Into < TimingOrigin > ) {
102+ pub fn push ( & mut self , origin : impl Into < Url > ) {
101103 self . origins . push ( origin. into ( ) ) ;
102104 }
103105
@@ -115,17 +117,33 @@ impl TimingAllowOrigin {
115117 pub fn value ( & self ) -> HeaderValue {
116118 let mut output = String :: new ( ) ;
117119 for ( n, origin) in self . origins . iter ( ) . enumerate ( ) {
118- let origin: HeaderValue = origin. clone ( ) . into ( ) ;
119120 match n {
120121 0 => write ! ( output, "{}" , origin) . unwrap ( ) ,
121122 _ => write ! ( output, ", {}" , origin) . unwrap ( ) ,
122123 } ;
123124 }
124125
126+ if self . wildcard {
127+ match output. len ( ) {
128+ 0 => write ! ( output, "*" ) . unwrap ( ) ,
129+ _ => write ! ( output, ", *" ) . unwrap ( ) ,
130+ } ;
131+ }
132+
125133 // SAFETY: the internal string is validated to be ASCII.
126134 unsafe { HeaderValue :: from_bytes_unchecked ( output. into ( ) ) }
127135 }
128136
137+ /// Returns `true` if a wildcard directive was set.
138+ pub fn wildcard ( & self ) -> bool {
139+ self . wildcard
140+ }
141+
142+ /// Set the wildcard directive.
143+ pub fn set_wildcard ( & mut self , wildcard : bool ) {
144+ self . wildcard = wildcard
145+ }
146+
129147 /// An iterator visiting all server timings.
130148 pub fn iter ( & self ) -> Iter < ' _ > {
131149 Iter {
@@ -142,7 +160,7 @@ impl TimingAllowOrigin {
142160}
143161
144162impl IntoIterator for TimingAllowOrigin {
145- type Item = TimingOrigin ;
163+ type Item = Url ;
146164 type IntoIter = IntoIter ;
147165
148166 #[ inline]
@@ -154,7 +172,7 @@ impl IntoIterator for TimingAllowOrigin {
154172}
155173
156174impl < ' a > IntoIterator for & ' a TimingAllowOrigin {
157- type Item = & ' a TimingOrigin ;
175+ type Item = & ' a Url ;
158176 type IntoIter = Iter < ' a > ;
159177
160178 // #[inline]serv
@@ -164,7 +182,7 @@ impl<'a> IntoIterator for &'a TimingAllowOrigin {
164182}
165183
166184impl < ' a > IntoIterator for & ' a mut TimingAllowOrigin {
167- type Item = & ' a mut TimingOrigin ;
185+ type Item = & ' a mut Url ;
168186 type IntoIter = IterMut < ' a > ;
169187
170188 #[ inline]
@@ -176,11 +194,11 @@ impl<'a> IntoIterator for &'a mut TimingAllowOrigin {
176194/// A borrowing iterator over entries in `AllowOrigin`.
177195#[ derive( Debug ) ]
178196pub struct IntoIter {
179- inner : std:: vec:: IntoIter < TimingOrigin > ,
197+ inner : std:: vec:: IntoIter < Url > ,
180198}
181199
182200impl Iterator for IntoIter {
183- type Item = TimingOrigin ;
201+ type Item = Url ;
184202
185203 fn next ( & mut self ) -> Option < Self :: Item > {
186204 self . inner . next ( )
@@ -195,11 +213,11 @@ impl Iterator for IntoIter {
195213/// A lending iterator over entries in `AllowOrigin`.
196214#[ derive( Debug ) ]
197215pub struct Iter < ' a > {
198- inner : slice:: Iter < ' a , TimingOrigin > ,
216+ inner : slice:: Iter < ' a , Url > ,
199217}
200218
201219impl < ' a > Iterator for Iter < ' a > {
202- type Item = & ' a TimingOrigin ;
220+ type Item = & ' a Url ;
203221
204222 fn next ( & mut self ) -> Option < Self :: Item > {
205223 self . inner . next ( )
@@ -214,11 +232,11 @@ impl<'a> Iterator for Iter<'a> {
214232/// A mutable iterator over entries in `AllowOrigin`.
215233#[ derive( Debug ) ]
216234pub struct IterMut < ' a > {
217- inner : slice:: IterMut < ' a , TimingOrigin > ,
235+ inner : slice:: IterMut < ' a , Url > ,
218236}
219237
220238impl < ' a > Iterator for IterMut < ' a > {
221- type Item = & ' a mut TimingOrigin ;
239+ type Item = & ' a mut Url ;
222240
223241 fn next ( & mut self ) -> Option < Self :: Item > {
224242 self . inner . next ( )
@@ -248,41 +266,6 @@ impl Debug for TimingAllowOrigin {
248266 }
249267}
250268
251- /// An origin passed into `AllowOrigin`.
252- ///
253- /// Values can either be `Url` or `Wildcard`. `"null"` values are skipped during parsing.
254- //
255- // NOTE: this origin is different than the origin in the fetch spec. It needs to
256- // be its own type.
257- #[ derive( Debug , Clone , Eq , PartialEq ) ]
258- pub enum TimingOrigin {
259- /// An origin URL.
260- Url ( Url ) ,
261- /// Allow all origins.
262- Wildcard ,
263- }
264-
265- impl From < Url > for TimingOrigin {
266- fn from ( url : Url ) -> Self {
267- TimingOrigin :: Url ( url)
268- }
269- }
270-
271- impl From < TimingOrigin > for HeaderValue {
272- fn from ( entry : TimingOrigin ) -> HeaderValue {
273- unsafe {
274- match entry {
275- TimingOrigin :: Url ( url) => {
276- HeaderValue :: from_bytes_unchecked ( format ! ( "{}" , url) . into_bytes ( ) )
277- }
278- TimingOrigin :: Wildcard => {
279- HeaderValue :: from_bytes_unchecked ( String :: from ( "*" ) . into_bytes ( ) )
280- }
281- }
282- }
283- }
284- }
285-
286269#[ cfg( test) ]
287270mod test {
288271 use super :: * ;
@@ -291,34 +274,33 @@ mod test {
291274 #[ test]
292275 fn smoke ( ) -> crate :: Result < ( ) > {
293276 let mut origins = TimingAllowOrigin :: new ( ) ;
294- origins. push ( TimingOrigin :: Wildcard ) ;
277+ origins. push ( Url :: parse ( "https://example.com" ) ? ) ;
295278
296279 let mut headers = Headers :: new ( ) ;
297280 origins. apply ( & mut headers) ;
298281
299282 let origins = TimingAllowOrigin :: from_headers ( headers) ?. unwrap ( ) ;
300283 let origin = origins. iter ( ) . next ( ) . unwrap ( ) ;
301- assert_eq ! ( origin, & TimingOrigin :: Wildcard ) ;
284+ assert_eq ! ( origin, & Url :: parse ( "https://example.com" ) ? ) ;
302285 Ok ( ( ) )
303286 }
304287
305288 #[ test]
306289 fn multi ( ) -> crate :: Result < ( ) > {
307290 let mut origins = TimingAllowOrigin :: new ( ) ;
308- origins. push ( TimingOrigin :: Wildcard ) ;
309- origins. push ( TimingOrigin :: Url ( Url :: parse ( "https://mozilla.org/" ) ?) ) ;
291+ origins. push ( Url :: parse ( "https://example.com" ) ? ) ;
292+ origins. push ( Url :: parse ( "https://mozilla.org/" ) ?) ;
310293
311294 let mut headers = Headers :: new ( ) ;
312295 origins. apply ( & mut headers) ;
313296
314297 let origins = TimingAllowOrigin :: from_headers ( headers) ?. unwrap ( ) ;
315298 let mut origins = origins. iter ( ) ;
316299 let origin = origins. next ( ) . unwrap ( ) ;
317- assert ! ( matches! ( origin, TimingOrigin :: Wildcard ) ) ;
300+ assert_eq ! ( origin, & Url :: parse ( "https://example.com" ) ? ) ;
318301
319302 let origin = origins. next ( ) . unwrap ( ) ;
320- let rhs = Url :: parse ( "https://mozilla.org/" ) ?;
321- assert_eq ! ( origin, & TimingOrigin :: Url ( rhs) ) ;
303+ assert_eq ! ( origin, & Url :: parse( "https://mozilla.org/" ) ?) ;
322304 Ok ( ( ) )
323305 }
324306
@@ -330,4 +312,22 @@ mod test {
330312 assert_eq ! ( err. status( ) , 400 ) ;
331313 Ok ( ( ) )
332314 }
315+
316+ #[ test]
317+ fn wildcard ( ) -> crate :: Result < ( ) > {
318+ let mut origins = TimingAllowOrigin :: new ( ) ;
319+ origins. push ( Url :: parse ( "https://example.com" ) ?) ;
320+ origins. set_wildcard ( true ) ;
321+
322+ let mut headers = Headers :: new ( ) ;
323+ origins. apply ( & mut headers) ;
324+
325+ let origins = TimingAllowOrigin :: from_headers ( headers) ?. unwrap ( ) ;
326+ assert_eq ! ( origins. wildcard( ) , true ) ;
327+ let origin = origins. iter ( ) . next ( ) . unwrap ( ) ;
328+ assert_eq ! ( origin, & Url :: parse( "https://example.com" ) ?) ;
329+ Ok ( ( ) )
330+ }
331+
332+
333333}
0 commit comments