pingora icon indicating copy to clipboard operation
pingora copied to clipboard

Is it possible to terminate iteration early in HttpModule

Open Chi-Kai opened this issue 1 year ago • 1 comments

What is the problem your feature solves, or the need it fulfills?

When using the HttpModule , I want to terminate the iteration and immediately return response. Currently, there is no clear way to stop the execution flow within the request_body_filter method and directly response back.

Describe the solution you'd like

I propose implementing a mechanism in the HttpModule to support immediate termination of the request flow and return a response. For example, within the request_body_filter method, if a cache hit is detected, the function should allow setting the response and halting further execution.

The code might look like this:

impl HttpModule for CacheContext {
    async fn request_body_filter(
        &mut self,
        body: &mut Option<Bytes>,
        _end_of_stream: bool,
    ) -> Result<()> {
        if let Some(cache) = Cache::global() {
            if let Ok(Some(cached_response)) = cache.try_cache(&self.query).await {
                info!("HIT! cached_response: {}", cached_response);
                let formatted_response =
                    cache.response_template.replace("%s", &cached_response);
                self.cached_response = Some(formatted_response);

                // Mechanism to terminate further processing and return cached response.
                
            }
        }
        Ok(())
    }
}

Describe alternatives you've considered

Additional context

Chi-Kai avatar Dec 12 '24 09:12 Chi-Kai

We forked pingora internally, add new args Next to Pingora Filter. It works well. Maybe we can add next function like Koa/Gin framework. But this require api breaking.

async fn request_body_filter(
      &mut self,
      body: &mut Option<Bytes>,
      end_of_stream: bool,
      next: RequestBodyFilter<'_>,
  ) -> Result<()> {
      if let Some(cache) = Cache::global() {
          if let Ok(Some(cached_response)) = cache.try_cache(&self.query).await {
              info!("HIT! cached_response: {}", cached_response);
              let formatted_response =
                  cache.response_template.replace("%s", &cached_response);
              self.cached_response = Some(formatted_response);
              return Ok(())
          }
      }
      return next.call(body, end_of_stream).await;
  }

taikulawo avatar Dec 20 '24 02:12 taikulawo