I have a secured application, meaning it insists on HTTPS, so it should return HTTPS URLs for everything, but it doesn't. When an event handler returns a page class or an injected page, Tapestry returns an HTTP URL.
The problem started when I switched handling of HTTPS to a load balancer (AWS Application Load Balancer). It forwards the request as HTTP, along with the HTTPS headers intact. Normally Tapestry recognises the request is secure and returns a secure URL, but not in the 2 cases above.
I've narrowed the problem down to a method in RequestSecurityManagerImpl:
It assumes that a secure page is HTTPS and therefore it returns LinkSecurity.SECURE instead of LinkSecurity.FORCE_SECURE . Consequently, Tapestry returns a relative URL instead of an absolute URL specifying "https://".
I see 3 possible solutions:
(1) Always return absolute URLs.
(2) Instead of relative URLs, return a protocol-relative URL (i.e. "//" instead of "https://" or "http://").
(3) Modify the code to handle the possibility that protocol and isSecure() disagree. For example (this code snippet has been tested and is running live):
Is possibility 1 a bad idea? Are longer URLs really a big deal?
Some people suggest possibility 2 has downsides such as page URLs not standing on their own if copied and pasted. Maybe that's an issue.
I used possibility 3 to solved my problem. It works.