How do I forward to another host?

Splash Forums Rewrite Users How do I forward to another host?

This topic contains 17 replies, has 5 voices, and was last updated by  Lincoln Baxter III 1 year, 7 months ago.

Viewing 15 posts - 1 through 15 (of 18 total)
  • Author
    Posts
  • #24023

    Wim
    Participant

    In our application we have a newer JBOSS server with some legacy servers behind it. Certain request need to be delegated in a transparent way to the legacy servers. I’m trying to use Rewrite for this, but I can’t figure out how to change the host part of the URL:

    I tried this:

                   .addRule()
                    .when(Direction.isInbound().and(Path.matches("{path}/external")))
                    .perform(Log.message(Level.INFO, "external path: {path}")
                            .and(Forward.to("http://externalserver/page"))
                            )
                    .where("path").matches(".*")

    but this gives a bogus URL such as http://localhost/app/path/http:/externalserver/page

    Any suggestions?

    #24024

    Forwards are always processed within the same servlet engine. So you can only forward to another resource on the same server.

    You will have to perform a redirect instead:

    
    .addRule()
    .when(Direction.isInbound().and(Path.matches("{path}/external")))
    .perform(Log.message(Level.INFO, "external path: {path}")
        .and(Redirect.temporary("http://externalserver/page"))
    .where("path").matches(".*")
    

    This will send a redirect response code to the client and the client will then send a separate request to the new URL.

    Does this fit your needs?

    #24026

    Wim
    Participant

    Thank you for your reply.

    The problem with a redirect is –if I’m not mistaken– that the client has to catch it and make another request, while I’m looking for a transparent way. The reason is that our client is coded to use a legacy API over HTTP that has to keep running until we can migrate fully to JBOSS (which will take months/years) and we want to avoid recoding it if possible.

    Is there no way to do this with Rewrite?

    #24028

    So you want some kind of reverse proxy?

    http://en.wikipedia.org/wiki/Reverse_proxy

    #24029

    Wim
    Participant

    Yes. Concretely something that could replace Jetty’s transparent ProxyServlet, but so far I haven’t found anything readily available in Java EE.

    #24031

    I actually have been working on a Proxy configuration for Rewrite, so you might try something like this:

    package org.ocpsoft.redoculous.config;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.Set;
    
    import javax.servlet.ServletOutputStream;
    
    import org.ocpsoft.common.util.Streams;
    import org.ocpsoft.rewrite.config.Operation;
    import org.ocpsoft.rewrite.context.EvaluationContext;
    import org.ocpsoft.rewrite.exception.RewriteException;
    import org.ocpsoft.rewrite.param.ParameterStore;
    import org.ocpsoft.rewrite.param.Parameterized;
    import org.ocpsoft.rewrite.param.ParameterizedPatternBuilder;
    import org.ocpsoft.rewrite.param.RegexParameterizedPatternBuilder;
    import org.ocpsoft.rewrite.servlet.config.HttpOperation;
    import org.ocpsoft.rewrite.servlet.http.event.HttpServletRewrite;
    
    public class Proxy extends HttpOperation implements Parameterized
    {
       private ParameterizedPatternBuilder urlBuilder;
    
       public Proxy(String url)
       {
          this.urlBuilder = new RegexParameterizedPatternBuilder(url);
       }
    
       public static Operation to(String url)
       {
          return new Proxy(url);
       }
    
       @Override
       public void performHttp(HttpServletRewrite event, EvaluationContext context)
       {
          String compiledUrl = urlBuilder.build(event, context);
          InputStream stream = null;
          try {
             URL url = new URL(compiledUrl);
             stream = url.openStream();
             ServletOutputStream responseStream = event.getResponse().getOutputStream();
             Streams.copy(stream, responseStream);
          }
          catch (MalformedURLException e) {
             throw new RewriteException("Could not parse URL [" + compiledUrl + "]", e);
          }
          catch (IOException e) {
             throw new RewriteException("Could read from URL [" + compiledUrl + "]", e);
          }
          finally
          {
             if (stream != null)
             {
                try {
                   stream.close();
                }
                catch (IOException e) {
                   throw new RewriteException("Error closing stream from URL [" + compiledUrl + "]", e);
                }
             }
          }
       }
    
       @Override
       public Set<String> getRequiredParameterNames()
       {
          return urlBuilder.getRequiredParameterNames();
       }
    
       @Override
       public void setParameterStore(ParameterStore store)
       {
          urlBuilder.setParameterStore(store);
       }
    
    }

    The problem, however, is that this is a read-only proxy, and Request/Response headers are not preserved. I am interested in adding this to Rewrite, but until now I didn’t have anyone who was interested in it.

    Would you be interested in working on this? We would then add it to the official product and you would not have to support it (unless you wanted to) 🙂

    I’m sure this would help a lot of people (including myself, since I am trying to use this in one of my pet-projects.)

    ~Lincoln

    #24033

    Wim
    Participant

    Well, to be honest I’m first seeing if any solution already exists, but if I need to write one myself I will let you know.

    #24034

    Of course! And if one does exist, it’s possible that it could easily be wrapped in a Rewrite rule, which would allow you to use it with your normal configuration (and keep it consistent,) which is what I imagine would be the case.

    I pretty much wrote this read-only proxy so that I could get something working quickly, but I want to find the right tool and use that instead.

    #24035

    Wim
    Participant

    Yes 🙂 It’s funny that no standard way is provided in Java EE. It seemed to me my issue isn’t THAT exotic 🙂

    #24047

    Yeah, seriously… story of my life 🙂 But I think we can help solve that! That’s why I created Rewrite in the first place!

    #25408

    rbattenfeld
    Participant

    Hi Lincoln

    I just found your great site! Awesome. I am looking exactly for the same feature. There is an example which works quite well: https://github.com/mitre/HTTP-Proxy-Servlet

    What is the state? I would prever to have this feature in a maintained framework like your rewrite. I saw there is a Git branch called ‘proxy’. If you need help than I can help but I am not the web expert, to be honest.

    Thanks
    Ralf (the one from the Shrinkwrap Decriptor project)

    • This reply was modified 2 years, 8 months ago by  rbattenfeld.
    #25416

    @lincoln: You are doing something very similar in Redoculous, right?

    #25473

    Hey! Sorry for the late reply. Yes, I am working on the Proxy feature, but haven’t merged it in yet. It works very well. I will probably find some time to finish it this week. @rbattenfeld, I’ll let you know.

    #25474

    Okay. It’s done. No tests ported, but I can verify that it works. Tests will have to follow 🙂 As you can see, it’s a half hack, but so far very reliable. Features will need to be added as needed.

    https://github.com/ocpsoft/rewrite/commit/33f738641eaaa36377602a3a2b53bc89e5fe1306

    Example usage:

    
    .addRule()
    .when(Path.matches("/something"))
    .perform(Proxy.to("http://example.com/something-else?foo=bar"))
    

    No extra header support yet. That will have to be added if you need it. It just passes the request through exactly as received, with all original headers and cookies.

    #25477

    Also, you’ll need to use (or build) the snapshot in order to try this out.

Viewing 15 posts - 1 through 15 (of 18 total)

You must be logged in to reply to this topic.

Comments are closed.