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