users@jersey.java.net

[Jersey] Re: UriInfo oddness on Jetty vs Grizzly

From: Robert DiFalco <robert.difalco_at_gmail.com>
Date: Tue, 25 Mar 2014 12:33:29 -0700

I agree with you Alexy, I think not setting the port relies on side effects
of a particular implementation. However, I do stand by the idea that JAX-RS
should really have a forwarded URI in its UriInfo class. It would be very
rare that someone would want to give Links or a redirect URI that didn't
defer to that instead of the base or resource URI. But the filter works
fine for now.


On Tue, Mar 25, 2014 at 12:02 PM, Oleksiy Stashok <
oleksiy.stashok_at_oracle.com> wrote:

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