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
