users@jersey.java.net

[Jersey] Re: UriInfo oddness on Jetty vs Grizzly

From: Oleksiy Stashok <oleksiy.stashok_at_oracle.com>
Date: Mon, 24 Mar 2014 18:25:13 -0700

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?
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>