users@jersey.java.net

[Jersey] Re: UriInfo oddness on Jetty vs Grizzly

From: Oleksiy Stashok <oleksiy.stashok_at_oracle.com>
Date: Tue, 25 Mar 2014 12:02:48 -0700

Hi Robert,

On 25.03.14 07:43, Robert DiFalco wrote:
> I don't have the startup for Jetty anymore but it was using the Jersey
> Servlet 3.0 capability. The Grizzly setup is much more lightweight, it
> doesn't use servlets at all.
>
> GrizzlyHttpServerFactory.createHttpServer(
> getBaseRestURI(),
> new JerseyResourceConfiguration());
>
> Nothing special about the ResourceConfig. Just that filter down
> further in the thread, Jackson, and exception mappers. Maybe the
> difference is between servlet and non-servlet Jersey?
I think that's the reason, it should be something in configuration.
BTW setting the port is needed anyway (IMO), because if the port wasn't
443 (the default HTTPS port) - Jetty-based Filter implementation
wouldn't work, I don't think Jetty automatically picks up the port from
"x-forwarded-port" header, but I could be wrong.

Thanks.

WBR,
Alexey.

>
>
>
>
> On Mon, Mar 24, 2014 at 6:25 PM, Oleksiy Stashok
> <oleksiy.stashok_at_oracle.com <mailto:oleksiy.stashok_at_oracle.com>> wrote:
>
> Hi Robert,
>
> can you pls. share the code how you initialize Grizzly and Jetty?
>
> Thanks.
>
> WBR,
> Alexey.
>
>
> On 20.03.14 07:47, Robert DiFalco wrote:
>> Sure, the only change is that Grizzly requires the forwarded port
>> to also be changed. Note, I would probably prefer to have a
>> #getForwardedUri in UriInfo and use that for redirects. That way
>> I have all the original information as well as the forwarded
>> information. But this definitely works for both HTTPS and HTTP.
>>
>>
>>
>> /**
>> * When using Heroku and an SSL Endpoint, the heroku
>> load-balancer will handle SSL and forward on
>> * requests to the container using HTTP. However, the HTTPS
>> scheme will be in the x-forwarded-proto
>> * header. This makes sure that in those cases the scheme
>> will remain HTTPS so that we can generate
>> * 303 locations (and such) that are appropriately HTTPS.
>> Jetty will keep the port empty (if it
>> * was not specified by the client) whereas Grizzly will
>> specify 80. Grizzly's behavior will break
>> * redirects for HTTPS since that uses a port other than 80.
>> So to cover both cases this filter will
>> * also grab the forwarded port.
>> */
>> @PreMatching
>> public class HerokuContainerRequestFilter implements
>> ContainerRequestFilter {
>>
>> @Override
>> public void filter( ContainerRequestContext ctx ) throws
>> IOException {
>>
>> String scheme = getValue( ctx.getHeaders(),
>> "x-forwarded-proto" );
>> String port = getValue( ctx.getHeaders(),
>> "x-forwarded-port" ); // For Grizzly
>> if ( scheme == null && port == null )
>> return;
>>
>> UriBuilder baseBuilder = ctx.getUriInfo().getBaseUriBuilder();
>> UriBuilder requestBuilder =
>> ctx.getUriInfo().getRequestUriBuilder();
>> if ( scheme != null ) {
>> baseBuilder.scheme( scheme );
>> requestBuilder.scheme( scheme );
>> }
>>
>> if ( port != null ) {
>> int nPort = Integer.parseInt( port );
>> baseBuilder.port( nPort );
>> requestBuilder.port( nPort );
>> }
>>
>> // maake sure to set both base and request URIs
>> ctx.setRequestUri( baseBuilder.build(),
>> requestBuilder.build() );
>> }
>>
>> private String getValue( MultivaluedMap<String,String>
>> headers, String header ) {
>> List<String> values = headers.get( header );
>> if ( values == null || values.isEmpty() )
>> return null;
>>
>> return values.get( 0 );
>> }
>> }
>>
>>
>>
>>
>> On Wed, Mar 19, 2014 at 11:38 PM, Oleksiy Stashok
>> <oleksiy.stashok_at_oracle.com <mailto:oleksiy.stashok_at_oracle.com>>
>> wrote:
>>
>> Hi Robert,
>>
>> can you pls. share the Filter/Resource code, which works on
>> Jetty, but doesn't work on Grizzly and the change you do to
>> make it work on Grizzly.
>> Can you pls. also share the HTTP request headers coming to
>> Jersey from Heroku?
>>
>> Thank you.
>>
>> WBR,
>> Alexey.
>>
>> On 12.03.14 19:32, Robert DiFalco wrote:
>>> I can't because I can't really replicate being run on a
>>> heroku dyno. However, any rest method that you can set on a
>>> heroku dyno and then access the URL using HTTPS will
>>> recreate the issue. Just use an @Context UriInfo info in any
>>> GET method and inspect the info.getBaseUri(). If you
>>> accessed the end-point via heroku and using the HTTPS scheme
>>> you should see port 80 there. If you switch to Jetty you
>>> will see no port specified.
>>>
>>>
>>>
>>>
>>> On Wed, Mar 12, 2014 at 7:04 PM, Oleksiy Stashok
>>> <oleksiy.stashok_at_oracle.com
>>> <mailto:oleksiy.stashok_at_oracle.com>> wrote:
>>>
>>>
>>> On 12.03.14 15:55, Robert DiFalco wrote:
>>>> Ah yes, then I can't say for sure if it is a bug or
>>>> not. But heroku is forwarding https without a port to
>>>> 443. So if the BaseURI/Request does not specify a port
>>>> and it is used for a redirect then there is no problem.
>>>> But if it has an 80 shoved in there then the redirect
>>>> URI will be broken because https cannot go through 80
>>>> from the client. Make sense?
>>> Do you have a testcase to reproduce the problem?
>>>
>>> Thanks.
>>>
>>> WBR,
>>> Alexey.
>>>
>>>>
>>>> I can see the rational for both approaches. It's just
>>>> weird that Jetty and Grizzly work differently and I
>>>> have to code accordingly.
>>>>
>>>>
>>>> On Wed, Mar 12, 2014 at 3:48 PM, Oleksiy Stashok
>>>> <oleksiy.stashok_at_oracle.com
>>>> <mailto:oleksiy.stashok_at_oracle.com>> wrote:
>>>>
>>>>
>>>> On 12.03.14 15:30, Robert DiFalco wrote:
>>>>> Well, before we go too fast. Why does Jetty not
>>>>> include the port while Grizzly does? Does it have
>>>>> to do with me not using a Servlet on Grizzly while
>>>>> I did on Jetty? I'm not even sure between the two
>>>>> which is the correct behavior (when running behind
>>>>> heroku).
>>>> AFAIR In HTTP URL if you don't specify the port -
>>>> port 80 is implied. So HTTP URL with and without
>>>> port 80 refer to the same resource.
>>>>
>>>> WBR,
>>>> Alexey.
>>>>
>>>>>
>>>>>
>>>>> On Wed, Mar 12, 2014 at 3:19 PM, Oleksiy Stashok
>>>>> <oleksiy.stashok_at_oracle.com
>>>>> <mailto:oleksiy.stashok_at_oracle.com>> wrote:
>>>>>
>>>>> Hi Robert,
>>>>>
>>>>> it doesn't sound like a bug, but for sure we
>>>>> can change that behavior.
>>>>> Please file an issue @ [1]
>>>>>
>>>>> Thanks.
>>>>>
>>>>> WBR,
>>>>> Alexey.
>>>>>
>>>>> [1] https://java.net/jira/browse/GRIZZLY
>>>>>
>>>>> On 12.03.14 12:04, Robert DiFalco wrote:
>>>>>
>>>>> I recently changed my heroku deployed app
>>>>> from Jetty to Grizzly. I am now getting
>>>>> some weird behavior.
>>>>>
>>>>> When I create my redirect URIs I now get a
>>>>> port 80 in the URI whereas under Jetty I
>>>>> get one with no port specified. I do NOT
>>>>> want the port specified.
>>>>>
>>>>> Any ideas what can be going on here?
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>