10
10
//! ```
11
11
//! # fn main() -> http_types::Result<()> {
12
12
//! #
13
- //! use http_types::Response;
14
- //! use http_types::security::{ TimingAllowOrigin, TimingOrigin} ;
13
+ //! use http_types::{ Response, Url} ;
14
+ //! use http_types::security::TimingAllowOrigin;
15
15
//!
16
16
//! let mut origins = TimingAllowOrigin::new();
17
- //! origins.push(TimingOrigin::Wildcard );
17
+ //! origins.push(Url::parse("https://example.com")? );
18
18
//!
19
19
//! let mut res = Response::new(200);
20
20
//! origins.apply(&mut res);
21
21
//!
22
22
//! let origins = TimingAllowOrigin::from_headers(res)?.unwrap();
23
23
//! let origin = origins.iter().next().unwrap();
24
- //! assert_eq!(origin, &TimingOrigin::Wildcard );
24
+ //! assert_eq!(origin, &Url::parse("https://example.com")? );
25
25
//! #
26
26
//! # Ok(()) }
27
27
//! ```
@@ -42,30 +42,31 @@ use std::slice;
42
42
/// ```
43
43
/// # fn main() -> http_types::Result<()> {
44
44
/// #
45
- /// use http_types::Response;
46
- /// use http_types::security::{ TimingAllowOrigin, TimingOrigin} ;
45
+ /// use http_types::{ Response, Url} ;
46
+ /// use http_types::security::TimingAllowOrigin;
47
47
///
48
48
/// let mut origins = TimingAllowOrigin::new();
49
- /// origins.push(TimingOrigin::Wildcard );
49
+ /// origins.push(Url::parse("https://example.com")? );
50
50
///
51
51
/// let mut res = Response::new(200);
52
52
/// origins.apply(&mut res);
53
53
///
54
54
/// let origins = TimingAllowOrigin::from_headers(res)?.unwrap();
55
55
/// let origin = origins.iter().next().unwrap();
56
- /// assert_eq!(origin, &TimingOrigin::Wildcard );
56
+ /// assert_eq!(origin, &Url::parse("https://example.com")? );
57
57
/// #
58
58
/// # Ok(()) }
59
59
/// ```
60
60
#[ derive( Clone , Eq , PartialEq ) ]
61
61
pub struct TimingAllowOrigin {
62
- origins : Vec < TimingOrigin > ,
62
+ origins : Vec < Url > ,
63
+ wildcard : bool ,
63
64
}
64
65
65
66
impl TimingAllowOrigin {
66
67
/// Create a new instance of `AllowOrigin`.
67
68
pub fn new ( ) -> Self {
68
- Self { origins : vec ! [ ] }
69
+ Self { origins : vec ! [ ] , wildcard : false , }
69
70
}
70
71
71
72
/// Create an instance of `AllowOrigin` from a `Headers` instance.
@@ -79,25 +80,26 @@ impl TimingAllowOrigin {
79
80
None => return Ok ( None ) ,
80
81
} ;
81
82
83
+ let mut wildcard = false ;
82
84
let mut origins = vec ! [ ] ;
83
85
for header in headers {
84
86
for origin in header. as_str ( ) . split ( ',' ) {
85
87
match origin. trim_start ( ) {
86
- "*" => origins . push ( TimingOrigin :: Wildcard ) ,
88
+ "*" => wildcard = true ,
87
89
r#""null""# => continue ,
88
90
origin => {
89
91
let url = Url :: parse ( origin) . status ( 400 ) ?;
90
- origins. push ( TimingOrigin :: Url ( url) ) ;
92
+ origins. push ( url) ;
91
93
}
92
94
}
93
95
}
94
96
}
95
97
96
- Ok ( Some ( Self { origins } ) )
98
+ Ok ( Some ( Self { origins, wildcard } ) )
97
99
}
98
100
99
101
/// 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 > ) {
101
103
self . origins . push ( origin. into ( ) ) ;
102
104
}
103
105
@@ -115,17 +117,33 @@ impl TimingAllowOrigin {
115
117
pub fn value ( & self ) -> HeaderValue {
116
118
let mut output = String :: new ( ) ;
117
119
for ( n, origin) in self . origins . iter ( ) . enumerate ( ) {
118
- let origin: HeaderValue = origin. clone ( ) . into ( ) ;
119
120
match n {
120
121
0 => write ! ( output, "{}" , origin) . unwrap ( ) ,
121
122
_ => write ! ( output, ", {}" , origin) . unwrap ( ) ,
122
123
} ;
123
124
}
124
125
126
+ if self . wildcard {
127
+ match output. len ( ) {
128
+ 0 => write ! ( output, "*" ) . unwrap ( ) ,
129
+ _ => write ! ( output, ", *" ) . unwrap ( ) ,
130
+ } ;
131
+ }
132
+
125
133
// SAFETY: the internal string is validated to be ASCII.
126
134
unsafe { HeaderValue :: from_bytes_unchecked ( output. into ( ) ) }
127
135
}
128
136
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
+
129
147
/// An iterator visiting all server timings.
130
148
pub fn iter ( & self ) -> Iter < ' _ > {
131
149
Iter {
@@ -142,7 +160,7 @@ impl TimingAllowOrigin {
142
160
}
143
161
144
162
impl IntoIterator for TimingAllowOrigin {
145
- type Item = TimingOrigin ;
163
+ type Item = Url ;
146
164
type IntoIter = IntoIter ;
147
165
148
166
#[ inline]
@@ -154,7 +172,7 @@ impl IntoIterator for TimingAllowOrigin {
154
172
}
155
173
156
174
impl < ' a > IntoIterator for & ' a TimingAllowOrigin {
157
- type Item = & ' a TimingOrigin ;
175
+ type Item = & ' a Url ;
158
176
type IntoIter = Iter < ' a > ;
159
177
160
178
// #[inline]serv
@@ -164,7 +182,7 @@ impl<'a> IntoIterator for &'a TimingAllowOrigin {
164
182
}
165
183
166
184
impl < ' a > IntoIterator for & ' a mut TimingAllowOrigin {
167
- type Item = & ' a mut TimingOrigin ;
185
+ type Item = & ' a mut Url ;
168
186
type IntoIter = IterMut < ' a > ;
169
187
170
188
#[ inline]
@@ -176,11 +194,11 @@ impl<'a> IntoIterator for &'a mut TimingAllowOrigin {
176
194
/// A borrowing iterator over entries in `AllowOrigin`.
177
195
#[ derive( Debug ) ]
178
196
pub struct IntoIter {
179
- inner : std:: vec:: IntoIter < TimingOrigin > ,
197
+ inner : std:: vec:: IntoIter < Url > ,
180
198
}
181
199
182
200
impl Iterator for IntoIter {
183
- type Item = TimingOrigin ;
201
+ type Item = Url ;
184
202
185
203
fn next ( & mut self ) -> Option < Self :: Item > {
186
204
self . inner . next ( )
@@ -195,11 +213,11 @@ impl Iterator for IntoIter {
195
213
/// A lending iterator over entries in `AllowOrigin`.
196
214
#[ derive( Debug ) ]
197
215
pub struct Iter < ' a > {
198
- inner : slice:: Iter < ' a , TimingOrigin > ,
216
+ inner : slice:: Iter < ' a , Url > ,
199
217
}
200
218
201
219
impl < ' a > Iterator for Iter < ' a > {
202
- type Item = & ' a TimingOrigin ;
220
+ type Item = & ' a Url ;
203
221
204
222
fn next ( & mut self ) -> Option < Self :: Item > {
205
223
self . inner . next ( )
@@ -214,11 +232,11 @@ impl<'a> Iterator for Iter<'a> {
214
232
/// A mutable iterator over entries in `AllowOrigin`.
215
233
#[ derive( Debug ) ]
216
234
pub struct IterMut < ' a > {
217
- inner : slice:: IterMut < ' a , TimingOrigin > ,
235
+ inner : slice:: IterMut < ' a , Url > ,
218
236
}
219
237
220
238
impl < ' a > Iterator for IterMut < ' a > {
221
- type Item = & ' a mut TimingOrigin ;
239
+ type Item = & ' a mut Url ;
222
240
223
241
fn next ( & mut self ) -> Option < Self :: Item > {
224
242
self . inner . next ( )
@@ -248,41 +266,6 @@ impl Debug for TimingAllowOrigin {
248
266
}
249
267
}
250
268
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
-
286
269
#[ cfg( test) ]
287
270
mod test {
288
271
use super :: * ;
@@ -291,34 +274,33 @@ mod test {
291
274
#[ test]
292
275
fn smoke ( ) -> crate :: Result < ( ) > {
293
276
let mut origins = TimingAllowOrigin :: new ( ) ;
294
- origins. push ( TimingOrigin :: Wildcard ) ;
277
+ origins. push ( Url :: parse ( "https://example.com" ) ? ) ;
295
278
296
279
let mut headers = Headers :: new ( ) ;
297
280
origins. apply ( & mut headers) ;
298
281
299
282
let origins = TimingAllowOrigin :: from_headers ( headers) ?. unwrap ( ) ;
300
283
let origin = origins. iter ( ) . next ( ) . unwrap ( ) ;
301
- assert_eq ! ( origin, & TimingOrigin :: Wildcard ) ;
284
+ assert_eq ! ( origin, & Url :: parse ( "https://example.com" ) ? ) ;
302
285
Ok ( ( ) )
303
286
}
304
287
305
288
#[ test]
306
289
fn multi ( ) -> crate :: Result < ( ) > {
307
290
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/" ) ?) ;
310
293
311
294
let mut headers = Headers :: new ( ) ;
312
295
origins. apply ( & mut headers) ;
313
296
314
297
let origins = TimingAllowOrigin :: from_headers ( headers) ?. unwrap ( ) ;
315
298
let mut origins = origins. iter ( ) ;
316
299
let origin = origins. next ( ) . unwrap ( ) ;
317
- assert ! ( matches! ( origin, TimingOrigin :: Wildcard ) ) ;
300
+ assert_eq ! ( origin, & Url :: parse ( "https://example.com" ) ? ) ;
318
301
319
302
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/" ) ?) ;
322
304
Ok ( ( ) )
323
305
}
324
306
@@ -330,4 +312,22 @@ mod test {
330
312
assert_eq ! ( err. status( ) , 400 ) ;
331
313
Ok ( ( ) )
332
314
}
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
+
333
333
}
0 commit comments