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.http.internal.services;
014
015import org.apache.tapestry5.http.TapestryHttpSymbolConstants;
016import org.apache.tapestry5.http.services.BaseURLSource;
017import org.apache.tapestry5.http.services.Request;
018import org.apache.tapestry5.ioc.annotations.Inject;
019import org.apache.tapestry5.ioc.annotations.Symbol;
020import org.apache.tapestry5.ioc.internal.util.InternalUtils;
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(TapestryHttpSymbolConstants.HOSTNAME) String hostname,
031                             @Symbol(TapestryHttpSymbolConstants.HOSTPORT) int hostPort, @Symbol(TapestryHttpSymbolConstants.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}