    001// Licensed under the Apache License, Version 2.0 (the "License");
    002// you may not use this file except in compliance with the License.
    003// You may obtain a copy of the License at
    004//
    005// http://www.apache.org/licenses/LICENSE-2.0
    006//
    007// Unless required by applicable law or agreed to in writing, software
    008// distributed under the License is distributed on an "AS IS" BASIS,
    009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    010// See the License for the specific language governing permissions and
    011// limitations under the License.
    012
    013package org.apache.tapestry5.internal.services;
    014
    015import org.apache.tapestry5.SymbolConstants;
    016import org.apache.tapestry5.ioc.annotations.Inject;
    017import org.apache.tapestry5.ioc.annotations.Symbol;
    018import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    019import org.apache.tapestry5.services.BaseURLSource;
    020import org.apache.tapestry5.services.Request;
    021
    022public class BaseURLSourceImpl implements BaseURLSource
    023{
    024    private final Request request;
    025
    026    private String hostname;
    027    private int hostPort;
    028    private int secureHostPort;
    029
    030    public BaseURLSourceImpl(Request request, @Inject @Symbol(SymbolConstants.HOSTNAME) String hostname,
    031                             @Symbol(SymbolConstants.HOSTPORT) int hostPort, @Symbol(SymbolConstants.HOSTPORT_SECURE) int secureHostPort)
    032    {
    033        this.request = request;
    034        this.hostname = hostname;
    035        this.hostPort = hostPort;
    036        this.secureHostPort = secureHostPort;
    037    }
    038
    039    public String getBaseURL(boolean secure)
    040    {
    041        return String.format("%s://%s%s",
    042                secure ? "https" : "http",
    043                hostname(),
    044                portExtension(secure));
    045    }
    046
    047    private String portExtension(boolean secure)
    048    {
    049        int configuredPort = secure ? secureHostPort : hostPort;
    050
    051        // The default for the ports is 0, which means to use Request.serverPort. That's mostly
    052        // for development.
    053        if (configuredPort <= 0 && secure == request.isSecure())
    054        {
    055            configuredPort = request.getServerPort();
    056        }
    057
    058        int expectedPort = secure ? 443 : 80;
    059
    060        if (configuredPort == expectedPort || configuredPort <= 0)
    061        {
    062            return "";
    063        }
    064
    065        return ":" + configuredPort;
    066    }
    067
    068    private String hostname()
    069    {
    070
    071        if (InternalUtils.isBlank(hostname))
    072        {
    073            return request.getServerName();
    074        }
    075
    076        // This is common in some PaaS deployments, such as Heroku, where the port is passed in as
    077        // and environment variable.
    078
    079        if (this.hostname.startsWith("$"))
    080        {
    081            return System.getenv(hostname.substring(1));
    082        }
    083
    084        return hostname;
    085    }
    086}