wip: feat: define response body enum
This commit is contained in:
		
					parent
					
						
							
								7cb25a7743
							
						
					
				
			
			
				commit
				
					
						008b62a925
					
				
			
		
					 12 changed files with 215 additions and 104 deletions
				
			
		|  | @ -1,14 +1,10 @@ | |||
| use crate::{ | ||||
|   error::{RpxyError, RpxyResult}, | ||||
|   globals::Globals, | ||||
|   hyper_ext::{ | ||||
|     body::{wrap_incoming_body_response, BoxBody, IncomingOr}, | ||||
|     rt::LocalExecutor, | ||||
|   }, | ||||
|   hyper_ext::{body::ResponseBody, rt::LocalExecutor}, | ||||
|   log::*, | ||||
| }; | ||||
| use async_trait::async_trait; | ||||
| use chrono::Duration; | ||||
| use http::{Request, Response, Version}; | ||||
| use hyper::body::{Body, Incoming}; | ||||
| use hyper_util::client::legacy::{ | ||||
|  | @ -19,10 +15,6 @@ use std::sync::Arc; | |||
| 
 | ||||
| #[cfg(feature = "cache")] | ||||
| use super::cache::{get_policy_if_cacheable, RpxyCache}; | ||||
| #[cfg(feature = "cache")] | ||||
| use crate::hyper_ext::body::{full, wrap_synthetic_body_response}; | ||||
| #[cfg(feature = "cache")] | ||||
| use http_body_util::BodyExt; | ||||
| 
 | ||||
| #[async_trait] | ||||
| /// Definition of the forwarder that simply forward requests from downstream client to upstream app servers.
 | ||||
|  | @ -40,7 +32,7 @@ pub struct Forwarder<C, B> { | |||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl<C, B1> ForwardRequest<B1, IncomingOr<BoxBody>> for Forwarder<C, B1> | ||||
| impl<C, B1> ForwardRequest<B1, ResponseBody> for Forwarder<C, B1> | ||||
| where | ||||
|   C: Send + Sync + Connect + Clone + 'static, | ||||
|   B1: Body + Send + Sync + Unpin + 'static, | ||||
|  | @ -49,7 +41,7 @@ where | |||
| { | ||||
|   type Error = RpxyError; | ||||
| 
 | ||||
|   async fn request(&self, req: Request<B1>) -> Result<Response<IncomingOr<BoxBody>>, Self::Error> { | ||||
|   async fn request(&self, req: Request<B1>) -> Result<Response<ResponseBody>, Self::Error> { | ||||
|     // TODO: cache handling
 | ||||
|     #[cfg(feature = "cache")] | ||||
|     { | ||||
|  | @ -67,38 +59,27 @@ where | |||
|       let res = self.request_directly(req).await; | ||||
| 
 | ||||
|       if self.cache.is_none() { | ||||
|         return res.map(wrap_incoming_body_response::<BoxBody>); | ||||
|         return res.map(|inner| inner.map(ResponseBody::Incoming)); | ||||
|       } | ||||
| 
 | ||||
|       // check cacheability and store it if cacheable
 | ||||
|       let Ok(Some(cache_policy)) = get_policy_if_cacheable(synth_req.as_ref(), res.as_ref().ok()) else { | ||||
|         return res.map(wrap_incoming_body_response::<BoxBody>); | ||||
|         return res.map(|inner| inner.map(ResponseBody::Incoming)); | ||||
|       }; | ||||
|       let (parts, body) = res.unwrap().into_parts(); | ||||
| 
 | ||||
|       // TODO: This is inefficient since current strategy needs to copy the whole body onto memory to cache it.
 | ||||
|       // This should be handled by copying buffer simultaneously while forwarding response to downstream.
 | ||||
|       let Ok(bytes) = body.collect().await.map(|v| v.to_bytes()) else { | ||||
|         return Err(RpxyError::FailedToWriteByteBufferForCache); | ||||
|       }; | ||||
|       let bytes_clone = bytes.clone(); | ||||
|       // Get streamed body without waiting for the arrival of the body,
 | ||||
|       // which is done simultaneously with caching.
 | ||||
|       let stream_body = self | ||||
|         .cache | ||||
|         .as_ref() | ||||
|         .unwrap() | ||||
|         .put(synth_req.unwrap().uri(), body, &cache_policy) | ||||
|         .await?; | ||||
| 
 | ||||
|       // TODO: this is inefficient. needs to be reconsidered to avoid unnecessary copy and should spawn async task to store cache.
 | ||||
|       // We may need to use the same logic as h3.
 | ||||
|       // Is bytes.clone() enough?
 | ||||
| 
 | ||||
|       // if let Err(cache_err) = self
 | ||||
|       //   .cache
 | ||||
|       //   .as_ref()
 | ||||
|       //   .unwrap()
 | ||||
|       //   .put(synth_req.unwrap().uri(), &bytes, &cache_policy)
 | ||||
|       //   .await
 | ||||
|       // {
 | ||||
|       //   error!("{:?}", cache_err);
 | ||||
|       // };
 | ||||
| 
 | ||||
|       // response with cached body
 | ||||
|       Ok(wrap_synthetic_body_response(Response::from_parts(parts, full(bytes)))) | ||||
|       // response with body being cached in background
 | ||||
|       let new_res = Response::from_parts(parts, ResponseBody::Streamed(stream_body)); | ||||
|       Ok(new_res) | ||||
|     } | ||||
| 
 | ||||
|     // No cache handling
 | ||||
|  | @ -107,7 +88,7 @@ where | |||
|       self | ||||
|         .request_directly(req) | ||||
|         .await | ||||
|         .map(wrap_incoming_body_response::<BoxBody>) | ||||
|         .map(|inner| inner.map(ResponseBody::Incoming)) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jun Kurihara
				Jun Kurihara