cloudflare / pingora

A library for building fast, reliable and evolvable network services.
Apache License 2.0
21.21k stars 1.17k forks source link

How to get additional input when call new_ctx? #316

Open taikulawo opened 2 months ago

taikulawo commented 2 months ago

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

We use pingora as library, pingora don't listen, just handle stream from another acceptor.

Service::handle_event(pingora_stream, self.inner.clone(), self.close_recv.clone())
            .instrument(pingora_span)
            .await;

In fn new_ctx we need some input from stream to create our Self::CTX

use pingora::{
    proxy::{Session as PingoraSession}
};
struct MyCtx {
    foo: String,
}
fn new_ctx(&self) -> Self::CTX {
    // How I can get info from handle_event?
    let s = MyCtx{
        foo: ??
    };
    Self::CTX { sess: s }
}
async fn upstream_peer(
        &self,
        session: &mut PingoraSession,
        ctx: &mut Self::CTX,
    ) -> pingora::Result<Box<HttpPeer>>
{
    ctx.foo;
}

Describe the solution you'd like

when call new_ctx, add stream as input which come from Service::handle_event, so we can access data in

// MyPingoraStream impl IO trait
struct MyPingoraStream {
    foo: String,
}
fn new_ctx(&self, stream: &dyn Any) -> Self::CTX {
    let pingora_stream = stream.downcast_ref().unwrap();
    let s = MyCtx{
        foo: pingora_stream.foo
    };
    Self::CTX { sess: s }
}

Describe alternatives you've considered

Service::handle_event add another struct foo as input, foo as input when call new_ctx

drcaramelsyrup commented 6 days ago

Thanks for your patience in asking this, and sorry for the delay. Would you mind giving more info on what your use case is for this, like what kind of additional data is necessary and why it's necessary prior to request filters? Regardless of how the stream events are being handled, both the CTX and Session should be available for mutation in the HTTP handling phase callbacks, in the CTX case early_request_filter is available immediately after the struct is created.

taikulawo commented 5 days ago

we have own listener logic, so before http process, we already have some data(local_addr), and need to add to CTX when create it, httpfilter need read that data

drcaramelsyrup commented 3 days ago

I'm confused because early_request_filter accepts both a Session and CTX. If all you need is the Session object to access your extra data, I don't see why you can't set the data in CTX within the http filter itself.

As part of your custom listener logic, presumably you are using an API like set_socket_digest when creating the Stream, so that you can init the local addr in the Session? On a proxy Session, the server_addr API should give you access to that digest's local_addr, so a ctx.local_addr = session.server_addr().unwrap() in the http filter would seem to suffice.