mirror of
https://github.com/openziti/zrok.git
synced 2025-03-14 23:48:22 +01:00
rough bubbletea tui (#56)
This commit is contained in:
parent
d984cbf832
commit
0119e54d43
@ -1,8 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/openziti-test-kitchen/zrok/endpoints"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -12,19 +14,12 @@ type shareModel struct {
|
||||
frontendEndpoints []string
|
||||
shareMode string
|
||||
backendMode string
|
||||
requests []*shareRequestModel
|
||||
requests []*endpoints.BackendRequest
|
||||
logMessages []string
|
||||
width int
|
||||
height int
|
||||
}
|
||||
|
||||
type shareRequestModel struct {
|
||||
stamp time.Time
|
||||
remoteAddr string
|
||||
verb string
|
||||
path string
|
||||
}
|
||||
|
||||
func newShareModel(shareToken string, frontendEndpoints []string, shareMode, backendMode string) *shareModel {
|
||||
return &shareModel{
|
||||
shareToken: shareToken,
|
||||
@ -38,6 +33,12 @@ func (m *shareModel) Init() tea.Cmd { return nil }
|
||||
|
||||
func (m *shareModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case *endpoints.BackendRequest:
|
||||
m.requests = append([]*endpoints.BackendRequest{msg}, m.requests...)
|
||||
if len(m.requests) > 2048 {
|
||||
m.requests = m.requests[:2048]
|
||||
}
|
||||
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = msg.Width
|
||||
shareHeaderStyle.Width(m.width - 30)
|
||||
@ -63,7 +64,7 @@ func (m *shareModel) View() string {
|
||||
shareHeaderStyle.Render(strings.Join(m.frontendEndpoints, "\n")),
|
||||
configHeaderStyle.Render(m.renderConfig()),
|
||||
)
|
||||
requests := requestsStyle.Render("hello")
|
||||
requests := requestsStyle.Render(m.renderBackendRequests())
|
||||
all := lipgloss.JoinVertical(lipgloss.Left, topRow, requests)
|
||||
return all
|
||||
}
|
||||
@ -85,6 +86,35 @@ func (m *shareModel) renderConfig() string {
|
||||
return out
|
||||
}
|
||||
|
||||
func (m *shareModel) renderBackendRequests() string {
|
||||
out := ""
|
||||
maxRows := requestsStyle.GetHeight()
|
||||
for i := 0; i < maxRows && i < len(m.requests); i++ {
|
||||
req := m.requests[i]
|
||||
out += fmt.Sprintf("%v %v -> %v %v",
|
||||
timeStyle.Render(req.Stamp.Format(time.RFC850)),
|
||||
addressStyle.Render(req.RemoteAddr),
|
||||
m.renderMethod(req.Method),
|
||||
req.Path,
|
||||
)
|
||||
if i != maxRows-1 {
|
||||
out += "\n"
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (m *shareModel) renderMethod(method string) string {
|
||||
switch strings.ToLower(method) {
|
||||
case "get":
|
||||
return getStyle.Render(method)
|
||||
case "post":
|
||||
return postStyle.Render(method)
|
||||
default:
|
||||
return otherMethodStyle.Render(method)
|
||||
}
|
||||
}
|
||||
|
||||
var shareHeaderStyle = lipgloss.NewStyle().
|
||||
Height(3).
|
||||
PaddingTop(1).PaddingLeft(2).PaddingBottom(1).PaddingRight(2).
|
||||
@ -101,7 +131,7 @@ var configHeaderStyle = lipgloss.NewStyle().
|
||||
|
||||
var requestsStyle = lipgloss.NewStyle().
|
||||
Height(3).
|
||||
PaddingTop(1).PaddingLeft(2).PaddingBottom(1).PaddingRight(2).
|
||||
PaddingLeft(2).PaddingRight(2).
|
||||
BorderStyle(lipgloss.RoundedBorder()).
|
||||
BorderForeground(lipgloss.Color("63"))
|
||||
|
||||
@ -109,3 +139,8 @@ var shareModePublicStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#0F0")
|
||||
var shareModePrivateStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#F00"))
|
||||
var backendModeProxyStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#FFA500"))
|
||||
var backendModeWebStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#0CC"))
|
||||
var timeStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#444"))
|
||||
var addressStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#FFA500"))
|
||||
var getStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("98"))
|
||||
var postStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("101"))
|
||||
var otherMethodStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("166"))
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti-test-kitchen/zrok/endpoints"
|
||||
"github.com/openziti-test-kitchen/zrok/endpoints/proxyBackend"
|
||||
"github.com/openziti-test-kitchen/zrok/endpoints/webBackend"
|
||||
"github.com/openziti-test-kitchen/zrok/model"
|
||||
@ -175,7 +176,7 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *sharePrivateCommand) proxyBackendMode(cfg *proxyBackend.Config) (backendHandler, error) {
|
||||
func (cmd *sharePrivateCommand) proxyBackendMode(cfg *proxyBackend.Config) (endpoints.BackendHandler, error) {
|
||||
be, err := proxyBackend.NewBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http proxy backend")
|
||||
@ -190,7 +191,7 @@ func (cmd *sharePrivateCommand) proxyBackendMode(cfg *proxyBackend.Config) (back
|
||||
return be, nil
|
||||
}
|
||||
|
||||
func (cmd *sharePrivateCommand) webBackendMode(cfg *webBackend.Config) (backendHandler, error) {
|
||||
func (cmd *sharePrivateCommand) webBackendMode(cfg *webBackend.Config) (endpoints.BackendHandler, error) {
|
||||
be, err := webBackend.NewBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http web backend")
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti-test-kitchen/zrok/endpoints"
|
||||
"github.com/openziti-test-kitchen/zrok/endpoints/proxyBackend"
|
||||
"github.com/openziti-test-kitchen/zrok/endpoints/webBackend"
|
||||
"github.com/openziti-test-kitchen/zrok/model"
|
||||
@ -137,13 +138,15 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
var bh backendHandler
|
||||
var bh endpoints.BackendHandler
|
||||
requestsChan := make(chan *endpoints.BackendRequest, 1024)
|
||||
switch cmd.backendMode {
|
||||
case "proxy":
|
||||
cfg := &proxyBackend.Config{
|
||||
IdentityPath: zif,
|
||||
EndpointAddress: target,
|
||||
ShrToken: resp.Payload.ShrToken,
|
||||
RequestsChan: requestsChan,
|
||||
}
|
||||
bh, err = cmd.proxyBackendMode(cfg)
|
||||
if err != nil {
|
||||
@ -158,6 +161,7 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
|
||||
IdentityPath: zif,
|
||||
WebRoot: target,
|
||||
ShrToken: resp.Payload.ShrToken,
|
||||
RequestsChan: requestsChan,
|
||||
}
|
||||
bh, err = cmd.webBackendMode(cfg)
|
||||
if err != nil {
|
||||
@ -171,25 +175,35 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
|
||||
tui.Error("invalid backend mode", nil)
|
||||
}
|
||||
|
||||
_ = bh.Requests()()
|
||||
|
||||
//logrus.Infof("access your zrok share: %v", resp.Payload.FrontendProxyEndpoints[0])
|
||||
//for {
|
||||
// time.Sleep(5 * time.Second)
|
||||
// logrus.Infof("requests: %d", bh.Requests()())
|
||||
//}
|
||||
|
||||
mdl := newShareModel(resp.Payload.ShrToken, resp.Payload.FrontendProxyEndpoints, "public", cmd.backendMode)
|
||||
prg := tea.NewProgram(mdl, tea.WithAltScreen())
|
||||
|
||||
go func() {
|
||||
bh.Requests()()
|
||||
for {
|
||||
select {
|
||||
case req := <-requestsChan:
|
||||
prg.Send(req)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
prg := tea.NewProgram(newShareModel(resp.Payload.ShrToken, resp.Payload.FrontendProxyEndpoints, "public", cmd.backendMode), tea.WithAltScreen())
|
||||
if _, err := prg.Run(); err != nil {
|
||||
tui.Error("An error occurred", err)
|
||||
}
|
||||
|
||||
close(requestsChan)
|
||||
cmd.destroy(zrd.Env.ZId, resp.Payload.ShrToken, zrok, auth)
|
||||
}
|
||||
|
||||
func (cmd *sharePublicCommand) proxyBackendMode(cfg *proxyBackend.Config) (backendHandler, error) {
|
||||
func (cmd *sharePublicCommand) proxyBackendMode(cfg *proxyBackend.Config) (endpoints.BackendHandler, error) {
|
||||
be, err := proxyBackend.NewBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http proxy backend")
|
||||
@ -204,7 +218,7 @@ func (cmd *sharePublicCommand) proxyBackendMode(cfg *proxyBackend.Config) (backe
|
||||
return be, nil
|
||||
}
|
||||
|
||||
func (cmd *sharePublicCommand) webBackendMode(cfg *webBackend.Config) (backendHandler, error) {
|
||||
func (cmd *sharePublicCommand) webBackendMode(cfg *webBackend.Config) (endpoints.BackendHandler, error) {
|
||||
be, err := webBackend.NewBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http web backend")
|
||||
|
@ -6,10 +6,6 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
type backendHandler interface {
|
||||
Requests() func() int32
|
||||
}
|
||||
|
||||
func mustGetAdminAuth() runtime.ClientAuthInfoWriter {
|
||||
adminToken := os.Getenv("ZROK_ADMIN_TOKEN")
|
||||
if adminToken == "" {
|
||||
|
@ -3,6 +3,7 @@ package proxyBackend
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openziti-test-kitchen/zrok/endpoints"
|
||||
"github.com/openziti-test-kitchen/zrok/util"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/config"
|
||||
@ -20,6 +21,7 @@ type Config struct {
|
||||
IdentityPath string
|
||||
EndpointAddress string
|
||||
ShrToken string
|
||||
RequestsChan chan *endpoints.BackendRequest
|
||||
}
|
||||
|
||||
type backend struct {
|
||||
@ -43,7 +45,7 @@ func NewBackend(cfg *Config) (*backend, error) {
|
||||
return nil, errors.Wrap(err, "error listening")
|
||||
}
|
||||
|
||||
proxy, err := newReverseProxy(cfg.EndpointAddress)
|
||||
proxy, err := newReverseProxy(cfg.EndpointAddress, cfg.RequestsChan)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -68,7 +70,7 @@ func (self *backend) Requests() func() int32 {
|
||||
return self.requests
|
||||
}
|
||||
|
||||
func newReverseProxy(target string) (*httputil.ReverseProxy, error) {
|
||||
func newReverseProxy(target string, requests chan *endpoints.BackendRequest) (*httputil.ReverseProxy, error) {
|
||||
targetURL, err := url.Parse(target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -81,9 +83,16 @@ func newReverseProxy(target string) (*httputil.ReverseProxy, error) {
|
||||
proxy.Transport = tpt
|
||||
director := proxy.Director
|
||||
proxy.Director = func(req *http.Request) {
|
||||
if requests != nil {
|
||||
requests <- &endpoints.BackendRequest{
|
||||
Stamp: time.Now(),
|
||||
RemoteAddr: fmt.Sprintf("%v", req.Header["X-Real-Ip"]),
|
||||
Method: req.Method,
|
||||
Path: req.URL.String(),
|
||||
}
|
||||
}
|
||||
fmt.Printf("proxy <= %v %v <= %v\n", req.Method, req.URL.String(), req.Header["X-Real-Ip"])
|
||||
director(req)
|
||||
logrus.Debugf("-> %v", req.URL.String())
|
||||
req.Header.Set("X-Proxy", "zrok")
|
||||
}
|
||||
proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
|
@ -6,8 +6,20 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BackendHandler interface {
|
||||
Requests() func() int32
|
||||
}
|
||||
|
||||
type BackendRequest struct {
|
||||
Stamp time.Time
|
||||
RemoteAddr string
|
||||
Method string
|
||||
Path string
|
||||
}
|
||||
|
||||
func GetRefreshedService(name string, ctx ziti.Context) (*edge.Service, bool) {
|
||||
svc, found := ctx.GetService(name)
|
||||
if !found {
|
||||
|
@ -2,6 +2,7 @@ package webBackend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti-test-kitchen/zrok/endpoints"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/config"
|
||||
"github.com/openziti/sdk-golang/ziti/edge"
|
||||
@ -14,6 +15,7 @@ type Config struct {
|
||||
IdentityPath string
|
||||
WebRoot string
|
||||
ShrToken string
|
||||
RequestsChan chan *endpoints.BackendRequest
|
||||
}
|
||||
|
||||
type backend struct {
|
||||
@ -36,11 +38,16 @@ func NewBackend(cfg *Config) (*backend, error) {
|
||||
return nil, errors.Wrap(err, "error listening")
|
||||
}
|
||||
|
||||
return &backend{
|
||||
be := &backend{
|
||||
cfg: cfg,
|
||||
listener: listener,
|
||||
handler: &requestLogger{handler: http.FileServer(http.Dir(cfg.WebRoot))},
|
||||
}, nil
|
||||
}
|
||||
if cfg.RequestsChan != nil {
|
||||
be.handler = &requestGrabber{requests: cfg.RequestsChan, handler: http.FileServer(http.Dir(cfg.WebRoot))}
|
||||
} else {
|
||||
be.handler = http.FileServer(http.Dir(cfg.WebRoot))
|
||||
}
|
||||
return be, nil
|
||||
}
|
||||
|
||||
func (self *backend) Run() error {
|
||||
@ -54,11 +61,19 @@ func (self *backend) Requests() func() int32 {
|
||||
return func() int32 { return 0 }
|
||||
}
|
||||
|
||||
type requestLogger struct {
|
||||
handler http.Handler
|
||||
type requestGrabber struct {
|
||||
requests chan *endpoints.BackendRequest
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
func (rl *requestLogger) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
||||
fmt.Printf("web <= %v %v <= %v\n", req.Method, req.URL.String(), req.Header["X-Real-Ip"])
|
||||
func (rl *requestGrabber) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
||||
if rl.requests != nil {
|
||||
rl.requests <- &endpoints.BackendRequest{
|
||||
Stamp: time.Now(),
|
||||
RemoteAddr: fmt.Sprintf("%v", req.Header["X-Real-Ip"]),
|
||||
Method: req.Method,
|
||||
Path: req.URL.String(),
|
||||
}
|
||||
}
|
||||
rl.handler.ServeHTTP(resp, req)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user