diff --git a/internal/server/assets/HelveticaNeue-Light.woff2 b/internal/server/assets/HelveticaNeue-Light.woff2 new file mode 100644 index 0000000..91b9d69 Binary files /dev/null and b/internal/server/assets/HelveticaNeue-Light.woff2 differ diff --git a/internal/server/assets/logo.png b/internal/server/assets/logo.png new file mode 100644 index 0000000..8240f73 Binary files /dev/null and b/internal/server/assets/logo.png differ diff --git a/internal/server/assets/logo.svg b/internal/server/assets/logo.svg new file mode 100644 index 0000000..e96f9c0 --- /dev/null +++ b/internal/server/assets/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/internal/server/assets/style.css b/internal/server/assets/style.css new file mode 100644 index 0000000..53f96b5 --- /dev/null +++ b/internal/server/assets/style.css @@ -0,0 +1,174 @@ +.clearfix:before, +.clearfix:after { + content: ""; + display: table; +} + +.clearfix:after { + clear: both; +} + +@font-face { + font-family: "HelveticaNeue-Light"; + src: url("/assets/HelveticaNeue-Light.woff2") format("woff2"); +} + +body { + background: #343434; + background-size: cover; + color: #4c4c4c; + font: 300 1.1em/1.7em "HelveticaNeue-Light", Helvetica, Arial, sans-serif; +} + +body > p { + bottom: 10px; + color: #fff; + font-size: 12px; + left: 10px; + position: absolute; +} + +body > p a { + color: #fff; +} + +.container { + color: #4c4c4c; + height: 249px; + left: 50%; + margin: -125px 0 0 -223px; + position: absolute; + top: 50%; + width: 446px; + box-shadow: 1px 1px 16px rgba(0, 0, 0, 0.58); + border-radius: 12px; +} + +.header { + color: #fdfdfd; + font: 12px/17px "HelveticaNeue-UltraLight", Helvetica, Arial, sans-serif; + padding: 18px 20px 20px; + border-radius: 2px 2px 0 0; +} + +.logo { + border: 4px solid #c9c9c9; + border-top-width: 3px; + float: left; + margin-right: 16px; + position: relative; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.6), 0 -1px 0 #9ce5fa; + border-radius: 2px; +} + +.logo::before { + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset; +} + +.logo img { + display: block; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.5) inset; +} + +.header h2, +.header p { + float: left; + margin-top: 30px; +} + +.header h2 { + font-size: 26px; + line-height: 32px; + margin: 10px 0 8px; +} + +.header h2 a { + color: #fdfdfd; + text-decoration: none; +} + +.header h2 a:hover, +.logo:hover { + opacity: 0.6; +} + +.stats { + background: rgb(243, 243, 243); + background: -moz-linear-gradient( + top, + rgba(243, 243, 243, 1) 0%, + rgba(236, 236, 237, 1) 100% + ); + background: -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0%, rgba(243, 243, 243, 1)), + color-stop(100%, rgba(236, 236, 237, 1)) + ); + background: -webkit-linear-gradient( + top, + rgba(243, 243, 243, 1) 0%, + rgba(236, 236, 237, 1) 100% + ); + background: -o-linear-gradient( + top, + rgba(243, 243, 243, 1) 0%, + rgba(236, 236, 237, 1) 100% + ); + background: -ms-linear-gradient( + top, + rgba(243, 243, 243, 1) 0%, + rgba(236, 236, 237, 1) 100% + ); + background: linear-gradient( + to bottom, + rgba(243, 243, 243, 1) 0%, + rgba(236, 236, 237, 1) 100% + ); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3f3f3', endColorstr='#ececed', GradientType=0); + border-top: 1px solid #fff; + border-bottom: 1px solid #d4d4d4; +} + +.stat { + color: #4c4c4c; + float: left; + font-size: 14px; + line-height: 17px; + padding: 15px 0 14px; + text-align: center; + text-decoration: none; + text-shadow: 0 1px 0 #fff; + width: 148px; + cursor: default; +} + +.stat:first-child { + margin-left: 1px; +} + +.stat.enable:hover { + color: #747474; + cursor: pointer; +} + +.stat strong { + display: block; + font-size: 25px; + line-height: 25px; +} + +.stats-bottom { + border-radius: 10px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} diff --git a/internal/server/internal.go b/internal/server/internal.go index bcc641c..647db50 100644 --- a/internal/server/internal.go +++ b/internal/server/internal.go @@ -1,7 +1,10 @@ package server import ( + "embed" + "fmt" "net/http" + _url "net/url" "os" "strconv" "strings" @@ -10,16 +13,21 @@ import ( ) const ( - INTERNAL_PAGE_HOME string = "/" - INTERNAL_PAGE_PING string = "/_/ping/" + INTERNAL_PAGE_HOME string = "/" + INTERNAL_PAGE_PING string = "/_/ping/" + INTERNAL_PAGE_ASSETS string = "/assets" ) const ( - TYPE_NOT_FOUND int = 0 - TYPE_HOME int = 1 - TYPE_PING int = 2 + TYPE_NOT_FOUND int = iota + TYPE_HOME + TYPE_PING + TYPE_ASSETS ) +//go:embed assets/* +var f embed.FS + func IsInternalUrls(url string) bool { u := strings.ToLower(url) return !(strings.Contains(u, "/ubuntu") || strings.Contains(u, "/debian") || strings.Contains(u, "/centos") || strings.Contains(u, "/alpine")) @@ -34,6 +42,10 @@ func GetInternalResType(url string) int { return TYPE_PING } + if strings.HasPrefix(url, INTERNAL_PAGE_ASSETS) { + return TYPE_ASSETS + } + return TYPE_NOT_FOUND } @@ -41,7 +53,7 @@ func GetInternalResType(url string) int { const CACHE_META_DIR = "./.aptcache/header/v1" const LABEL_NO_VALID_VALUE = "N/A" -func RenderInternalUrls(url string) (string, int) { +func RenderInternalUrls(url string) ([]byte, int) { switch GetInternalResType(url) { case TYPE_HOME: cacheSizeLabel := LABEL_NO_VALID_VALUE @@ -77,9 +89,22 @@ func RenderInternalUrls(url string) (string, int) { memoryUsage, goroutine := system.GetMemoryUsageAndGoroutine() memoryUsageLabel = system.ByteCountDecimal(memoryUsage) - return GetBaseTemplate(cacheSizeLabel, filesNumberLabel, diskAvailableLabel, memoryUsageLabel, goroutine), 200 + return []byte(GetBaseTemplate(cacheSizeLabel, filesNumberLabel, diskAvailableLabel, memoryUsageLabel, goroutine)), http.StatusOK case TYPE_PING: - return "pong", http.StatusOK + return []byte("pong"), http.StatusOK + case TYPE_ASSETS: + // [FIXME] logging with fmt.Println is ugly + u, err := _url.Parse(url) + if err != nil { + fmt.Printf("error parsing url %s : %s", url, err.Error()) + return nil, http.StatusInternalServerError + } + f, err := f.ReadFile(u.Path[1:]) + if err != nil { + fmt.Printf("error reading url %s : %s", url, err.Error()) + return nil, http.StatusNotFound + } + return f, http.StatusOK } - return "Not Found", http.StatusNotFound + return []byte("Not Found"), http.StatusNotFound } diff --git a/internal/server/internal_test.go b/internal/server/internal_test.go index ec943e4..54e9512 100644 --- a/internal/server/internal_test.go +++ b/internal/server/internal_test.go @@ -39,7 +39,7 @@ func TestRenderInternalUrls(t *testing.T) { if code != http.StatusOK { t.Fatal("test render internal urls failed") } - if res != "pong" { + if string(res) != "pong" { t.Fatal("test render internal urls failed") } @@ -53,7 +53,7 @@ func TestRenderInternalUrls(t *testing.T) { if !(code == http.StatusOK || code == http.StatusBadGateway) { t.Fatal("test render internal urls failed") } - if res == "" { + if len(res) == 0 { t.Fatal("test render internal urls failed") } } diff --git a/internal/server/page.go b/internal/server/page.go index 2ac8545..b1aaf7a 100644 --- a/internal/server/page.go +++ b/internal/server/page.go @@ -1,217 +1,17 @@ package server import ( + _ "embed" "strings" ) -const SERVER_DEFAULT_TEMPLATE = ` - - -
- - - - -APT Proxy is a Lightweight and Reliable packages (Ubuntu / Debian / CentOS / Alpine) cache tool, supports a large - number of common system and Docker usage.
-+ APT Proxy is a Lightweight and Reliable packages (Ubuntu / Debian / + CentOS / Alpine) cache tool, supports a large number of common system + and Docker usage. +
+