Request Forwarding / Proxy Servlet

3,841 views
Skip to first unread message

alexander anguiano

unread,
May 8, 2014, 11:29:38 AM5/8/14
to dropwiz...@googlegroups.com
I have several dropwizard services.  I have ApplicationService that calls Service1 and Service2.   

ApplicationServices listens on 8050
Service1 listens on 8052
Service2 listens onf 8054

Service1 implements
POST /service1/computers

i'd like the client to only communicate to 8050 and it needs to make a call to 

POST /service1/computers

How do i get forwarding or proxying to work in Dropwizard.



I know there is a ProxyServlet in jetty how do i use it in DropWizard


PS I looked at the cross origin and i think that will cause a lot more problems to be solved.

Thanks
 

Shan Syed

unread,
May 8, 2014, 11:37:18 AM5/8/14
to dropwiz...@googlegroups.com
a few options:

- setup a reverse proxy (httpd or nginx), so your client knows only about one server - your dropwizard services then sit behind this, and you control what goes where (ex: http://www.jamescoyle.net/how-to/116-simple-apache-reverse-proxy-example)

- you write code in "ApplicationService" to simply call Service1 or Service2, a la: https://dropwizard.github.io/dropwizard/manual/client.html
there will be duplication of sorts, but it's up to you to figure out if that's a problem or not

eventually an "automagic" request brokering thing would be neat (kind of like what an enterprise service bus does)



--
You received this message because you are subscribed to the Google Groups "dropwizard-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dropwizard-us...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jochen Schalanda

unread,
May 8, 2014, 11:38:28 AM5/8/14
to dropwiz...@googlegroups.com
Hi Alexander,

On 08.05.2014 17:29, alexander anguiano wrote:
> How do i get forwarding or proxying to work in Dropwizard.

You can simply add Jetty's ProxyServlet or ProxyServlet.Transparent [1]
to your ServletEnvironment [2] (via Environment#servlets() [3]).


> PS I looked at the cross origin and i think that will cause a lot more
> problems to be solved.

Maybe Jetty's Cross Origin Filter can help you there.


[1]:
http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/proxy/ProxyServlet.Transparent.html
[2]:
https://joschi.github.io/dropwizard/0.7.0/dropwizard-jetty/apidocs/io/dropwizard/jetty/setup/ServletEnvironment.html#addServlet-java.lang.String-java.lang.Class-
[3]:
https://joschi.github.io/dropwizard/0.7.0/dropwizard-core/apidocs/io/dropwizard/setup/Environment.html#servlets--
[4]:
http://www.eclipse.org/jetty/documentation/current/cross-origin-filter.html


Cheers,
Jochen

Shan Syed

unread,
May 8, 2014, 11:47:45 AM5/8/14
to dropwiz...@googlegroups.com
holy moley, this ProxyServlet is something that I should have known about a year ago
serves me right for not really trying to get comfortable with Jetty directly


alexander anguiano

unread,
May 8, 2014, 12:51:19 PM5/8/14
to dropwiz...@googlegroups.com
Does this work in the 0.62 release?  

I did this

ServletBuilder sb = environment.addServlet(ProxyServlet.Transparent.class, "/service1/*");
sb.setInitParam("ProxyTo","http://host1:8052/");
sb.setInitParam("Prefix", "/service1");

and it get to other service but the root is missing,  it gets


[08/May/2014:16:40:50 +0000] "GET / HTTP/1.1" 405 1336 6 6

instead of 

[08/May/2014:16:40:50 +0000] "GET /service1 HTTP/1.1" 405 1336 6 6

Christopher Elkins

unread,
May 8, 2014, 1:00:42 PM5/8/14
to dropwiz...@googlegroups.com
On May 8, 2014, at 9:51 AM, alexander anguiano <job...@gmail.com> wrote:

Does this work in the 0.62 release?  

I did this

ServletBuilder sb = environment.addServlet(ProxyServlet.Transparent.class, "/service1/*");
sb.setInitParam("ProxyTo","http://host1:8052/");
sb.setInitParam("Prefix", "/service1");

Assuming they’re not just email typos, those parameter names are incorrect. They should be “proxyTo” and “prefix” respectively (initial lower-case).


and it get to other service but the root is missing,  it gets


[08/May/2014:16:40:50 +0000] "GET / HTTP/1.1" 405 1336 6 6

instead of 

[08/May/2014:16:40:50 +0000] "GET /service1 HTTP/1.1" 405 1336 6 6


-- 
Christopher Elkins


alexander anguiano

unread,
May 8, 2014, 3:04:05 PM5/8/14
to dropwiz...@googlegroups.com
I replace the parameters one at a time.  

ProxyTo -> proxyTo = ...
DEBUG [2014-05-08 18:34:36,260] org.eclipse.jetty.servlet.ServletHandler: 
! javax.servlet.UnavailableException: ProxyTo parameter is requred.
! at org.eclipse.jetty.servlets.ProxyServlet$Transparent.init(ProxyServlet.java:873) ~[jetty-servlets-8.1.8.v20121106.jar:8.1.8.v20121106]

Prefix -> prefix = ....
WARN  [2014-05-08 18:36:26,495] /: unavailable
! javax.servlet.UnavailableException: Prefix parameter must start with a '/'.

The parameters seem to be correct.   I guess I can upgrade this dropwizard project to .70 to see if that works



WARN  [2014-05-08 18:36:26,495] /: unavailable
! javax.servlet.UnavailableException: Prefix parameter must start with a '/'.

Christopher Elkins

unread,
May 8, 2014, 3:47:36 PM5/8/14
to dropwiz...@googlegroups.com
Sorry, I overlooked the version number.

As penance, I am providing working examples for both 0.7.0 and 0.6.2 respectively:


-- 
Christopher Elkins

alexander anguiano

unread,
May 9, 2014, 9:10:41 AM5/9/14
to dropwiz...@googlegroups.com
Thanks for the projects! 

I've got it mostly working.  The only problem is the urls

I expect


This is what have to do to hit the proxy

http://localhost:8082/application/computers/computers that gets forward to http://localhost:/computers

how do i get rid of the extra application/computers path

alexander anguiano

unread,
May 9, 2014, 4:47:29 PM5/9/14
to dropwiz...@googlegroups.com
Here an update on this.

I need to be able to setup the servlet at the root.  It looks like i have to use the root.war file to do this.  Does anybody know how to access the root of jetty programmatically.

The reason is the service1 rest interface returns links.  The proxy is returing the correct server and port, in the link of a resource the path is as if i called the server 1 correctly.

alexander anguiano

unread,
May 9, 2014, 5:07:13 PM5/9/14
to dropwiz...@googlegroups.com
I have another idea, Is it possible to setup more than one application context in a dropwizard?  

I guess that means setting up two  or more io.dropwizard.Application 

Christopher Elkins

unread,
May 9, 2014, 6:30:07 PM5/9/14
to dropwiz...@googlegroups.com
That’s possible (in 0.7 at least), but you’ll need to configure the Jersey servlet to use a different mapping or disable it altogether. For example,

    @Override
    public void run(final ExampleConfiguration configuration, final Environment environment) throws Exception {
        environment.jersey().setUrlPattern(“/somepath");
        //environment.jersey().disable();

        final ProxyServlet.Transparent proxyServlet = new ProxyServlet.Transparent(“http://localhost:8080/",”/");
        environment.servlets().addServlet("ProxyServlet", proxyServlet).addMapping("/*");
    }

-- 
Christopher Elkins

alexander anguiano

unread,
May 9, 2014, 6:52:48 PM5/9/14
to dropwiz...@googlegroups.com
Sorry, i don't understand.

This what i need
GET http://localhost:8082/rest1/service1  -> server by application1
GET http://localhost:8082/rest2/service2 -> forward to http://localhost:8080:/rest2/service2

and probably eventually another proxy

 I'm trying to use it part microservices.  i have a main application that has one port that the client will communicate too.  I have 2 other services that return json object with links.  The links have the path of the other dropwizard application

Abdullahi Egal

unread,
May 12, 2014, 7:46:07 AM5/12/14
to dropwiz...@googlegroups.com
Hi,

I had a similar issue, and I created a dropwizard service for it: https://github.com/abduegal/dropwizard-DDSL-service

It workes in the following use case:
You can have 4 identical authentication services running on: 127.0.0.1/xxxx/api/auth.
You can also have 3 identical calculation services running on: 127.0.0.1/xxxx/api/calc.
These 7 services are hosted on different ports (and maybe on different hosts aswell)
The load balancer is hosted for example on port 7080 and on hostname: 127.0.0.1
The result will then be as follow:
127.0.0.1:7080/api/auth will resolve to: the authentication services 
127.0.0.1:7080/api/calc will resolve to: the calculation services.

Im currentlty using this for my microservices.

Sincerely,
Abdullahi Egal


Op zaterdag 10 mei 2014 00:52:48 UTC+2 schreef alexander anguiano:

alexander anguiano

unread,
May 12, 2014, 11:00:28 AM5/12/14
to dropwiz...@googlegroups.com
Thanks!

alexander anguiano

unread,
May 12, 2014, 2:58:25 PM5/12/14
to dropwiz...@googlegroups.com

Ok, this is how to make it work in 0.6.2 ....



Two services

http://localhost:8082/api/application

http://localhost:8080/api/service2

 

Calls on application

GET http://localhost:8082/api/application/app1

 

Calls that get forward to service2 but from application uri

GET http://localhost:8082/api/service2 

 

The links have the application server name and port and correct

 

 

Need to add this to you pom

 

<dependency>

<groupId>org.eclipse.jetty</groupId>

<artifactId>jetty-servlets</artifactId>

<version>8.1.10.v20130312</version>

</dependency>

 

import org.eclipse.jetty.servlets.ProxyServlet;

 

public class ApplicationService extends Service<ApplicationConfiguration> {

@Override

public void run(ApplicationConfiguration configuration, Environment environment)

throws Exception {

ServletBuilder sb = environment.addServlet(ProxyServlet.Transparent.class, "/api/service2/*");

sb.setInitParam("ProxyTo","http://service2_computer:8080/");

sb.setInitParam("Prefix", "/");

Natan Abolafya

unread,
Sep 5, 2014, 11:29:31 AM9/5/14
to dropwiz...@googlegroups.com
Hi there!

I'm not sure if I should have created a new post instead of bumping this up but this felt better. If not, apologies..

As we are somewhere between using nginx or ProxyServlets for the use-case mentioned by the OP, we decided to give ProxyServlet a chance since it will give us the flexibility to play around with the requests in the future if we need to.
But we don't want to give up the performance for that, so we decided to benchmark both solutions simply by using Apache Benchmark.

Non-concurrent requests seem to be fine however it gets strange when we try concurrent requests. What happens is that, whatever the request size is, towards the end it gets timeout. Here is a list of concurrent tests and their results by Apache Benchmark:

And this is how it looks with non-concurrent requests:

It looks like it's something kinky with Apache Benchmark but it actually works fine with nginx.

My question is, why? What's happening?


Here is relevant pieces.

Gradle

compile 'org.eclipse.jetty:jetty-proxy:9.0.7.v20131107'
compile 'io.dropwizard:dropwizard-core:0.7.0'

Application.run()
  1. environment.jersey().disable();
  2.  
  3. final ProxyServlet.Transparent proxyServlet = new ProxyServlet.Transparent("http://localhost:9030/identity""/testjetty");
  4. environment.servlets().addServlet("ProxyServlet", proxyServlet).addMapping("/testjetty/*");

Lance N.

unread,
Sep 5, 2014, 7:55:24 PM9/5/14
to dropwiz...@googlegroups.com
ProxyServlet must use a thread pool and have a maximum # of threads. I don't know where these are set.

ApacheBench is an old program and is not maintained much. It does not do SSL well. Try Gatling: http://gatling.io/
You can script it in Scala. It has spiffy graphing.

Manuel Chávez Astucuri

unread,
Apr 19, 2015, 8:41:38 PM4/19/15
to dropwiz...@googlegroups.com
How to add authentication to proxied request?, I'm trying to build an api gateway with auth/auth, it would be ideal if I could filter proxied requests.
Reply all
Reply to author
Forward
0 new messages