mirror of
https://github.com/openziti/ziti.git
synced 2026-10-08 22:01:15 +00:00
Merge pull request #1542 from openziti/prototype-zac-xweb-handler
Prototype zac xweb handler
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright NetFoundry Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package spa_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SinglePageAppHandler struct {
|
||||
HttpHandler http.Handler
|
||||
BindingKey string
|
||||
}
|
||||
|
||||
func (spa *SinglePageAppHandler) Binding() string {
|
||||
return spa.BindingKey
|
||||
}
|
||||
|
||||
func (spa *SinglePageAppHandler) Options() map[interface{}]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (spa *SinglePageAppHandler) RootPath() string {
|
||||
return "/" + spa.BindingKey
|
||||
}
|
||||
|
||||
func (spa *SinglePageAppHandler) IsHandler(r *http.Request) bool {
|
||||
return strings.HasPrefix(r.URL.Path, spa.RootPath()) || strings.HasPrefix(r.URL.Path, "/assets")
|
||||
}
|
||||
|
||||
func (spa *SinglePageAppHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
spa.HttpHandler.ServeHTTP(writer, request)
|
||||
}
|
||||
|
||||
// Thanks to https://github.com/roberthodgen/spa-server
|
||||
// Serve from a public directory with specific index
|
||||
type spaHandler struct {
|
||||
content string // The directory from which to serve
|
||||
contextRoot string // The context root to remove
|
||||
indexFile string // The fallback/default file to serve
|
||||
}
|
||||
|
||||
// Falls back to a supplied index (indexFile) when either condition is true:
|
||||
// (1) Request (file) path is not found
|
||||
// (2) Request path is a directory
|
||||
// Otherwise serves the requested file.
|
||||
func (h *spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, h.contextRoot)
|
||||
p := filepath.Join(h.content, filepath.Clean(r.URL.Path))
|
||||
|
||||
if info, err := os.Stat(p); err != nil {
|
||||
http.ServeFile(w, r, filepath.Join(h.content, h.indexFile))
|
||||
return
|
||||
} else if info.IsDir() {
|
||||
http.ServeFile(w, r, filepath.Join(h.content, h.indexFile))
|
||||
return
|
||||
}
|
||||
|
||||
http.ServeFile(w, r, p)
|
||||
}
|
||||
|
||||
// SpaHandler returns a request handler (http.Handler) that serves a single
|
||||
// page application from a given public directory (location).
|
||||
func SpaHandler(location string, contextRoot string, indexFile string) http.Handler {
|
||||
return &spaHandler{location, contextRoot, indexFile}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/openziti/ziti/controller/event"
|
||||
"github.com/openziti/ziti/controller/events"
|
||||
"github.com/openziti/ziti/controller/handler_peer_ctrl"
|
||||
"github.com/openziti/ziti/controller/zac"
|
||||
"math/big"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
@@ -247,6 +248,10 @@ func (c *Controller) initWeb() {
|
||||
logrus.WithError(err).Fatalf("failed to create metrics api factory")
|
||||
}
|
||||
|
||||
if err := c.xweb.GetRegistry().Add(zac.NewZitiAdminConsoleFactory()); err != nil {
|
||||
logrus.WithError(err).Fatalf("failed to create single page application factory")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *Controller) Run() error {
|
||||
|
||||
@@ -22,12 +22,12 @@ import (
|
||||
clientInformational "github.com/openziti/edge-api/rest_client_api_server/operations/informational"
|
||||
managementInformational "github.com/openziti/edge-api/rest_management_api_server/operations/informational"
|
||||
"github.com/openziti/edge-api/rest_model"
|
||||
"github.com/openziti/xweb/v2"
|
||||
"github.com/openziti/ziti/common/build"
|
||||
"github.com/openziti/ziti/controller"
|
||||
"github.com/openziti/ziti/controller/env"
|
||||
"github.com/openziti/ziti/controller/internal/permissions"
|
||||
"github.com/openziti/ziti/controller/response"
|
||||
"github.com/openziti/ziti/common/build"
|
||||
"github.com/openziti/xweb/v2"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package zac
|
||||
|
||||
import (
|
||||
"github.com/openziti/xweb/v2"
|
||||
"github.com/openziti/ziti/common/spa_handler"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
Binding = "zac"
|
||||
)
|
||||
|
||||
type ZitiAdminConsoleFactory struct {
|
||||
}
|
||||
|
||||
var _ xweb.ApiHandlerFactory = &ZitiAdminConsoleFactory{}
|
||||
|
||||
func NewZitiAdminConsoleFactory() *ZitiAdminConsoleFactory {
|
||||
return &ZitiAdminConsoleFactory{}
|
||||
}
|
||||
|
||||
func (factory ZitiAdminConsoleFactory) Validate(*xweb.InstanceConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (factory ZitiAdminConsoleFactory) Binding() string {
|
||||
return Binding
|
||||
}
|
||||
|
||||
func (factory ZitiAdminConsoleFactory) New(_ *xweb.ServerConfig, options map[interface{}]interface{}) (xweb.ApiHandler, error) {
|
||||
loc := options["location"]
|
||||
if loc == nil || loc == "" {
|
||||
log.Fatal("location must be supplied in " + Binding + " options")
|
||||
}
|
||||
indexFile := options["indexFile"]
|
||||
if indexFile == nil || indexFile == "" {
|
||||
indexFile = "index.html"
|
||||
}
|
||||
spa := &spa_handler.SinglePageAppHandler{
|
||||
HttpHandler: spa_handler.SpaHandler(loc.(string), "/"+Binding, indexFile.(string)),
|
||||
BindingKey: Binding,
|
||||
}
|
||||
|
||||
log.Infof("initializing ZAC SPA Handler from %s", loc)
|
||||
return spa, nil
|
||||
}
|
||||
@@ -215,3 +215,5 @@ web:
|
||||
options: { }
|
||||
- binding: fabric
|
||||
options: { }
|
||||
# - binding: zac
|
||||
# options: { "location": "./zac", "indexFile":"index.html" }
|
||||
|
||||
Reference in New Issue
Block a user