Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

treat registry.consul.kvpath as prefix #417

Merged
merged 3 commits into from
Feb 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions admin/api/manual.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
)

// ManualHandler provides a fetch and update handler for the manual overrides api.
type ManualHandler struct{}
type ManualHandler struct {
BasePath string
}

type manual struct {
Value string `json:"value"`
Expand All @@ -23,9 +25,11 @@ func (h *ManualHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}

path := r.RequestURI[len(h.BasePath):]

switch r.Method {
case "GET":
value, version, err := registry.Default.ReadManual()
value, version, err := registry.Default.ReadManual(path)
if err != nil {
log.Print("[ERROR] ", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand All @@ -43,7 +47,7 @@ func (h *ManualHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
defer r.Body.Close()

ok, err := registry.Default.WriteManual(m.Value, m.Version)
ok, err := registry.Default.WriteManual(path, m.Value, m.Version)
if err != nil {
log.Print("[ERROR] ", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand Down
39 changes: 39 additions & 0 deletions admin/api/paths.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package api

import (
"log"
"net/http"
"strings"

"github.com/fabiolb/fabio/registry"
)

type ManualPathsHandler struct {
Prefix string
}

func (h *ManualPathsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// we need this for testing.
// under normal circumstances this is never nil
if registry.Default == nil {
return
}

switch r.Method {
case "GET":
paths, err := registry.Default.ManualPaths()
if err != nil {
log.Print("[ERROR] ", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
for i, p := range paths {
paths[i] = strings.TrimPrefix(p, h.Prefix)
}
writeJSON(w, r, paths)
return

default:
http.Error(w, "not allowed", http.StatusMethodNotAllowed)
}
}
26 changes: 24 additions & 2 deletions admin/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/tls"
"fmt"
"net/http"
"strings"

"github.com/fabiolb/fabio/admin/api"
"github.com/fabiolb/fabio/admin/ui"
Expand Down Expand Up @@ -31,11 +32,32 @@ func (s *Server) handler() http.Handler {

switch s.Access {
case "ro":
mux.HandleFunc("/api/paths", forbidden)
mux.HandleFunc("/api/manual", forbidden)
mux.HandleFunc("/api/manual/", forbidden)
mux.HandleFunc("/manual", forbidden)
mux.HandleFunc("/manual/", forbidden)
case "rw":
mux.Handle("/api/manual", &api.ManualHandler{})
mux.Handle("/manual", &ui.ManualHandler{Color: s.Color, Title: s.Title, Version: s.Version, Commands: s.Commands})
// for historical reasons the configured config path starts with a '/'
// but Consul treats all KV paths without a leading slash.
pathsPrefix := strings.TrimPrefix(s.Cfg.Registry.Consul.KVPath, "/")
mux.Handle("/api/paths", &api.ManualPathsHandler{Prefix: pathsPrefix})
mux.Handle("/api/manual", &api.ManualHandler{BasePath: "/api/manual"})
mux.Handle("/api/manual/", &api.ManualHandler{BasePath: "/api/manual"})
mux.Handle("/manual", &ui.ManualHandler{
BasePath: "/manual",
Color: s.Color,
Title: s.Title,
Version: s.Version,
Commands: s.Commands,
})
mux.Handle("/manual/", &ui.ManualHandler{
BasePath: "/manual",
Color: s.Color,
Title: s.Title,
Version: s.Version,
Commands: s.Commands,
})
}

mux.Handle("/api/config", &api.ConfigHandler{Config: s.Cfg})
Expand Down
15 changes: 14 additions & 1 deletion admin/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"net/http"
"net/http/httptest"
"testing"

"github.com/fabiolb/fabio/config"
)

func TestAdminServerAccess(t *testing.T) {
Expand All @@ -13,7 +15,16 @@ func TestAdminServerAccess(t *testing.T) {
}

testAccess := func(access string, tests []test) {
srv := &Server{Access: access}
srv := &Server{
Access: access,
Cfg: &config.Config{
Registry: config.Registry{
Consul: config.Consul{
KVPath: "/fabio/config",
},
},
},
}
ts := httptest.NewServer(srv.handler())
defer ts.Close()

Expand All @@ -37,6 +48,7 @@ func TestAdminServerAccess(t *testing.T) {

roTests := []test{
{"/api/manual", 403},
{"/api/paths", 403},
{"/api/config", 200},
{"/api/routes", 200},
{"/api/version", 200},
Expand All @@ -49,6 +61,7 @@ func TestAdminServerAccess(t *testing.T) {

rwTests := []test{
{"/api/manual", 200},
{"/api/paths", 200},
{"/api/config", 200},
{"/api/routes", 200},
{"/api/version", 200},
Expand Down
60 changes: 59 additions & 1 deletion admin/ui/logo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import "net/http"

func HandleLogo(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
w.Write(logo)
if r.FormValue("format") == "bw" {
w.Write(logoBW)
} else {
w.Write(logo)
}
}

var logo = []byte(`<?xml version="1.0" encoding="UTF-8"?>
Expand All @@ -29,3 +33,57 @@ var logo = []byte(`<?xml version="1.0" encoding="UTF-8"?>
</g>
</g>
</svg>`)

var logoBW = []byte(`<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 724.7 143.1" style="enable-background:new 0 0 724.7 143.1;" xml:space="preserve">
<style type="text/css">
.st0{enable-background:new ;}
.st1{fill:#FFFFFF;}
.st2{fill:#FFFFFF;stroke:#FFFFFF;stroke-width:6;stroke-linecap:round;}
</style>
<title>Fabio</title>
<g class="st0">
<path class="st1" d="M304.4,140V38.6H401v11.2h-82.9v32.3h79.7v11.2h-79.7V140H304.4z"/>
<path class="st1" d="M482.4,140v-7.1h-0.3c-0.8,1.6-1.8,2.9-2.8,4c-1,1.1-2.5,1.9-4.3,2.6c-1.8,0.7-4.2,1.1-7.1,1.3
c-2.9,0.2-6.7,0.4-11.3,0.4h-28.8c-4.6,0-8.3-0.5-11.3-1.5c-2.9-1-5.3-2.4-7-4.2c-1.7-1.8-2.9-4.1-3.6-6.7c-0.7-2.7-1-5.7-1-9v-4.8
c0-4,0.7-7.2,2.1-9.7s3.5-4.3,6.2-5.5c2.8-1.3,6.2-2.1,10.2-2.5c4.1-0.4,8.7-0.6,13.9-0.6h19.3c3.9,0,7.3,0.1,10,0.3
s5.1,0.7,7.1,1.3c2,0.7,3.6,1.5,4.9,2.7s2.5,2.5,3.5,4.2h0.3V91.8c0-3.2-0.5-5.7-1.5-7.7c-1-2-2.6-3.4-4.8-4.4c-2.2-1-5-1.6-8.3-2
c-3.4-0.3-7.3-0.5-11.9-0.5h-17.6c-3.8,0-6.9,0.2-9.2,0.6c-2.3,0.4-4.2,1-5.5,1.9c-1.3,0.8-2.2,1.8-2.7,3c-0.5,1.2-0.7,2.5-0.7,4
v2.5h-12v-3.5c0-3.3,0.5-6.1,1.6-8.4c1.1-2.3,2.8-4.2,5.2-5.7c2.4-1.4,5.5-2.5,9.2-3.2c3.8-0.7,8.4-1,13.8-1h19
c5.6,0,10.7,0.3,15.3,0.8c4.6,0.6,8.6,1.7,11.8,3.5c3.3,1.8,5.8,4.3,7.6,7.5c1.8,3.2,2.7,7.5,2.7,12.8V140H482.4z M482.4,120.8
v-3.2c0-2.4-0.6-4.4-1.7-5.8c-1.1-1.4-2.8-2.6-5-3.4c-2.2-0.8-5.1-1.3-8.5-1.5c-3.4-0.2-7.4-0.4-12-0.4h-18.5
c-3.9,0-7.1,0.2-9.7,0.5c-2.5,0.3-4.5,0.9-6.1,1.8s-2.6,2-3.2,3.4c-0.6,1.4-0.9,3.3-0.9,5.5v2.2c0,2,0.2,3.7,0.7,5.1
c0.5,1.4,1.4,2.6,2.8,3.6c1.4,0.9,3.4,1.6,5.9,2s5.8,0.6,9.9,0.6h16c5.4,0,10.1-0.1,13.9-0.4s7-0.7,9.4-1.5
c2.4-0.8,4.1-1.9,5.2-3.2C481.8,124.9,482.4,123.1,482.4,120.8z"/>
<path class="st1" d="M504.5,140V38.6h12v39.5h0.3c1.3-3.7,3.7-6.4,7.2-8.1c3.5-1.7,8.7-2.5,15.6-2.5H558c7.3,0,13.3,0.5,18.1,1.6
c4.8,1.1,8.7,2.8,11.6,5.3c2.9,2.5,5,5.7,6.2,9.6c1.2,3.9,1.8,8.7,1.8,14.4V111c0,6.2-0.9,11.2-2.7,15.1c-1.8,3.9-4.4,7-7.6,9.2
c-3.3,2.2-7.2,3.7-11.8,4.6c-4.6,0.8-9.6,1.3-15,1.3h-16.8c-6.3,0-11.8-1-16.4-2.9s-7.7-5.1-9.5-9.5h-0.3V140H504.5z M583.7,110.9
v-14c0-4.1-0.5-7.4-1.5-10c-1-2.6-2.6-4.5-4.6-6c-2.1-1.4-4.6-2.4-7.8-2.9c-3.1-0.5-6.7-0.8-10.9-0.8h-16.2c-4.1,0-7.8,0.2-11,0.7
c-3.2,0.5-6,1.4-8.2,2.8c-2.2,1.4-4,3.4-5.2,6c-1.2,2.6-1.8,6.1-1.8,10.4v13.6c0,3.3,0.4,6.2,1.2,8.8c0.8,2.6,2.1,4.7,3.9,6.4
s4.2,3.1,7.3,4s6.8,1.4,11.3,1.4h19.6c4.9,0,8.8-0.4,12-1.3c3.1-0.8,5.6-2.1,7.3-3.8c1.8-1.7,3-3.8,3.6-6.4
S583.7,114.3,583.7,110.9z"/>
<path class="st1" d="M605.7,51.8V38.6h12v13.2H605.7z M605.7,140V68.6h12V140H605.7z"/>
<path class="st1" d="M628.5,112.1V96.5c0-5.9,1-10.7,2.9-14.4s4.7-6.7,8.2-8.9s7.7-3.7,12.5-4.5c4.9-0.8,10.1-1.2,15.8-1.2h17.2
c5.7,0,11,0.4,15.8,1.2c4.9,0.8,9,2.3,12.5,4.5s6.2,5.2,8.2,8.9s2.9,8.5,2.9,14.4v15.7c0,5.9-1,10.7-2.9,14.4
c-2,3.7-4.7,6.7-8.2,8.9s-7.7,3.7-12.5,4.5c-4.9,0.8-10.1,1.2-15.8,1.2H668c-5.7,0-11-0.4-15.8-1.2c-4.9-0.8-9-2.3-12.5-4.5
s-6.2-5.2-8.2-8.9C629.5,122.8,628.5,118,628.5,112.1z M712.7,111.4V97.2c0-4.2-0.6-7.6-1.8-10.2c-1.2-2.6-2.8-4.6-4.9-6
c-2.1-1.4-4.6-2.4-7.6-2.9c-2.9-0.5-6.1-0.8-9.6-0.8h-24.5c-3.5,0-6.8,0.3-9.7,0.8c-2.9,0.5-5.4,1.5-7.5,2.9
c-2.1,1.4-3.7,3.5-4.9,6c-1.2,2.6-1.8,6-1.8,10.2v14.3c0,4.2,0.6,7.6,1.8,10.1s2.8,4.6,4.9,6c2.1,1.4,4.6,2.4,7.5,2.9
c2.9,0.5,6.1,0.8,9.7,0.8h24.5c3.5,0,6.6-0.3,9.6-0.8c2.9-0.5,5.5-1.5,7.6-2.9c2.1-1.4,3.7-3.5,4.9-6S712.7,115.6,712.7,111.4z"/>
</g>
<path class="st1" d="M106,0h60c5.5,0,10,4.5,10,10v20c0,5.5-4.5,10-10,10h-60c-5.5,0-10-4.5-10-10V10C96,4.5,100.5,0,106,0z"/>
<path class="st1" d="M10,104h60c5.5,0,10,4.5,10,10v20c0,5.5-4.5,10-10,10H10c-5.5,0-10-4.5-10-10v-20C0,108.5,4.5,104,10,104z"/>
<path class="st1" d="M106,104h60c5.5,0,10,4.5,10,10v20c0,5.5-4.5,10-10,10h-60c-5.5,0-10-4.5-10-10v-20C96,108.5,100.5,104,106,104
z"/>
<path class="st1" d="M202,104h60c5.5,0,10,4.5,10,10v20c0,5.5-4.5,10-10,10h-60c-5.5,0-10-4.5-10-10v-20
C192,108.5,196.5,104,202,104z"/>
<line class="st2" x1="136" y1="48" x2="136" y2="96"/>
<line class="st2" x1="40" y1="80" x2="40" y2="96"/>
<line class="st2" x1="232" y1="80" x2="232" y2="96"/>
<line class="st2" x1="80" y1="64" x2="192" y2="64"/>
<line class="st2" x1="80" y1="64" x2="40" y2="80"/>
<line class="st2" x1="192" y1="64" x2="232" y2="80"/>
</svg>
`)
59 changes: 46 additions & 13 deletions admin/ui/manual.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,48 @@ import (
)

type ManualHandler struct {
BasePath string
Color string
Title string
Version string
Commands string
}

type paths struct {
Path string
Name string
}

func (h *ManualHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
tmplManual.ExecuteTemplate(w, "manual", h)
path := r.RequestURI[len(h.BasePath):]
data := struct {
*ManualHandler
Path string
APIPath string
}{
ManualHandler: h,
Path: path,
APIPath: "/api/manual" + path,
}
tmplManual.ExecuteTemplate(w, "manual", data)
}

var funcs = template.FuncMap{
"noescape": func(str string) template.HTML {
return template.HTML(str)
},
}

var tmplManual = template.Must(template.New("manual").Parse(`
var tmplManual = template.Must(template.New("manual").Funcs(funcs).Parse(`
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>fabio{{if .Title}} - {{.Title}}{{end}}</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.3/css/materialize.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.3/js/materialize.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>

<style type="text/css">
Expand All @@ -34,13 +57,16 @@ var tmplManual = template.Must(template.New("manual").Parse(`
</head>
<body>

<ul id="overrides" class="dropdown-content"></ul>

<nav class="top-nav {{.Color}}">

<div class="container">
<div class="nav-wrapper">
<a href="/" class="brand-logo">fabio{{if .Title}} - {{.Title}}{{end}}</a>
<a href="/" class="brand-logo"><img style="margin: 15px 0" class="logo" src="/logo.svg?format=bw"> {{if .Title}} - {{.Title}}{{end}}</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li><a href="/routes">Routes</a></li>
<li><a class="dropdown-button" href="#!" data-activates="overrides">Overrides<i class="material-icons right">arrow_drop_down</i></a></li>
<li><a href="https://github.com/fabiolb/fabio/blob/master/CHANGELOG.md">{{.Version}}</a></li>
<li><a href="https://github.com/fabiolb/fabio">Github</a></li>
</ul>
Expand All @@ -52,7 +78,7 @@ var tmplManual = template.Must(template.New("manual").Parse(`
<div class="container">

<div class="section">
<h5>Manual Overrides</h5>
<h5>Manual Routes{{if .Path}} for "{{.Path}}"{{end}}</h5>

<div class="row">
<form class="col s12">
Expand All @@ -73,23 +99,30 @@ var tmplManual = template.Must(template.New("manual").Parse(`
</div>
</div>

<div class="section footer">
<img class="logo" src="/logo.svg">
</div>

</div>

<script>
$(function(){
var params={};window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi,function(str,key,value){params[key] = value;});

$.get("/api/manual", function(data) {
$.get({{.APIPath}}, function(data) {
$("input[name=version]").val(data.version);
$("textarea>label").val("Version " + data.version);
$("#textarea1").val(data.value);
$("#textarea1").trigger('autoresize');
});

$.get('/api/paths', function(data) {
var d = $("#overrides");
$.each(data, function(idx, val) {
var path = val;
if (val == "") {
val = "default"
}
d.append('<li><a href="/manual'+path+'">'+val+'</a></li>');
});
});

$("button[name=help]").click(function() {
$("pre.help").toggleClass("hide");
});
Expand All @@ -99,7 +132,7 @@ $(function(){
value : $("#textarea1").val(),
version : $("input[name=version]").val()
}
$.ajax('/api/manual', {
$.ajax({{.APIPath}}, {
type: 'PUT',
data: JSON.stringify(data),
contentType: 'application/json',
Expand Down
Loading