mirror of
https://github.com/prymitive/karma
synced 2026-05-05 03:16:51 +00:00
Add -web.prefix / WEB_PREFIX option
This allows people to use unsee with a sub uri setup, which is pretty common usa case, fixes #22
This commit is contained in:
committed by
Jeppe Toustrup
parent
039240bd73
commit
0d82cffd79
16
README.md
16
README.md
@@ -260,6 +260,22 @@ This option can also be set using `-strip.labels` flag. Example:
|
||||
|
||||
This variable is optional and default is not set (all labels will be shown).
|
||||
|
||||
#### WEB_PREFIX
|
||||
|
||||
URL root for unsee, you can use to if you wish to serve it from location other
|
||||
than /. Examples:
|
||||
|
||||
WEB_PREFIX=/unsee/
|
||||
|
||||
This will configure unsee to serve requests from http://localhost/unsee/
|
||||
instead http://localhost/.
|
||||
|
||||
This option can also be set using `-web.prefix` flag. Example:
|
||||
|
||||
$ unsee -web.prefix /unsee/
|
||||
|
||||
Default is `/`.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING](/CONTRIBUTING.md) for details.
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
<title>(◕︵◕)</title>
|
||||
|
||||
{{ range .CSSFiles }}
|
||||
<link rel="stylesheet" href="/static/managed/css/{{ . }}"> {{- end }}
|
||||
<link rel="stylesheet" href="{{ $.WebPrefix }}static/managed/css/{{ . }}"> {{- end }}
|
||||
|
||||
<link rel="stylesheet" href="/static/base.css">
|
||||
<link rel="stylesheet" href="{{ .WebPrefix }}static/base.css">
|
||||
|
||||
</head>
|
||||
|
||||
@@ -248,7 +248,7 @@
|
||||
<nav>
|
||||
<ul class="pager">
|
||||
<li>
|
||||
<a href="/">
|
||||
<a href="{{ .WebPrefix }}">
|
||||
<i class="fa fa-arrow-circle-left"></i> Back
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -8,15 +8,15 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="shortcut icon" id="favicon" href="/static/favicon.ico">
|
||||
<link rel="shortcut icon" id="favicon" href="{{ .WebPrefix }}static/favicon.ico">
|
||||
|
||||
<title>(◕︵◕)</title>
|
||||
|
||||
{{ range .CSSFiles }}
|
||||
<link rel="stylesheet" href="/static/managed/css/{{ . }}">
|
||||
<link rel="stylesheet" href="{{ $.WebPrefix }}static/managed/css/{{ . }}">
|
||||
{{- end }}
|
||||
|
||||
<link rel="stylesheet" href="/static/base.css?_={{ .NowQ }}">
|
||||
<link rel="stylesheet" href="{{ .WebPrefix }}static/base.css?_={{ .NowQ }}">
|
||||
|
||||
</head>
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
</div>
|
||||
|
||||
{{ range .JSFiles }}
|
||||
<script type="text/javascript" src="/static/managed/js/{{ . }}"></script>
|
||||
<script type="text/javascript" src="{{ $.WebPrefix }}static/managed/js/{{ . }}"></script>
|
||||
{{- end }}
|
||||
|
||||
{{ template "templates/js.html" .}}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<script type="text/javascript" src="/static/jquery.typing-0.2.0.js"></script>
|
||||
<script type="text/javascript" src="/static/lru.js"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/jquery.typing-0.2.0.js"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/lru.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/static/alerts.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/autocomplete.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/config.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/colors.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/counter.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/filters.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/grid.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/progress.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/summary.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/watchdog.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/querystring.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="/static/unsee.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/alerts.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/autocomplete.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/config.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/colors.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/counter.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/filters.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/grid.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/progress.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/summary.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/watchdog.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/querystring.js?_={{ .NowQ }}"></script>
|
||||
<script type="text/javascript" src="{{ .WebPrefix }}static/unsee.js?_={{ .NowQ }}"></script>
|
||||
|
||||
{{ if .SentryDSN }}
|
||||
<script type="application/javascript">
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -36,6 +36,7 @@ type configEnvs struct {
|
||||
SentryDSN string `envconfig:"SENTRY_DSN" help:"Sentry DSN for Go exceptions"`
|
||||
SentryPublicDSN string `envconfig:"SENTRY_PUBLIC_DSN" help:"Sentry DSN for javascript exceptions"`
|
||||
StripLabels spaceSeparatedList `envconfig:"STRIP_LABELS" help:"List of labels to ignore"`
|
||||
WebPrefix string `envconfig:"WEB_PREFIX" default:"/" help:"URL prefix"`
|
||||
}
|
||||
|
||||
// Config exposes all options required to run
|
||||
|
||||
26
main.go
26
main.go
@@ -1,6 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -69,14 +71,24 @@ func init() {
|
||||
metricAlertmanagerErrors.With(prometheus.Labels{"endpoint": "silences"}).Set(0)
|
||||
}
|
||||
|
||||
func setupRouter(router *gin.Engine) {
|
||||
router.Use(static.Serve("/static", newBinaryFileSystem("static")))
|
||||
func getViewURL(sub string) string {
|
||||
u := path.Join(config.Config.WebPrefix, sub)
|
||||
if strings.HasSuffix(sub, "/") {
|
||||
// if sub path had trailing slash then add it here, since path.Join will
|
||||
// skip it
|
||||
return u + "/"
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
router.GET("/favicon.ico", favicon)
|
||||
router.GET("/", index)
|
||||
router.GET("/help", help)
|
||||
router.GET("/alerts.json", alerts)
|
||||
router.GET("/autocomplete.json", autocomplete)
|
||||
func setupRouter(router *gin.Engine) {
|
||||
router.Use(static.Serve(getViewURL("/static"), newBinaryFileSystem("static")))
|
||||
|
||||
router.GET(getViewURL("/favicon.ico"), favicon)
|
||||
router.GET(getViewURL("/"), index)
|
||||
router.GET(getViewURL("/help"), help)
|
||||
router.GET(getViewURL("/alerts.json"), alerts)
|
||||
router.GET(getViewURL("/autocomplete.json"), autocomplete)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
5
views.go
5
views.go
@@ -61,6 +61,7 @@ func index(c *gin.Context) {
|
||||
"QFilter": q,
|
||||
"DefaultUsed": defaultUsed,
|
||||
"StaticColorLabels": strings.Join(config.Config.ColorLabelsStatic, " "),
|
||||
"WebPrefix": config.Config.WebPrefix,
|
||||
})
|
||||
|
||||
log.Infof("[%s] %s %s took %s", c.ClientIP(), c.Request.Method, c.Request.RequestURI, time.Since(start))
|
||||
@@ -74,6 +75,7 @@ func help(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "templates/help.html", gin.H{
|
||||
"CSSFiles": cssFiles,
|
||||
"SentryDSN": config.Config.SentryPublicDSN,
|
||||
"WebPrefix": config.Config.WebPrefix,
|
||||
})
|
||||
log.Infof("[%s] <%d> %s %s took %s", c.ClientIP(), http.StatusOK, c.Request.Method, c.Request.RequestURI, time.Since(start))
|
||||
}
|
||||
@@ -268,5 +270,8 @@ func autocomplete(c *gin.Context) {
|
||||
}
|
||||
|
||||
func favicon(c *gin.Context) {
|
||||
if config.Config.WebPrefix != "/" {
|
||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, config.Config.WebPrefix)
|
||||
}
|
||||
faviconFileServer.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
|
||||
@@ -45,6 +45,19 @@ func TestIndex(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexPrefix(t *testing.T) {
|
||||
os.Setenv("WEB_PREFIX", "/prefix")
|
||||
defer os.Unsetenv("WEB_PREFIX")
|
||||
mockConfig()
|
||||
r := ginTestEngine()
|
||||
req, _ := http.NewRequest("GET", "/prefix/", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
r.ServeHTTP(resp, req)
|
||||
if resp.Code != http.StatusOK {
|
||||
t.Errorf("GET /prefix/ returned status %d", resp.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHelp(t *testing.T) {
|
||||
mockConfig()
|
||||
r := ginTestEngine()
|
||||
@@ -56,6 +69,25 @@ func TestHelp(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHelpPrefix(t *testing.T) {
|
||||
os.Setenv("WEB_PREFIX", "/prefix")
|
||||
defer os.Unsetenv("WEB_PREFIX")
|
||||
mockConfig()
|
||||
r := ginTestEngine()
|
||||
req, _ := http.NewRequest("GET", "/prefix/help", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
r.ServeHTTP(resp, req)
|
||||
if resp.Code != http.StatusOK {
|
||||
t.Errorf("GET /prefix/help returned status %d", resp.Code)
|
||||
}
|
||||
req, _ = http.NewRequest("GET", "/help", nil)
|
||||
resp = httptest.NewRecorder()
|
||||
r.ServeHTTP(resp, req)
|
||||
if resp.Code != http.StatusNotFound {
|
||||
t.Errorf("GET /help returned status %d, expected 404", resp.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func mockAlerts() {
|
||||
httpmock.Activate()
|
||||
defer httpmock.DeactivateAndReset()
|
||||
@@ -345,3 +377,42 @@ func TestStaticFiles(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var staticFilePrefixTests = []staticFileTestCase{
|
||||
staticFileTestCase{
|
||||
path: "/sub/favicon.ico",
|
||||
code: 200,
|
||||
},
|
||||
staticFileTestCase{
|
||||
path: "/sub/static/unsee.js",
|
||||
code: 200,
|
||||
},
|
||||
staticFileTestCase{
|
||||
path: "/sub/static/managed/js/assets.txt",
|
||||
code: 200,
|
||||
},
|
||||
staticFileTestCase{
|
||||
path: "/sub/xxx",
|
||||
code: 404,
|
||||
},
|
||||
staticFileTestCase{
|
||||
path: "/sub/static/abcd",
|
||||
code: 404,
|
||||
},
|
||||
}
|
||||
|
||||
func TestStaticFilesPrefix(t *testing.T) {
|
||||
os.Setenv("WEB_PREFIX", "/sub")
|
||||
defer os.Unsetenv("WEB_PREFIX")
|
||||
mockConfig()
|
||||
mockAlerts()
|
||||
r := ginTestEngine()
|
||||
for _, staticFileTest := range staticFilePrefixTests {
|
||||
req, _ := http.NewRequest("GET", staticFileTest.path, nil)
|
||||
resp := httptest.NewRecorder()
|
||||
r.ServeHTTP(resp, req)
|
||||
if resp.Code != staticFileTest.code {
|
||||
t.Errorf("Invalid status code for GET %s: %d", staticFileTest.path, resp.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user