pub struct RequestBodyBuffer { /* private fields */ }Expand description
An opaque object that represents the underlying Envoy Http request body buffer. This is used to interact with it from the module code. The buffer consists of multiple slices. Each slice is a contiguous memory region.
This corresponds to either a frame of the request body or the whole body.
This is a shallow wrapper around the raw pointer to the Envoy request body buffer.
TODO: implement the std::io::Read trait for this object.
Implementations§
Source§impl RequestBodyBuffer
impl RequestBodyBuffer
Sourcepub fn slices_count(&self) -> usize
pub fn slices_count(&self) -> usize
Returns the number of slices in the buffer.
Sourcepub fn slices(&self) -> Vec<&mut [u8]>
pub fn slices(&self) -> Vec<&mut [u8]>
Returns the slices of the buffer. The slices are the contiguous memory regions that represent the buffer.
Examples found in repository?
354 fn request_body(
355 &mut self,
356 request_body_frame: &RequestBodyBuffer,
357 end_of_stream: bool,
358 ) -> RequestBodyStatus {
359 println!(
360 "new request body frame: {}",
361 String::from_utf8(request_body_frame.copy()).unwrap()
362 );
363 if !end_of_stream {
364 // Wait for the end of the stream to see the full body.
365 return RequestBodyStatus::StopIterationAndBuffer;
366 }
367
368 // Get the entire request body reference - this does not copy the body.
369 let entire_body = self.envoy_filter_instance.get_request_body_buffer();
370 println!(
371 "entire request body: {}",
372 String::from_utf8(entire_body.copy()).unwrap()
373 );
374
375 // This demonstrates how to use the reader to read the body.
376 let mut reader = entire_body.reader();
377 let mut buf = vec![0; 2];
378 let mut offset = 0;
379 loop {
380 let n = reader.read(&mut buf).unwrap();
381 if n == 0 {
382 break;
383 }
384 println!(
385 "request body read 2 bytes offset at {}: \"{}\"",
386 offset,
387 std::str::from_utf8(&buf[..n]).unwrap()
388 );
389 offset += 2;
390 }
391
392 // Replace the entire body with 'Y' without copying.
393 for i in entire_body.slices() {
394 for j in i {
395 *j = b'X';
396 }
397 }
398 RequestBodyStatus::Continue
399 }Sourcepub fn copy(&self) -> Vec<u8> ⓘ
pub fn copy(&self) -> Vec<u8> ⓘ
Copies the entire buffer into a single contiguous Vec
Examples found in repository?
354 fn request_body(
355 &mut self,
356 request_body_frame: &RequestBodyBuffer,
357 end_of_stream: bool,
358 ) -> RequestBodyStatus {
359 println!(
360 "new request body frame: {}",
361 String::from_utf8(request_body_frame.copy()).unwrap()
362 );
363 if !end_of_stream {
364 // Wait for the end of the stream to see the full body.
365 return RequestBodyStatus::StopIterationAndBuffer;
366 }
367
368 // Get the entire request body reference - this does not copy the body.
369 let entire_body = self.envoy_filter_instance.get_request_body_buffer();
370 println!(
371 "entire request body: {}",
372 String::from_utf8(entire_body.copy()).unwrap()
373 );
374
375 // This demonstrates how to use the reader to read the body.
376 let mut reader = entire_body.reader();
377 let mut buf = vec![0; 2];
378 let mut offset = 0;
379 loop {
380 let n = reader.read(&mut buf).unwrap();
381 if n == 0 {
382 break;
383 }
384 println!(
385 "request body read 2 bytes offset at {}: \"{}\"",
386 offset,
387 std::str::from_utf8(&buf[..n]).unwrap()
388 );
389 offset += 2;
390 }
391
392 // Replace the entire body with 'Y' without copying.
393 for i in entire_body.slices() {
394 for j in i {
395 *j = b'X';
396 }
397 }
398 RequestBodyStatus::Continue
399 }Sourcepub fn reader(&self) -> RequestBodyBufferReader ⓘ
pub fn reader(&self) -> RequestBodyBufferReader ⓘ
Returns a reader that implements the std::io::Read trait.
Examples found in repository?
354 fn request_body(
355 &mut self,
356 request_body_frame: &RequestBodyBuffer,
357 end_of_stream: bool,
358 ) -> RequestBodyStatus {
359 println!(
360 "new request body frame: {}",
361 String::from_utf8(request_body_frame.copy()).unwrap()
362 );
363 if !end_of_stream {
364 // Wait for the end of the stream to see the full body.
365 return RequestBodyStatus::StopIterationAndBuffer;
366 }
367
368 // Get the entire request body reference - this does not copy the body.
369 let entire_body = self.envoy_filter_instance.get_request_body_buffer();
370 println!(
371 "entire request body: {}",
372 String::from_utf8(entire_body.copy()).unwrap()
373 );
374
375 // This demonstrates how to use the reader to read the body.
376 let mut reader = entire_body.reader();
377 let mut buf = vec![0; 2];
378 let mut offset = 0;
379 loop {
380 let n = reader.read(&mut buf).unwrap();
381 if n == 0 {
382 break;
383 }
384 println!(
385 "request body read 2 bytes offset at {}: \"{}\"",
386 offset,
387 std::str::from_utf8(&buf[..n]).unwrap()
388 );
389 offset += 2;
390 }
391
392 // Replace the entire body with 'Y' without copying.
393 for i in entire_body.slices() {
394 for j in i {
395 *j = b'X';
396 }
397 }
398 RequestBodyStatus::Continue
399 }
400
401 fn response_body(
402 &mut self,
403 response_body_frame: &ResponseBodyBuffer,
404 end_of_stream: bool,
405 ) -> ResponseBodyStatus {
406 println!(
407 "new response body frame: {}",
408 String::from_utf8(response_body_frame.copy()).unwrap()
409 );
410 if !end_of_stream {
411 // Wait for the end of the stream to see the full body.
412 return ResponseBodyStatus::StopIterationAndBuffer;
413 }
414
415 // Get the entire response body reference - this does not copy the body.
416 let entire_body = self.envoy_filter_instance.get_response_body_buffer();
417 println!(
418 "entire response body: {}",
419 String::from_utf8(entire_body.copy()).unwrap()
420 );
421
422 // This demonstrates how to use the reader to read the body.
423 let mut reader = entire_body.reader();
424 let mut buf = vec![0; 2];
425 let mut offset = 0;
426 loop {
427 let n = reader.read(&mut buf).unwrap();
428 if n == 0 {
429 break;
430 }
431 println!(
432 "response body read 2 bytes offset at {}: \"{}\"",
433 offset,
434 std::str::from_utf8(&buf[..n]).unwrap()
435 );
436 offset += 2;
437 }
438
439 // Replace the entire body with 'Y' without copying.
440 for i in entire_body.slices() {
441 for j in i {
442 *j = b'Y';
443 }
444 }
445
446 ResponseBodyStatus::Continue
447 }
448}
449
450/// BodiesReplaceFilter is a filter that replaces request/response bodies.
451///
452/// This implements the [`HttpFilter`] trait, and will be created per each filter chain.
453struct BodiesReplace {}
454
455impl HttpFilter for BodiesReplace {
456 fn new_instance(
457 &mut self,
458 envoy_filter_instance: EnvoyFilterInstance,
459 ) -> Box<dyn HttpFilterInstance> {
460 Box::new(BodiesReplaceInstance {
461 envoy_filter_instance,
462 request_append: String::new(),
463 request_prepend: String::new(),
464 request_replace: String::new(),
465 response_append: String::new(),
466 response_prepend: String::new(),
467 response_replace: String::new(),
468 })
469 }
470}
471
472/// BodiesReplaceInstance is a filter instance that replaces request/response bodies.
473///
474/// This implements the [`HttpFilterInstance`] trait, and will be created per each request.
475struct BodiesReplaceInstance {
476 envoy_filter_instance: EnvoyFilterInstance,
477 request_append: String,
478 request_prepend: String,
479 request_replace: String,
480 response_append: String,
481 response_prepend: String,
482 response_replace: String,
483}
484
485impl HttpFilterInstance for BodiesReplaceInstance {
486 fn request_headers(
487 &mut self,
488 request_headers: &RequestHeaders,
489 _end_of_stream: bool,
490 ) -> RequestHeadersStatus {
491 if let Some(value) = request_headers.get(b"append") {
492 self.request_append = std::str::from_utf8(value).unwrap().to_string();
493 }
494 if let Some(value) = request_headers.get(b"prepend") {
495 self.request_prepend = std::str::from_utf8(value).unwrap().to_string();
496 }
497 if let Some(value) = request_headers.get(b"replace") {
498 self.request_replace = std::str::from_utf8(value).unwrap().to_string();
499 }
500 request_headers.remove(b"content-length"); // Remove content-length header to avoid mismatch.
501 RequestHeadersStatus::Continue
502 }
503
504 fn request_body(
505 &mut self,
506 _request_body_frame: &RequestBodyBuffer,
507 end_of_stream: bool,
508 ) -> RequestBodyStatus {
509 if !end_of_stream {
510 // Wait for the end of the stream to see the full body.
511 return RequestBodyStatus::StopIterationAndBuffer;
512 }
513
514 let entire_body = self.envoy_filter_instance.get_request_body_buffer();
515 if !self.request_append.is_empty() {
516 entire_body.append(self.request_append.as_bytes());
517 }
518 if !self.request_prepend.is_empty() {
519 entire_body.prepend(self.request_prepend.as_bytes());
520 }
521 if !self.request_replace.is_empty() {
522 entire_body.replace(self.request_replace.as_bytes());
523 }
524 RequestBodyStatus::Continue
525 }
526
527 fn response_headers(
528 &mut self,
529 response_headers: &ResponseHeaders,
530 _end_of_stream: bool,
531 ) -> ResponseHeadersStatus {
532 if let Some(value) = response_headers.get(b"append") {
533 self.response_append = std::str::from_utf8(value).unwrap().to_string();
534 }
535 if let Some(value) = response_headers.get(b"prepend") {
536 self.response_prepend = std::str::from_utf8(value).unwrap().to_string();
537 }
538 if let Some(value) = response_headers.get(b"replace") {
539 self.response_replace = std::str::from_utf8(value).unwrap().to_string();
540 }
541 response_headers.remove(b"content-length"); // Remove content-length header to avoid mismatch.
542 ResponseHeadersStatus::Continue
543 }
544
545 fn response_body(
546 &mut self,
547 _response_body_frame: &ResponseBodyBuffer,
548 end_of_stream: bool,
549 ) -> ResponseBodyStatus {
550 if !end_of_stream {
551 // Wait for the end of the stream to see the full body.
552 return ResponseBodyStatus::StopIterationAndBuffer;
553 }
554
555 let entire_body = self.envoy_filter_instance.get_response_body_buffer();
556 if !self.response_append.is_empty() {
557 entire_body.append(self.response_append.as_bytes());
558 }
559 if !self.response_prepend.is_empty() {
560 entire_body.prepend(self.response_prepend.as_bytes());
561 }
562 if !self.response_replace.is_empty() {
563 entire_body.replace(self.response_replace.as_bytes());
564 }
565 ResponseBodyStatus::Continue
566 }
567}
568
569/// SendResponseFilter is a filter that sends a response.
570///
571/// This implements the [`HttpFilter`] trait, and will be created per each filter chain.
572struct SendResponseFilter {}
573
574impl HttpFilter for SendResponseFilter {
575 fn new_instance(
576 &mut self,
577 envoy_filter_instance: EnvoyFilterInstance,
578 ) -> Box<dyn HttpFilterInstance> {
579 Box::new(SendResponseFilterInstance {
580 envoy_filter_instance,
581 on_response_headers: false,
582 })
583 }
584}
585
586/// SendResponseFilterInstance is a filter instance that sends a response.
587///
588/// This implements the [`HttpFilterInstance`] trait, and will be created per each request.
589struct SendResponseFilterInstance {
590 envoy_filter_instance: EnvoyFilterInstance,
591 on_response_headers: bool,
592}
593
594impl HttpFilterInstance for SendResponseFilterInstance {
595 fn request_headers(
596 &mut self,
597 request_headers: &RequestHeaders,
598 _end_of_stream: bool,
599 ) -> RequestHeadersStatus {
600 if let Some(value) = request_headers.get(b":path") {
601 if value == "/on_request".as_bytes() {
602 let headers: Vec<(&[u8], &[u8])> = vec![
603 ("foo".as_bytes(), "bar".as_bytes()),
604 ("bar".as_bytes(), "baz".as_bytes()),
605 ];
606 self.envoy_filter_instance.send_response(
607 401,
608 headers.as_slice(),
609 "local response at request headers".as_bytes(),
610 );
611 }
612 if value == b"/on_response" {
613 self.on_response_headers = true;
614 }
615 }
616 RequestHeadersStatus::Continue
617 }
618
619 fn response_headers(
620 &mut self,
621 _response_headers: &ResponseHeaders,
622 _end_of_stream: bool,
623 ) -> ResponseHeadersStatus {
624 if self.on_response_headers {
625 let headers: Vec<(&[u8], &[u8])> = vec![("dog".as_bytes(), "cat".as_bytes())];
626 self.envoy_filter_instance.send_response(
627 500,
628 headers.as_slice(),
629 "local response at response headers".as_bytes(),
630 );
631 }
632 ResponseHeadersStatus::Continue
633 }
634}
635
636/// ValidateJsonFilter is a filter that validates JSON.
637///
638/// This implements the [`HttpFilter`] trait, and will be created per each filter chain.
639struct ValidateJsonFilter {}
640
641impl HttpFilter for ValidateJsonFilter {
642 fn new_instance(
643 &mut self,
644 envoy_filter_instance: EnvoyFilterInstance,
645 ) -> Box<dyn HttpFilterInstance> {
646 Box::new(ValidateJsonFilterInstance {
647 envoy_filter_instance,
648 })
649 }
650}
651
652/// ValidateJsonFilterInstance is a filter instance that validates JSON.
653///
654/// This implements the [`HttpFilterInstance`] trait, and will be created per each request.
655struct ValidateJsonFilterInstance {
656 envoy_filter_instance: EnvoyFilterInstance,
657}
658
659#[derive(Serialize, Deserialize)]
660struct ValidateJsonFilterBody {
661 foo: String,
662}
663
664impl HttpFilterInstance for ValidateJsonFilterInstance {
665 fn request_body(
666 &mut self,
667 _request_body_frame: &RequestBodyBuffer,
668 end_of_stream: bool,
669 ) -> RequestBodyStatus {
670 if !end_of_stream {
671 // Wait for the end of the stream to see the full body.
672 return RequestBodyStatus::StopIterationAndBuffer;
673 }
674
675 let reader = self
676 .envoy_filter_instance
677 .get_request_body_buffer()
678 .reader();
679
680 match serde_json::from_reader(reader) {
681 Ok(body) => {
682 let _body: ValidateJsonFilterBody = body;
683 }
684 Err(_e) => {
685 self.envoy_filter_instance.send_response(400, &[], &[]);
686 }
687 }
688 RequestBodyStatus::Continue
689 }Sourcepub fn append(&self, data: &[u8])
pub fn append(&self, data: &[u8])
Appends the given data to the buffer.
After this operation, previous slices might be invalidated.
Examples found in repository?
504 fn request_body(
505 &mut self,
506 _request_body_frame: &RequestBodyBuffer,
507 end_of_stream: bool,
508 ) -> RequestBodyStatus {
509 if !end_of_stream {
510 // Wait for the end of the stream to see the full body.
511 return RequestBodyStatus::StopIterationAndBuffer;
512 }
513
514 let entire_body = self.envoy_filter_instance.get_request_body_buffer();
515 if !self.request_append.is_empty() {
516 entire_body.append(self.request_append.as_bytes());
517 }
518 if !self.request_prepend.is_empty() {
519 entire_body.prepend(self.request_prepend.as_bytes());
520 }
521 if !self.request_replace.is_empty() {
522 entire_body.replace(self.request_replace.as_bytes());
523 }
524 RequestBodyStatus::Continue
525 }Sourcepub fn prepend(&self, data: &[u8])
pub fn prepend(&self, data: &[u8])
Prepends the given data to the buffer.
After this operation, previous slices might be invalidated.
Examples found in repository?
504 fn request_body(
505 &mut self,
506 _request_body_frame: &RequestBodyBuffer,
507 end_of_stream: bool,
508 ) -> RequestBodyStatus {
509 if !end_of_stream {
510 // Wait for the end of the stream to see the full body.
511 return RequestBodyStatus::StopIterationAndBuffer;
512 }
513
514 let entire_body = self.envoy_filter_instance.get_request_body_buffer();
515 if !self.request_append.is_empty() {
516 entire_body.append(self.request_append.as_bytes());
517 }
518 if !self.request_prepend.is_empty() {
519 entire_body.prepend(self.request_prepend.as_bytes());
520 }
521 if !self.request_replace.is_empty() {
522 entire_body.replace(self.request_replace.as_bytes());
523 }
524 RequestBodyStatus::Continue
525 }Sourcepub fn drain(&self, size: usize)
pub fn drain(&self, size: usize)
Drains the buffer by the given size.
After this operation, previous slices might be invalidated.
Sourcepub fn replace(&self, data: &[u8])
pub fn replace(&self, data: &[u8])
Replaces the entire buffer with the given data.
After this operation, previous slices might be invalidated.
Examples found in repository?
504 fn request_body(
505 &mut self,
506 _request_body_frame: &RequestBodyBuffer,
507 end_of_stream: bool,
508 ) -> RequestBodyStatus {
509 if !end_of_stream {
510 // Wait for the end of the stream to see the full body.
511 return RequestBodyStatus::StopIterationAndBuffer;
512 }
513
514 let entire_body = self.envoy_filter_instance.get_request_body_buffer();
515 if !self.request_append.is_empty() {
516 entire_body.append(self.request_append.as_bytes());
517 }
518 if !self.request_prepend.is_empty() {
519 entire_body.prepend(self.request_prepend.as_bytes());
520 }
521 if !self.request_replace.is_empty() {
522 entire_body.replace(self.request_replace.as_bytes());
523 }
524 RequestBodyStatus::Continue
525 }Trait Implementations§
Source§impl Clone for RequestBodyBuffer
impl Clone for RequestBodyBuffer
Source§fn clone(&self) -> RequestBodyBuffer
fn clone(&self) -> RequestBodyBuffer
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more