tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Chet Hosey <ChetHo...@gmail.com>
Subject Re: UriInfo always returning "localhost" in URIs
Date Fri, 08 Feb 2013 13:06:02 GMT
Success!

UriInfo is now using the HTTP request info, both through HTTP and AJP. I've confirmed with
apache-tomee-1.5.2-20130208.041201-63-jaxrs. Absolutely no configuration changes were needed,
either. I unpacked the snapshot, copied the test app to webapps/, ran bin/startup.sh, and
tested.

This is exactly the behavior I'd expected initially, and should allow JAX-RS UriInfo to work
through HTTP and AJP load balancers on TomEE.

Thank you!

-- Chet

On Feb 7, 2013, at 9:08 AM, Romain Manni-Bucau <rmannibucau@gmail.com> wrote:

> oh think i misunderstood, in fact you want the input value so potentially
> the load balancer value, not always the ajp info right?
> 
> so i hope my fix will help
> 
> *Romain Manni-Bucau*
> *Twitter: @rmannibucau <https://twitter.com/rmannibucau>*
> *Blog: **http://rmannibucau.wordpress.com/*<http://rmannibucau.wordpress.com/>
> *LinkedIn: **http://fr.linkedin.com/in/rmannibucau*
> *Github: https://github.com/rmannibucau*
> 
> 
> 
> 2013/2/7 Chet Hosey <ChetHosey@gmail.com>
> 
>> AJP isn't generally exposed to the client at all.
>> 
>> A typical configuration might include a web server such httpd or IIS
>> listening on a public IP on port 80, and several Tomcat instances running
>> AJP on private IP addresses. The web server is configured to route certain
>> requests (like /appname/*) to a running Tomcat instance via AJP. If
>> sessions are clustered, or the conversations are stateless, an
>> administrator shut down an individual Tomcat instance without impacting
>> external users.
>> 
>> So a REST request would be made over HTTP (or HTTPS) to the web server,
>> and routed to one of the Tomcat instances over AJP. There's nothing special
>> about REST that makes AJP inappropriate; it's just a way of connecting a
>> web server to Tomcat. But please consider an HTTP load balancer running on
>> port 80, and sending requests to internal Tomcat instances running on ports
>> 8080, 8081, etc. The client will send requests to port 80. But none of
>> Tomcat servers' connectors will be bound to the same port. It would similar
>> to AJP, in that the public port doesn't match the Tomcat connectors' listen
>> ports. And all communication would be over HTTP.
>> 
>> Even with requests over AJP, for example, a REST method can get an
>> injected HttpServletRequest object. My test code demonstrates that. This is
>> why I believe that the right behavior for UriInfo would be to match the
>> behavior of the HttpServletRequest object. It generally works
>> out-of-the-box, and there are already ways for an administrator to override
>> the values returned by HttpServletRequest without having to alter the
>> application.
>> 
>> I'll try the latest snapshot, and put the AJP connector first as you
>> advise. Please consider, though, that the correct public host / port may
>> never match a connector's configuration, and that it may be better for
>> UriInfo to get these values from an HttpServletRequest than to check the
>> connectors.
>> 
>> Thanks!
>> 
>> On Feb 7, 2013, at 8:14 AM, Romain Manni-Bucau <rmannibucau@gmail.com>
>> wrote:
>> 
>>> updated as possible as it was this feature
>>> 
>>> can you try with the next snapshot please?
>>> 
>>> where i doubt is when using ajp protocol you don't really respect REST
>>> specification which relies on http only.
>>> 
>>> *Romain Manni-Bucau*
>>> *Twitter: @rmannibucau <https://twitter.com/rmannibucau>*
>>> *Blog: **http://rmannibucau.wordpress.com/*<
>> http://rmannibucau.wordpress.com/>
>>> *LinkedIn: **http://fr.linkedin.com/in/rmannibucau*
>>> *Github: https://github.com/rmannibucau*
>>> 
>>> 
>>> 
>>> 2013/2/7 Romain Manni-Bucau <rmannibucau@gmail.com>
>>> 
>>>> Hmm, the point is it needs to select the connector to use for deployment
>>>> (to compute the base address)...not sure of a clever way here
>>>> 
>>>> Can you try to define ajp connector first in server.xml please?
>>>> Le 7 févr. 2013 08:24, "Chet Hosey" <gargantuchet@gmail.com> a écrit
:
>>>> 
>>>> To say that it's "deployed on HTTP" is inaccurate. It's deployed on
>>>>> Tomcat, which TomEE is built around, and which provides more than one
>> type
>>>>> of connector.
>>>>> 
>>>>> It's common to use httpd in front of Tomcat to serve static content,
>>>>> balance between multiple workers, etc. It's reasonable that AJP support
>>>>> might not be ready yet or might have been overlooked.
>>>>> 
>>>>> The statements on the project's website suggest that the goal is to add
>>>>> features to Tomcat without sacrificing functionality:
>>>>> 
>>>>> - Goal: "Simple, Get more from Tomcat without giving anything up."
>>>>> - Focuses: "Don't mess with Tomcat"
>>>>> - TomEE doesn't "include Tomcat in some truncated and stripped-down
>> form"
>>>>> - With TomEE, there's "no picking and choosing individual parts of
>> Tomcat
>>>>> and building a 'new' server leveraging Tomcat."
>>>>> 
>>>>> With such strong language, it would be surprising if the project didn't
>>>>> plan to support AJP connections as it does HTTP.
>>>>> 
>>>>> Might this be addressed in a future release? Can you suggest ways to
>>>>> contribute?
>>>>> 
>>>>> 
>>>>> On Feb 6, 2013, at 5:40 PM, Romain Manni-Bucau <rmannibucau@gmail.com>
>>>>> wrote:
>>>>> 
>>>>>> because the REST service is deployed on HTTP not AJP
>>>>>> 
>>>>>> *Romain Manni-Bucau*
>>>>>> *Twitter: @rmannibucau <https://twitter.com/rmannibucau>*
>>>>>> *Blog: **http://rmannibucau.wordpress.com/*<
>>>>> http://rmannibucau.wordpress.com/>
>>>>>> *LinkedIn: **http://fr.linkedin.com/in/rmannibucau*
>>>>>> *Github: https://github.com/rmannibucau*
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 2013/2/6 Chet Hosey <ChetHosey@gmail.com>
>>>>>> 
>>>>>>> 
>>>>>>> That was my expectation too. But it just isn't working that way
for
>> me
>>>>>>> with AJP.
>>>>>>> 
>>>>>>> Apache httpd is listening on port 8888 and forwarding application
>>>>> requests
>>>>>>> (/rs-test/*) to TomEE via AJP. TomEE is listening on ports 8080
for
>>>>> HTTP
>>>>>>> and 8009 for AJP requests. If the UriInfo matched the request
info,
>>>>> then
>>>>>>> the port number given should be 8080 when loading an app from
TomEE
>>>>>>> directly, and 8888 when using httpd to load the app via AJP.
>>>>>>> 
>>>>>>> When I request http://servername:8080/rs-**test/<
>>>>> http://servername:8080/rs-test/>to get content directly from TomEE
via
>>>>> HTTP, the UriInfo methods match the
>>>>>>> request info, which also matches the server.xml host name and
HTTP
>>>>>>> connector port (8080). But when I request
>> http://servername:8888/rs-**
>>>>>>> test/ <http://servername:8888/rs-test/> to get content
from TomEE
>> over
>>>>>>> AJP, UriInfo still lists the HTTP connector port (8080) instead
of
>> the
>>>>>>> request port (8888). The HttpServletRequest and HttpHeaders objects
>> do
>>>>>>> return the request port, but UriInfo does not.
>>>>>>> 
>>>>>>> What I tried:
>>>>>>> 
>>>>>>> 1. Set up the environment
>>>>>>>      1. export TESTDIR=/tmp/test
>>>>>>>      2. mkdir -p $TESTDIR
>>>>>>>      3. export JDK_HOME=/opt/java/jdk1.7.0_11
>>>>>>>      4. export PATH=$JDK_HOME/bin:$PATH
>>>>>>> 2. Download, build, and install Apache httpd
>>>>>>>      1. Download and unpack httpd-2.2.23.tar.bz2
>>>>>>>      2. cd httpd-2.2.23
>>>>>>>      3. ./configure --prefix=$TESTDIR/httpd
>>>>>>>      4. make && make install
>>>>>>> 3. Download, build, and install mod_jk
>>>>>>>      1. Download and unpack tomcat-connectors-1.2.37-src.**tar.gz
>>>>>>>      2. cd tomcat-connectors-1.2.37-src/**native
>>>>>>>      3. ./configure --with-apxs=$TESTDIR/httpd/**bin/apxs
>>>>>>>      4. make && cp apache-2.0/mod_jk.so $TESTDIR/httpd/modules/
>>>>>>> 4. Download and unpack apache-tomee-1.5.1-jaxrs.tar.**gz
>>>>>>> 5. Configure Apache httpd
>>>>>>>      1. Edit $TESTDIR/httpd/conf/httpd.conf
>>>>>>>            1. Change Listen setting to port 8888 on public IP
>>>>>>>            2. Append the following to load and configure mod_jk:
>>>>>>> 
>>>>>>>         LoadModule jk_module modules/mod_jk.so
>>>>>>>         JkWorkersFile $TESTDIR/httpd/conf/workers.**properties
>>>>>>>         JkShmFile $TESTDIR/httpd/logs/mod_jk.shm
>>>>>>>         JkLogFile $TESTDIR/httpd/logs/mod_jk.log
>>>>>>>         JkLogLevel info
>>>>>>>         JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
>>>>>>>         JkMount /rs-test/* worker1
>>>>>>> 
>>>>>>>      2. Create $TESTDIR/httpd/conf/workers.**properties with
the
>>>>>>>         following content:
>>>>>>> 
>>>>>>>         worker.list=worker1
>>>>>>>         worker.worker1.type=ajp13
>>>>>>>         worker.worker1.host=localhost
>>>>>>>         worker.worker1.port=8009
>>>>>>> 
>>>>>>> 6. Configure TomEE and create test app
>>>>>>>      1. Edit conf/server.xml:
>>>>>>>            1. Add jvmRoute="worker1" to engine configuration
>>>>>>>            2. Change Engine "defaultHost" and Host "name" values
to
>>>>>>>               external host name
>>>>>>>      2. Create test application
>>>>>>>            1. Create webapps/rs-test/WEB-INF/**classes/test
>>>>> directory.
>>>>>>>            2. Create
>>>>> webapps/rs-test/WEB-INF/**classes/test/TestRS.java
>>>>>>> with
>>>>>>>               the following content:
>>>>>>> 
>>>>>>>         package test;
>>>>>>>         import java.net.URI;
>>>>>>>         import javax.servlet.http.**HttpServletRequest;
>>>>>>>         import javax.ws.rs.*;
>>>>>>>         import javax.ws.rs.core.*;
>>>>>>>         @Path("")
>>>>>>>         public class TestRS {
>>>>>>> 
>>>>>>>             @GET
>>>>>>>             @Produces({MediaType.TEXT_**PLAIN})
>>>>>>>             public String defaultPage(@Context UriInfo uriInfo,
>>>>>>>                   @Context HttpHeaders hh, @Context
>>>>>>>         HttpServletRequest httpServletRequest) {
>>>>>>>                String response =
>>>>>>>                   "uriInfo.getAbsolutePath(): "
>>>>>>>                      + uriInfo.getAbsolutePath() + "\n"
>>>>>>>                   + "uriInfo.getBaseUri(): "
>>>>>>>                      + uriInfo.getBaseUri() + "\n"
>>>>>>>                   + "uriInfo.getRequestUri(): "
>>>>>>>                      + uriInfo.getRequestUri() + "\n"
>>>>>>>                   + "httpServletRequest.**getLocalAddr(): "
>>>>>>>                      + httpServletRequest.**getLocalAddr() +
"\n"
>>>>>>>                   + "httpServletRequest.**getLocalName(): "
>>>>>>>                      + httpServletRequest.**getLocalName() +
"\n"
>>>>>>>                   + "httpServletRequest.**getLocalPort(): "
>>>>>>>                      + httpServletRequest.**getLocalPort() +
"\n"
>>>>>>>                   + "httpServletRequest.**getServerName(): "
>>>>>>>                      + httpServletRequest.**getServerName() +
"\n"
>>>>>>>                   + "httpServletRequest.**getServerPort(): "
>>>>>>>                      + httpServletRequest.**getServerPort() +
>> "\n\n";
>>>>>>>                for (String header :
>>>>> hh.getRequestHeaders().keySet(**))
>>>>>>> {
>>>>>>>                   response += header + ":\n";
>>>>>>>                   for (String value :
>>>>>>>         hh.getRequestHeaders().get(**header)) {
>>>>>>>                      response += "\t" + value + "\n";
>>>>>>>                   }
>>>>>>>                }
>>>>>>>                return response;
>>>>>>>             }
>>>>>>>         }
>>>>>>> 
>>>>>>>        3. Compile test class with javac -classpath
>>>>>>>           lib/javaee-api-6.0-4-tomcat.**jar:lib/servlet-api.jar
>>>>>>>           webapps/rs-test/WEB-INF/**classes/test/TestRS.java
>>>>>>> 
>>>>>>> 7. Start services
>>>>>>>      1. Run apache-tomee-jaxrs-1.5.1/bin/**startup.sh to start
TomEE
>>>>>>>      2. Run httpd/bin/apachectl start to start httpd.
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> On Wed, Feb 6, 2013 at 1:17 AM, Romain Manni-Bucau <
>>>>> rmannibucau@gmail.com<mailto:
>>>>>>> rmannibucau@gmail.com>**> wrote:
>>>>>>> 
>>>>>>> UriInfo matches the http request info...
>>>>>>> Le 6 févr. 2013 07:16, "Chet Hosey" <ChetHosey@gmail.com
>>>>>>> <mailto:ChetHosey@gmail.com>> a écrit :
>>>>>>> 
>>>>>>> 
>>>>>>>> After building httpd 2.2.23 and mod_jk 1.2.37, I configured
an
>>>>>>> AJP proxy
>>>>>>>> for the TomEE test instance and set the jvmRoute in server.xml
to
>>>>>>> match the
>>>>>>>> worker name from workers.properties.
>>>>>>>> 
>>>>>>>> A request through httpd shows httpd's port number for the
>>>>>>>> httpServletRequest methods, but still shows the TomEE HTTP
>>>>>>> connector port
>>>>>>>> in the URIs returned by the uriInfo methods.
>>>>>>>> 
>>>>>>>> Doing string replacements seems fairly inelegant but I suppose
>>>>>>> it's an
>>>>>>>> option for custom apps. It would be surprising to learn that
the
>>>>>>> only other
>>>>>>>> option is to configure the TomEE instances' HTTP connectors
on
>>>>>>> the same
>>>>>>>> port as the httpd server, since each TomEE instance would
then need
>> a
>>>>>>>> dedicated IP.
>>>>>>>> 
>>>>>>>> I've filed TOMEE-757 in JIRA, as it's hard to imagine that
this
>>>>>>> behavior is
>>>>>>>> intended.
>>>>>>>> 
>>>>>>>> 
>>>>>>>> On Tue, Feb 5, 2013 at 9:17 AM, Chet Hosey <ChetHosey@gmail.com
>>>>>>> <mailto:ChetHosey@gmail.com>> wrote:
>>>>>>>> 
>>>>>>>>> Ahh, that's a good thought. It was the default value
of
>>>>>>> "localhost".
>>>>>>>> After
>>>>>>>>> changing the "name" attribute on the Host entry and updating
the
>>>>>>>>> defaultHost on the Engine, I'm getting the expected host
name
>>>>>>> in the
>>>>>>>>> response.
>>>>>>>>> 
>>>>>>>>> This leads me to wonder what happens when using AJP.
I'm
>>>>>>> picturing a
>>>>>>>> setup
>>>>>>>>> where httpd runs on port 80 and proxies to multiple TomEE
>>>>>>> instances via
>>>>>>>>> AJP. If the HTTP connector port is still used by the
UriInfo
>>>>>>> methods,
>>>>>>>> then
>>>>>>>>> TomEE would require special access (root or authbind)
to bind
>>>>>>> to port 80
>>>>>>>> to
>>>>>>>>> work around this behavior. And it wouldn't be possible
to run
>>>>>>> multiple
>>>>>>>>> TomEE instances on the same IP, since they'd all have
to bind
>>>>>>> to port 80
>>>>>>>> to
>>>>>>>>> ensure URI correctness.
>>>>>>>>> 
>>>>>>>>> I'll have to experiment to find out. If I get the chance
to do
>>>>>>> so, I'll
>>>>>>>>> report results back.
>>>>>>>>> 
>>>>>>>>> Thanks!
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> On Tue, Feb 5, 2013 at 1:16 AM, Romain Manni-Bucau <
>>>>>>>> rmannibucau@gmail.com <mailto:rmannibucau@gmail.com>**>wrote:
>>>>>>> 
>>>>>>>>> 
>>>>>>>>>> Hi,
>>>>>>>>>> 
>>>>>>>>>> What's your host in the server.xml?
>>>>>>>>>> Le 5 févr. 2013 06:30, "Chet Hosey" <ChetHosey@gmail.com
>>>>>>> <mailto:ChetHosey@gmail.com>> a écrit :
>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>>> I've been using apache-tomee-1.5.1-jaxrs as a
platform for
>>>>>>> learning
>>>>>>>>>> JAX-RS
>>>>>>>>>>> and have run into some confusion about UriInfo
determines
>>>>>>> the base
>>>>>>>> URI.
>>>>>>>>>> In
>>>>>>>>>>> my testing the URIs returned by UriInfo include
the correct port
>>>>>>>> number.
>>>>>>>>>>> But the host name is always "localhost", even
when I'm
>>>>>>> accessing TomEE
>>>>>>>>>> from
>>>>>>>>>>> a remote machine.
>>>>>>>>>>> 
>>>>>>>>>>> It's possible that UriInfo is meant to build
identifiers,
>>>>>>> and not
>>>>>>>>>> locators.
>>>>>>>>>>> This would explain why it's not called UrlInfo.
But the
>>>>>>> design of
>>>>>>>>>>> UriBuilder suggests that one should be able to
call
>>>>>>>>>>> 
>>>>>>>>>>> uriInfo.getBaseUriBuilder()
>>>>>>>>>>>       .path(User.class, "getUserInfo")
>>>>>>>>>>>       .path(userId).build();
>>>>>>>>>>> 
>>>>>>>>>>> and use the result as a hyperlink in a JAX-RS
response.
>>>>>>>>>>> 
>>>>>>>>>>> Having used mod_jk with JBoss, I know that it
can override
>>>>>>> the values
>>>>>>>>>>> returned by HttpServletRequest methods with parameters
like
>>>>>>>>>> JK_LOCAL_NAME.
>>>>>>>>>>> But since this is just a sandbox I'm accessing
Tomcat directly,
>>>>>>>> without
>>>>>>>>>> an
>>>>>>>>>>> Apache httpd proxy. But this led me to wonder
what
>>>>>>>>>>> httpServletRequest.**getlocalName() would return.
So I created
>>>>>>> a test
>>>>>>>>>> method
>>>>>>>>>>> to find out, using the following signature:
>>>>>>>>>>> 
>>>>>>>>>>> @GET
>>>>>>>>>>> @Produces({MediaType.TEXT_**PLAIN})
>>>>>>>>>>> public String defaultPage(@Context UriInfo uriInfo,
>>>>>>>>>>>       @Context HttpHeaders hh,
>>>>>>>>>>>       @Context HttpServletRequest httpServletRequest)
{
>>>>>>>>>>> 
>>>>>>>>>>> The output surprised me. The HttpServletRequest
methods use the
>>>>>>>> correct
>>>>>>>>>>> host name and IP address, and the "Host" header
uses the public
>>>>>>>> address.
>>>>>>>>>>> The UriInfo methods get the port correct, but
they still use
>>>>>>>>>> "localhost" as
>>>>>>>>>>> the host name.
>>>>>>>>>>> 
>>>>>>>>>>> uriInfo.getAbsolutePath():
>>>>>>>>>>> http://localhost:8081/sample-**app-1.0-SNAPSHOT/<
>>>>> http://localhost:8081/sample-app-1.0-SNAPSHOT/>
>>>>>>>>>>> uriInfo.getBaseUri():
>>>>>>>> http://localhost:8081/sample-**app-1.0-SNAPSHOT<
>>>>> http://localhost:8081/sample-app-1.0-SNAPSHOT>
>>>>>>>>>>> uriInfo.getRequestUri():
>>>>>>>>>> http://localhost:8081/sample-**app-1.0-SNAPSHOT/<
>>>>> http://localhost:8081/sample-app-1.0-SNAPSHOT/>
>>>>>>>>>>> httpServletRequest.**getLocalAddr(): 1.2.3.4
>>>>>>>>>>> httpServletRequest.**getLocalName(): www.example.com
>>>>>>> <http://www.example.com>
>>>>>>>>>>> httpServletRequest.**getLocalPort(): 8081
>>>>>>>>>>> httpServletRequest.**getServerName(): www.example.com
>>>>>>> <http://www.example.com>
>>>>>>>>>>> httpServletRequest.**getServerPort(): 8081
>>>>>>>>>>> 
>>>>>>>>>>> host:
>>>>>>>>>>> www.example.com:8081 <http://www.example.com:8081>
>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> Is there a way to use TomEE's embedded CXF REST
>>>>>>> implementation to
>>>>>>>>>> generate
>>>>>>>>>>> URIs that can be used by external clients to
locate other
>>>>>>> resources
>>>>>>>>>> within
>>>>>>>>>>> the same application? Or am I making bad assumptions
about
>>>>>>> the purpose
>>>>>>>>>> of
>>>>>>>>>>> the UriInfo methods that return UriBuilders?
>>>>>>>>>>> 
>>>>>>>>>>> -- Chet
>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>> 
>>>>> 
>> 
>> 


Mime
View raw message