Address list / Mirror list / fallback logic could be entirely within the
HttpClient layer, proxy isn't involved there.


Joakim Erdfelt / [email protected]

On Wed, Sep 27, 2017 at 2:22 PM, Steven Schlansker <
[email protected]> wrote:

>
> > On Sep 26, 2017, at 5:05 PM, Joakim Erdfelt <[email protected]> wrote:
> >
> > modifying the request or response during proxy is also supported out of
> the box by the ...
> > org.eclipse.jetty.proxy.AsyncMiddleManServlet
> >
> > https://github.com/eclipse/jetty.project/blob/jetty-9.4.
> x/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/
> AsyncMiddleManServlet.java
> >
>
> This is getting much closer to what I need.  The big thing that's missing,
> we have a custom
> service resolution protocol layered on top of DNS; I have a list of URIs
> to attempt
> and if there is a failure before the request content is sent (for example,
> socket
> timeout, no route to host, connection refused) I then want to try the next
> in the list
> until we have a success or the operation times out.
>
> (Once we write the request, we do not do further retries)
>
> My initial attempt was to implement this as a custom HttpDestination
> subclass and
> subclass of SocketAddressResolver.Async that returns many
> InetSocketAddresses;
> unfortunately the resolver does not receive the Destination and similarly
> the
> Request gets no knowledge of which address ends up getting picked.
>
> I tried prying open the HttpConversation and HttpExchange objects by the
> usual blind downcasts,
> but it was seemingly not possible to figure out the actual endpoint
> selected.
>
> Not knowing the actual destination means we can't log all the information
> we want to.
> So my current approach is the tried and true "while (keepTrying) {
> client.send(...); }"
> which is less elegant but then we know the actual URI we try every time :)
>
>
> The MiddleManServlet takes care of the HTTP proxying beautifully, and you
> are correct
> that I'd rather not replicate that.  But it doesn't look like it does this
> sort of
> retries, and I'm not sure I can plug in to all the right places to collect
> the metrics
> and logging data I need.  I'll play with it though and maybe with some
> cleverly placed
> overrides I can get most of it.
>
> >
> >
> > Joakim Erdfelt / [email protected]
> >
> > On Tue, Sep 26, 2017 at 5:03 PM, Steven Schlansker <
> [email protected]> wrote:
> >
> > > On Sep 26, 2017, at 4:51 PM, Joakim Erdfelt <[email protected]>
> wrote:
> > >
> > > This is what our org.eclipse.jetty.proxy.AsyncProxyServlet already
> does.
> > >
> > > https://github.com/eclipse/jetty.project/blob/jetty-9.4.
> x/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncProxyServlet.java
> > >
> > > Why write your own?
> >
> > Because I did not know this existed :)
> >
> > Also, I do nontrivial rewriting of the request (this is not at all a
> transparent proxy,
> > it is quite invasive) so I will probably not be able to use the code as
> is.
> >
> > But it probably answers my questions and just needs adaptation, so thank
> you very much
> > for the pointer.
> >
> > (This is a lot of complex code!  Asynchronous programming is hard...)
> >
> > >
> > >
> > > Joakim Erdfelt / [email protected]
> > >
> > > On Tue, Sep 26, 2017 at 4:47 PM, Steven Schlansker <
> [email protected]> wrote:
> > > Hi jetty-users,
> > >
> > > Still working on my http proxy :)
> > > Now I'm trying to make sure I've got the content proxying working
> correctly
> > > using both asynchronous servlet as well as NIO nonblocking writing.
> > >
> > > Because both the server and client are pushing notifications at me, I
> believe
> > > I need to implement some sort of transfer queue.  I was hoping that
> I'd end up
> > > in a push-pull situation but ServletOutputStream calls you via a
> WriteListener
> > > and Jetty-Client calls you via a Response.ContentListener.
> > >
> > > Unfortunately, this leaves me in a position where I don't know how to
> get flow
> > > control working.  The client pushes data at me and I don't have a way
> to push back.
> > >
> > > My current pesudocoded approach:
> > >
> > > Deque<Runnable> writes;
> > > volatile boolean complete = false;
> > >
> > > asyncCtx = httpResponse.startAsync();
> > > out = (HttpOutput) httpResponse.getOutputStream();
> > >
> > > writeListener = new WriteListener() {
> > >     synchronized void onWritePossible() { // avoid re-entrance with
> 'synchronized'
> > >         while(out.isReady()) {
> > >             pending = writes.removeFirst();
> > >             if (pending != null) {
> > >                 pending.run();
> > >             } else if (complete && writes.isEmpty()) {
> > >                 asyncCtx.complete();
> > >             } else {
> > >                 return;
> > >             }
> > >         }
> > >     }
> > > };
> > >
> > > out.setWriteListener(writeListener);
> > >
> > > proxyClientRequest.send(new Response.ContentListener() {
> > >     void onContent(ByteBuffer buf, Callback complete) {
> > >         writes.push(() -> {
> > >             out.write(buf);
> > >             complete.succeeded();
> > >         };
> > >         writeListener.onWritePossible();  // See if we can write it
> immediately
> > >     }
> > >
> > >     void onComplete() {
> > >         complete = true;
> > >         writeListener.onWritePossible();
> > >     }
> > > });
> > >
> > > This has the nice property where I don't copy buffers, just keep them
> in a queue
> > > of pending writes -- but I worry that in the case of a slow reader,
> Jetty Client
> > > will continue onContent-pushing buffers at me until I run out of
> memory.
> > >
> > > I could instead use the OutputStreamContentProvider and just read from
> it in the
> > > WriteListener, which might fix the flow control, but that seems likely
> to involve
> > > a number of byte[] copies that I was hoping to avoid.
> > >
> > > What's the right approach to wire up Jetty server to Jetty client with
> full NIO + Async
> > > content proxying, without introducing an intermediate transfer buffer
> that might grow
> > > without bound?  Am I on the right path or am I missing something?
> Thanks for any guidance!
> > >
> > >
> > > _______________________________________________
> > > jetty-users mailing list
> > > [email protected]
> > > To change your delivery options, retrieve your password, or
> unsubscribe from this list, visit
> > > https://dev.eclipse.org/mailman/listinfo/jetty-users
> > >
> > > _______________________________________________
> > > jetty-users mailing list
> > > [email protected]
> > > To change your delivery options, retrieve your password, or
> unsubscribe from this list, visit
> > > https://dev.eclipse.org/mailman/listinfo/jetty-users
> >
> >
> > _______________________________________________
> > jetty-users mailing list
> > [email protected]
> > To change your delivery options, retrieve your password, or unsubscribe
> from this list, visit
> > https://dev.eclipse.org/mailman/listinfo/jetty-users
> >
> > _______________________________________________
> > jetty-users mailing list
> > [email protected]
> > To change your delivery options, retrieve your password, or unsubscribe
> from this list, visit
> > https://dev.eclipse.org/mailman/listinfo/jetty-users
>
>
> _______________________________________________
> jetty-users mailing list
> [email protected]
> To change your delivery options, retrieve your password, or unsubscribe
> from this list, visit
> https://dev.eclipse.org/mailman/listinfo/jetty-users
>
_______________________________________________
jetty-users mailing list
[email protected]
To change your delivery options, retrieve your password, or unsubscribe from 
this list, visit
https://dev.eclipse.org/mailman/listinfo/jetty-users

Reply via email to