add base url support

This commit is contained in:
Prabhat Khera
2021-12-02 09:45:55 +13:00
parent d0f562a827
commit cdc9ea32fc
14 changed files with 49 additions and 8 deletions

View File

@@ -55,6 +55,7 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
Labels: pairs(kingpin.Flag("hide-label", "Hide containers with a specific label in the UI").Short('l')),
Logo: kingpin.Flag("logo", "URL for the logo displayed in the UI").String(),
Templates: kingpin.Flag("templates", "URL to the templates definitions.").Short('t').String(),
BaseURL: kingpin.Flag("base-url", "Base URL parameter such as portainer if running portainer as http://yourdomain.com/portainer/.").Short('b').Default(defaultBaseURL).String(),
}
kingpin.Parse()

View File

@@ -19,4 +19,5 @@ const (
defaultSSLCertPath = "/certs/portainer.crt"
defaultSSLKeyPath = "/certs/portainer.key"
defaultSnapshotInterval = "5m"
defaultBaseURL = "/"
)

View File

@@ -17,4 +17,5 @@ const (
defaultSSLCertPath = "C:\\certs\\portainer.crt"
defaultSSLKeyPath = "C:\\certs\\portainer.key"
defaultSnapshotInterval = "5m"
defaultBaseURL = "/"
)

View File

@@ -650,6 +650,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
ShutdownCtx: shutdownCtx,
ShutdownTrigger: shutdownTrigger,
StackDeployer: stackDeployer,
BaseURL: *flags.BaseURL,
}
}

View File

@@ -21,15 +21,17 @@ type Handler struct {
kubernetesClientFactory *cli.ClientFactory
authorizationService *authorization.Service
JwtService portainer.JWTService
BaseURL string
}
// NewHandler creates a handler to process pre-proxied requests to external APIs.
func NewHandler(bouncer *security.RequestBouncer, authorizationService *authorization.Service, dataStore portainer.DataStore, kubernetesClientFactory *cli.ClientFactory) *Handler {
func NewHandler(bouncer *security.RequestBouncer, authorizationService *authorization.Service, dataStore portainer.DataStore, kubernetesClientFactory *cli.ClientFactory, baseURL string) *Handler {
h := &Handler{
Router: mux.NewRouter(),
dataStore: dataStore,
kubernetesClientFactory: kubernetesClientFactory,
authorizationService: authorizationService,
BaseURL: baseURL,
}
kubeRouter := h.PathPrefix("/kubernetes").Subrouter()

View File

@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"net/http"
"strings"
clientV1 "k8s.io/client-go/tools/clientcmd/api/v1"
@@ -162,6 +163,14 @@ func buildCluster(r *http.Request, endpoint portainer.Endpoint) clientV1.NamedCl
}
}
// getProxyUrl generates portainer proxy url which acts as proxy to k8s api server
func getProxyUrl(r *http.Request, baseURL string, endpointID int) string {
if baseURL != "/" {
baseURL = fmt.Sprintf("/%s/", strings.Trim(baseURL, "/"))
}
return fmt.Sprintf("https://%s%sapi/endpoints/%d/kubernetes", r.Host, baseURL, endpointID)
}
func buildClusterName(endpointName string) string {
return fmt.Sprintf("portainer-cluster-%s", endpointName)
}

View File

@@ -94,6 +94,7 @@ type Server struct {
ShutdownCtx context.Context
ShutdownTrigger context.CancelFunc
StackDeployer stackdeployer.StackDeployer
BaseURL string
}
// Start starts the HTTP server
@@ -170,7 +171,7 @@ func (server *Server) Start() error {
endpointProxyHandler.ProxyManager = server.ProxyManager
endpointProxyHandler.ReverseTunnelService = server.ReverseTunnelService
var kubernetesHandler = kubehandler.NewHandler(requestBouncer, server.AuthorizationService, server.DataStore, server.KubernetesClientFactory)
var kubernetesHandler = kubehandler.NewHandler(requestBouncer, server.AuthorizationService, server.DataStore, server.KubernetesClientFactory, server.BaseURL)
kubernetesHandler.JwtService = server.JWTService
var fileHandler = file.NewHandler(filepath.Join(server.AssetsPath, "public"))

View File

@@ -67,6 +67,7 @@ type (
SSLKey *string
Rollback *bool
SnapshotInterval *string
BaseURL *string
}
// CustomTemplate represents a custom template

View File

@@ -1,4 +1,5 @@
import { Terminal } from 'xterm';
import { baseHref } from '@/portainer/helpers/pathHelper';
angular.module('portainer.docker').controller('ContainerConsoleController', [
'$scope',
@@ -69,7 +70,8 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
};
var url =
window.location.href.split('#')[0] +
window.location.origin +
baseHref() +
'api/websocket/attach?' +
Object.keys(params)
.map((k) => k + '=' + params[k])
@@ -109,7 +111,8 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
};
var url =
window.location.href.split('#')[0] +
window.location.origin +
baseHref() +
'api/websocket/exec?' +
Object.keys(params)
.map((k) => k + '=' + params[k])

View File

@@ -5,6 +5,12 @@
<title>Portainer</title>
<meta name="description" content="" />
<meta name="author" content="<%= author %>" />
<base id="base" />
<script>
var path = window.location.pathname.replace(/^\/+|\/+$/g, '');
var basePath = path ? '/' + path + '/' : '/';
document.getElementById('base').href = basePath;
</script>
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>

View File

@@ -1,5 +1,6 @@
import { Terminal } from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit';
import { baseHref } from '@/portainer/helpers/pathHelper';
export default class KubectlShellController {
/* @ngInject */
@@ -91,7 +92,7 @@ export default class KubectlShellController {
};
const wsProtocol = this.$window.location.protocol === 'https:' ? 'wss://' : 'ws://';
const path = '/api/websocket/kubernetes-shell';
const path = baseHref() + 'api/websocket/kubernetes-shell';
const queryParams = Object.entries(params)
.map(([k, v]) => `${k}=${v}`)
.join('&');

View File

@@ -1,5 +1,6 @@
import angular from 'angular';
import { Terminal } from 'xterm';
import { baseHref } from '@/portainer/helpers/pathHelper';
class KubernetesApplicationConsoleController {
/* @ngInject */
@@ -59,7 +60,8 @@ class KubernetesApplicationConsoleController {
};
let url =
window.location.href.split('#')[0] +
window.location.origin +
baseHref() +
'api/websocket/pod?' +
Object.keys(params)
.map((k) => k + '=' + params[k])

View File

@@ -0,0 +1,10 @@
/**
* calculates baseHref
*
* return [string]
*
*/
export function baseHref() {
const base = document.getElementById('base');
return base ? base.getAttribute('href') : '/';
}

View File

@@ -1,3 +1,5 @@
import { baseHref } from '@/portainer/helpers/pathHelper';
angular.module('portainer.app').factory('WebhookHelper', [
'$location',
'API_ENDPOINT_WEBHOOKS',
@@ -11,11 +13,11 @@ angular.module('portainer.app').factory('WebhookHelper', [
const displayPort = (protocol === 'http' && port === 80) || (protocol === 'https' && port === 443) ? '' : ':' + port;
helper.returnWebhookUrl = function (token) {
return `${protocol}://${$location.host()}${displayPort}/${API_ENDPOINT_WEBHOOKS}/${token}`;
return `${protocol}://${$location.host()}${displayPort}${baseHref()}${API_ENDPOINT_WEBHOOKS}/${token}`;
};
helper.returnStackWebhookUrl = function (token) {
return `${protocol}://${$location.host()}${displayPort}/${API_ENDPOINT_STACKS}/webhooks/${token}`;
return `${protocol}://${$location.host()}${displayPort}${baseHref()}${API_ENDPOINT_STACKS}/webhooks/${token}`;
};
return helper;