@@ -51,8 +51,14 @@ impl From<MediaType> for OutputFormat {
51
51
}
52
52
53
53
// Builds the `micro_http::Response` with a given HTTP version, status code, and body.
54
- fn build_response ( http_version : Version , status_code : StatusCode , body : Body ) -> Response {
54
+ fn build_response (
55
+ http_version : Version ,
56
+ status_code : StatusCode ,
57
+ content_type : MediaType ,
58
+ body : Body ,
59
+ ) -> Response {
55
60
let mut response = Response :: new ( http_version, status_code) ;
61
+ response. set_content_type ( content_type) ;
56
62
response. set_body ( body) ;
57
63
response
58
64
}
@@ -105,6 +111,7 @@ pub fn convert_to_response(mmds: Arc<Mutex<Mmds>>, request: Request) -> Response
105
111
return build_response (
106
112
request. http_version ( ) ,
107
113
StatusCode :: BadRequest ,
114
+ MediaType :: PlainText ,
108
115
Body :: new ( VmmMmdsError :: InvalidURI . to_string ( ) ) ,
109
116
) ;
110
117
}
@@ -125,6 +132,7 @@ fn respond_to_request_mmdsv1(mmds: &Mmds, request: Request) -> Response {
125
132
let mut response = build_response (
126
133
request. http_version ( ) ,
127
134
StatusCode :: MethodNotAllowed ,
135
+ MediaType :: PlainText ,
128
136
Body :: new ( VmmMmdsError :: MethodNotAllowed . to_string ( ) ) ,
129
137
) ;
130
138
response. allow_method ( Method :: Get ) ;
@@ -141,6 +149,7 @@ fn respond_to_request_mmdsv2(mmds: &mut Mmds, request: Request) -> Response {
141
149
return build_response (
142
150
request. http_version ( ) ,
143
151
StatusCode :: BadRequest ,
152
+ MediaType :: PlainText ,
144
153
Body :: new ( err. to_string ( ) ) ,
145
154
) ;
146
155
}
@@ -154,6 +163,7 @@ fn respond_to_request_mmdsv2(mmds: &mut Mmds, request: Request) -> Response {
154
163
let mut response = build_response (
155
164
request. http_version ( ) ,
156
165
StatusCode :: MethodNotAllowed ,
166
+ MediaType :: PlainText ,
157
167
Body :: new ( VmmMmdsError :: MethodNotAllowed . to_string ( ) ) ,
158
168
) ;
159
169
response. allow_method ( Method :: Get ) ;
@@ -176,6 +186,7 @@ fn respond_to_get_request_checked(
176
186
return build_response (
177
187
request. http_version ( ) ,
178
188
StatusCode :: Unauthorized ,
189
+ MediaType :: PlainText ,
179
190
Body :: new ( error_msg) ,
180
191
) ;
181
192
}
@@ -187,6 +198,7 @@ fn respond_to_get_request_checked(
187
198
Ok ( false ) => build_response (
188
199
request. http_version ( ) ,
189
200
StatusCode :: Unauthorized ,
201
+ MediaType :: PlainText ,
190
202
Body :: new ( VmmMmdsError :: InvalidToken . to_string ( ) ) ,
191
203
) ,
192
204
Err ( _) => unreachable ! ( ) ,
@@ -200,10 +212,13 @@ fn respond_to_get_request_unchecked(mmds: &Mmds, request: Request) -> Response {
200
212
// sanitize the URI.
201
213
let json_path = sanitize_uri ( uri. to_string ( ) ) ;
202
214
203
- match mmds. get_value ( json_path, request. headers . accept ( ) . into ( ) ) {
215
+ let content_type = request. headers . accept ( ) ;
216
+
217
+ match mmds. get_value ( json_path, content_type. into ( ) ) {
204
218
Ok ( response_body) => build_response (
205
219
request. http_version ( ) ,
206
220
StatusCode :: OK ,
221
+ content_type,
207
222
Body :: new ( response_body) ,
208
223
) ,
209
224
Err ( err) => match err {
@@ -212,17 +227,20 @@ fn respond_to_get_request_unchecked(mmds: &Mmds, request: Request) -> Response {
212
227
build_response (
213
228
request. http_version ( ) ,
214
229
StatusCode :: NotFound ,
230
+ MediaType :: PlainText ,
215
231
Body :: new ( error_msg) ,
216
232
)
217
233
}
218
234
MmdsError :: UnsupportedValueType => build_response (
219
235
request. http_version ( ) ,
220
236
StatusCode :: NotImplemented ,
237
+ MediaType :: PlainText ,
221
238
Body :: new ( err. to_string ( ) ) ,
222
239
) ,
223
240
MmdsError :: DataStoreLimitExceeded => build_response (
224
241
request. http_version ( ) ,
225
242
StatusCode :: PayloadTooLarge ,
243
+ MediaType :: PlainText ,
226
244
Body :: new ( err. to_string ( ) ) ,
227
245
) ,
228
246
_ => unreachable ! ( ) ,
@@ -248,6 +266,7 @@ fn respond_to_put_request(
248
266
return build_response (
249
267
request. http_version ( ) ,
250
268
StatusCode :: BadRequest ,
269
+ MediaType :: PlainText ,
251
270
Body :: new ( error_msg) ,
252
271
) ;
253
272
}
@@ -262,6 +281,7 @@ fn respond_to_put_request(
262
281
return build_response (
263
282
request. http_version ( ) ,
264
283
StatusCode :: NotFound ,
284
+ MediaType :: PlainText ,
265
285
Body :: new ( error_msg) ,
266
286
) ;
267
287
}
@@ -273,6 +293,7 @@ fn respond_to_put_request(
273
293
return build_response (
274
294
request. http_version ( ) ,
275
295
StatusCode :: BadRequest ,
296
+ MediaType :: PlainText ,
276
297
Body :: new ( VmmMmdsError :: NoTtlProvided . to_string ( ) ) ,
277
298
) ;
278
299
}
@@ -281,15 +302,16 @@ fn respond_to_put_request(
281
302
// Generate token.
282
303
let result = mmds. generate_token ( ttl_seconds) ;
283
304
match result {
284
- Ok ( token) => {
285
- let mut response =
286
- build_response ( request . http_version ( ) , StatusCode :: OK , Body :: new ( token ) ) ;
287
- response . set_content_type ( MediaType :: PlainText ) ;
288
- response
289
- }
305
+ Ok ( token) => build_response (
306
+ request . http_version ( ) ,
307
+ StatusCode :: OK ,
308
+ MediaType :: PlainText ,
309
+ Body :: new ( token ) ,
310
+ ) ,
290
311
Err ( err) => build_response (
291
312
request. http_version ( ) ,
292
313
StatusCode :: BadRequest ,
314
+ MediaType :: PlainText ,
293
315
Body :: new ( err. to_string ( ) ) ,
294
316
) ,
295
317
}
@@ -343,6 +365,31 @@ mod tests {
343
365
}"#
344
366
}
345
367
368
+ fn get_plain_text_data ( ) -> & ' static str {
369
+ "age\n name/\n phones/"
370
+ }
371
+
372
+ fn generate_request_and_expected_response (
373
+ request_bytes : & [ u8 ] ,
374
+ media_type : MediaType ,
375
+ ) -> ( Request , Response ) {
376
+ let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
377
+
378
+ let mut response = Response :: new ( Version :: Http10 , StatusCode :: OK ) ;
379
+ response. set_content_type ( media_type) ;
380
+ let body = match media_type {
381
+ MediaType :: ApplicationJson => {
382
+ let mut body = get_json_data ( ) . to_string ( ) ;
383
+ body. retain ( |c| !c. is_whitespace ( ) ) ;
384
+ body
385
+ }
386
+ MediaType :: PlainText => get_plain_text_data ( ) . to_string ( ) ,
387
+ } ;
388
+ response. set_body ( Body :: new ( body) ) ;
389
+
390
+ ( request, response)
391
+ }
392
+
346
393
#[ test]
347
394
fn test_sanitize_uri ( ) {
348
395
let sanitized = "/a/b/c/d" ;
@@ -362,6 +409,66 @@ mod tests {
362
409
assert_eq ! ( sanitize_uri( "//aa//bb///cc//d" . to_owned( ) ) , "/aa/bb/cc/d" ) ;
363
410
}
364
411
412
+ #[ test]
413
+ fn test_request_accept_header ( ) {
414
+ // This test validates the response `Content-Type` header and the response content for
415
+ // various request `Accept` headers.
416
+
417
+ // Populate MMDS with data.
418
+ let mmds = populate_mmds ( ) ;
419
+
420
+ // Test without `Accept` header. micro-http defaults to `Accept: text/plain`.
421
+ let ( request, expected_response) = generate_request_and_expected_response (
422
+ b"GET http://169.254.169.254/ HTTP/1.0\r \n \r \n " ,
423
+ MediaType :: PlainText ,
424
+ ) ;
425
+ assert_eq ! (
426
+ convert_to_response( mmds. clone( ) , request) ,
427
+ expected_response
428
+ ) ;
429
+
430
+ // Test with empty `Accept` header. micro-http defaults to `Accept: text/plain`.
431
+ let ( request, expected_response) = generate_request_and_expected_response (
432
+ b"GET http://169.254.169.254/ HTTP/1.0\r \n \"
433
+ Accept:\r \n \r \n " ,
434
+ MediaType :: PlainText ,
435
+ ) ;
436
+ assert_eq ! (
437
+ convert_to_response( mmds. clone( ) , request) ,
438
+ expected_response
439
+ ) ;
440
+
441
+ // Test with `Accept: */*` header.
442
+ let ( request, expected_response) = generate_request_and_expected_response (
443
+ b"GET http://169.254.169.254/ HTTP/1.0\r \n \"
444
+ Accept: */*\r \n \r \n " ,
445
+ MediaType :: PlainText ,
446
+ ) ;
447
+ assert_eq ! (
448
+ convert_to_response( mmds. clone( ) , request) ,
449
+ expected_response
450
+ ) ;
451
+
452
+ // Test with `Accept: text/plain`.
453
+ let ( request, expected_response) = generate_request_and_expected_response (
454
+ b"GET http://169.254.169.254/ HTTP/1.0\r \n \
455
+ Accept: text/plain\r \n \r \n ",
456
+ MediaType :: PlainText ,
457
+ ) ;
458
+ assert_eq ! (
459
+ convert_to_response( mmds. clone( ) , request) ,
460
+ expected_response
461
+ ) ;
462
+
463
+ // Test with `Accept: application/json`.
464
+ let ( request, expected_response) = generate_request_and_expected_response (
465
+ b"GET http://169.254.169.254/ HTTP/1.0\r \n \
466
+ Accept: application/json\r \n \r \n ",
467
+ MediaType :: ApplicationJson ,
468
+ ) ;
469
+ assert_eq ! ( convert_to_response( mmds, request) , expected_response) ;
470
+ }
471
+
365
472
#[ test]
366
473
fn test_respond_to_request_mmdsv1 ( ) {
367
474
// Populate MMDS with data.
@@ -381,6 +488,7 @@ mod tests {
381
488
let request_bytes = b"GET http://169.254.169.254/invalid HTTP/1.0\r \n \r \n " ;
382
489
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
383
490
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: NotFound ) ;
491
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
384
492
expected_response. set_body ( Body :: new (
385
493
VmmMmdsError :: ResourceNotFound ( String :: from ( "/invalid" ) ) . to_string ( ) ,
386
494
) ) ;
@@ -391,6 +499,7 @@ mod tests {
391
499
let request_bytes = b"GET /age HTTP/1.1\r \n \r \n " ;
392
500
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
393
501
let mut expected_response = Response :: new ( Version :: Http11 , StatusCode :: NotImplemented ) ;
502
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
394
503
let body = "Cannot retrieve value. The value has an unsupported type." . to_string ( ) ;
395
504
expected_response. set_body ( Body :: new ( body) ) ;
396
505
let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
@@ -403,6 +512,7 @@ mod tests {
403
512
let request = Request :: try_from ( request_bytes. as_bytes ( ) , None ) . unwrap ( ) ;
404
513
let mut expected_response =
405
514
Response :: new ( Version :: Http10 , StatusCode :: MethodNotAllowed ) ;
515
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
406
516
expected_response. set_body ( Body :: new ( VmmMmdsError :: MethodNotAllowed . to_string ( ) ) ) ;
407
517
expected_response. allow_method ( Method :: Get ) ;
408
518
let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
@@ -413,6 +523,7 @@ mod tests {
413
523
let request_bytes = b"GET http:// HTTP/1.0\r \n \r \n " ;
414
524
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
415
525
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: BadRequest ) ;
526
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
416
527
expected_response. set_body ( Body :: new ( VmmMmdsError :: InvalidURI . to_string ( ) ) ) ;
417
528
let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
418
529
assert_eq ! ( actual_response, expected_response) ;
@@ -458,6 +569,7 @@ mod tests {
458
569
let request_bytes = b"PATCH http://169.254.169.255/ HTTP/1.0\r \n \r \n " ;
459
570
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
460
571
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: MethodNotAllowed ) ;
572
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
461
573
expected_response. set_body ( Body :: new ( VmmMmdsError :: MethodNotAllowed . to_string ( ) ) ) ;
462
574
expected_response. allow_method ( Method :: Get ) ;
463
575
expected_response. allow_method ( Method :: Put ) ;
@@ -470,6 +582,7 @@ mod tests {
470
582
X-metadata-token-ttl-seconds: application/json\r \n \r \n " ;
471
583
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
472
584
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: BadRequest ) ;
585
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
473
586
expected_response. set_body ( Body :: new (
474
587
"Invalid header. Reason: Invalid value. Key:X-metadata-token-ttl-seconds; \
475
588
Value:application/json"
@@ -484,6 +597,7 @@ mod tests {
484
597
X-Forwarded-For: 203.0.113.195\r \n \r \n ";
485
598
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
486
599
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: BadRequest ) ;
600
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
487
601
expected_response. set_body ( Body :: new (
488
602
"Invalid header. Reason: Unsupported header name. Key: X-Forwarded-For" . to_string ( ) ,
489
603
) ) ;
@@ -495,6 +609,7 @@ mod tests {
495
609
X-metadata-token-ttl-seconds: 60\r \n \r \n ";
496
610
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
497
611
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: NotFound ) ;
612
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
498
613
expected_response. set_body ( Body :: new (
499
614
VmmMmdsError :: ResourceNotFound ( String :: from ( "/token" ) ) . to_string ( ) ,
500
615
) ) ;
@@ -511,6 +626,7 @@ mod tests {
511
626
) ;
512
627
let request = Request :: try_from ( request_bytes. as_bytes ( ) , None ) . unwrap ( ) ;
513
628
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: BadRequest ) ;
629
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
514
630
let error_msg = format ! (
515
631
"Invalid time to live value provided for token: {}. Please provide a value \
516
632
between {} and {}.",
@@ -525,6 +641,7 @@ mod tests {
525
641
let request_bytes = b"PUT http://169.254.169.254/latest/api/token HTTP/1.0\r \n \r \n " ;
526
642
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
527
643
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: BadRequest ) ;
644
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
528
645
expected_response. set_body ( Body :: new ( VmmMmdsError :: NoTtlProvided . to_string ( ) ) ) ;
529
646
let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
530
647
assert_eq ! ( actual_response, expected_response) ;
@@ -559,6 +676,7 @@ mod tests {
559
676
) ;
560
677
let request = Request :: try_from ( request_bytes. as_bytes ( ) , None ) . unwrap ( ) ;
561
678
let mut expected_response = Response :: new ( Version :: Http11 , StatusCode :: NotImplemented ) ;
679
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
562
680
let body = "Cannot retrieve value. The value has an unsupported type." . to_string ( ) ;
563
681
expected_response. set_body ( Body :: new ( body) ) ;
564
682
let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
@@ -571,6 +689,7 @@ mod tests {
571
689
) ;
572
690
let request = Request :: try_from ( request_bytes. as_bytes ( ) , None ) . unwrap ( ) ;
573
691
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: NotFound ) ;
692
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
574
693
expected_response. set_body ( Body :: new (
575
694
VmmMmdsError :: ResourceNotFound ( String :: from ( "/invalid" ) ) . to_string ( ) ,
576
695
) ) ;
@@ -581,6 +700,7 @@ mod tests {
581
700
let request_bytes = b"GET http://169.254.169.254/ HTTP/1.0\r \n \r \n " ;
582
701
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
583
702
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: Unauthorized ) ;
703
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
584
704
expected_response. set_body ( Body :: new ( VmmMmdsError :: NoTokenProvided . to_string ( ) ) ) ;
585
705
let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
586
706
assert_eq ! ( actual_response, expected_response) ;
@@ -590,6 +710,7 @@ mod tests {
590
710
X-metadata-token: foo\r \n \r \n ";
591
711
let request = Request :: try_from ( request_bytes, None ) . unwrap ( ) ;
592
712
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: Unauthorized ) ;
713
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
593
714
expected_response. set_body ( Body :: new ( VmmMmdsError :: InvalidToken . to_string ( ) ) ) ;
594
715
let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
595
716
assert_eq ! ( actual_response, expected_response) ;
@@ -614,6 +735,7 @@ mod tests {
614
735
) ;
615
736
let request = Request :: try_from ( request_bytes. as_bytes ( ) , None ) . unwrap ( ) ;
616
737
let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: Unauthorized ) ;
738
+ expected_response. set_content_type ( MediaType :: PlainText ) ;
617
739
expected_response. set_body ( Body :: new ( VmmMmdsError :: InvalidToken . to_string ( ) ) ) ;
618
740
let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
619
741
assert_eq ! ( actual_response, expected_response) ;
0 commit comments