Fix frontend routing

This commit is contained in:
Lukas SP 2020-08-23 14:13:17 +02:00
parent 0f90b267c7
commit 13b0e961ae
7 changed files with 180 additions and 4 deletions

4
.gitignore vendored
View File

@ -112,4 +112,6 @@ modules.xml
# Sonarlint plugin
.idea/sonarlint
# End of https://www.toptal.com/developers/gitignore/api/jetbrains+all,go
# End of https://www.toptal.com/developers/gitignore/api/jetbrains+all,go
web/*.gz

1
go.mod
View File

@ -9,4 +9,5 @@ require (
github.com/joho/godotenv v1.3.0
github.com/klauspost/compress v1.10.11 // indirect
github.com/valyala/fasthttp v1.16.0
github.com/zekroTJA/seiteki v0.0.0-20200704144115-4da98a9f806b
)

8
go.sum
View File

@ -8,22 +8,30 @@ github.com/fasthttp/router v1.2.4 h1:RBWbCv4vVf+boczSZh/rX9PDSdR9F8I9zSnVJx5YJfU
github.com/fasthttp/router v1.2.4/go.mod h1:Au2V1CaqqAdzQQcPKrbkFAsImd1aHpadrce21AIPnvE=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.7 h1:7rix8v8GpI3ZBb0nSozFRgbtXKv+hOe+qfEpZqybrAg=
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.11 h1:K9z59aO18Aywg2b/WSgBaUX99mHy2BES18Cr5lBKZHk=
github.com/klauspost/compress v1.10.11/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/savsgio/gotils v0.0.0-20200616100644-13ff1fd2c28c h1:KKqhycXW1WVNkX7r4ekTV2gFkbhdyihlWD8c0/FiWmk=
github.com/savsgio/gotils v0.0.0-20200616100644-13ff1fd2c28c/go.mod h1:TWNAOTaVzGOXq8RbEvHnhzA/A2sLZzgn0m6URjnukY8=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.9.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
github.com/valyala/fasthttp v1.15.1/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
github.com/valyala/fasthttp v1.16.0 h1:9zAqOYLl8Tuy3E5R6ckzGDJ1g8+pw15oQp2iL9Jl6gQ=
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/zekroTJA/seiteki v0.0.0-20200704144115-4da98a9f806b h1:91TpJPV0um3tRyn04crvki4pmvqBOaRqmI3dF6Iy73s=
github.com/zekroTJA/seiteki v0.0.0-20200704144115-4da98a9f806b/go.mod h1:tnwJnVgsX5mc6GJA02qx0vSOP1j6jkM5TKo5bOxscrw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

10
internal/web/logger.go Normal file
View File

@ -0,0 +1,10 @@
package web
// nilLogger represents a logger that does not print anything
type nilLogger struct {
}
// Printf prints nothing
func (logger *nilLogger) Printf(string, ...interface{}) {
return
}

View File

@ -5,6 +5,8 @@ import (
v1 "github.com/Lukaesebrot/pasty/internal/web/controllers/v1"
routing "github.com/fasthttp/router"
"github.com/valyala/fasthttp"
"path/filepath"
"strings"
)
// Serve serves the web server
@ -12,6 +14,23 @@ func Serve() error {
// Create the router
router := routing.New()
// Define the 404 handler
router.NotFound = func(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusNotFound)
ctx.SetBodyString("not found")
}
// Route the frontend requests
frontend := frontendHandler()
router.GET("/{path:*}", func(ctx *fasthttp.RequestCtx) {
path := string(ctx.Path())
if !strings.HasPrefix(path, "/api") {
frontend(ctx)
return
}
router.NotFound(ctx)
})
// Route the API endpoints
apiRoute := router.Group("/api")
{
@ -21,9 +40,24 @@ func Serve() error {
}
}
// TODO: Route the paste endpoints
// Serve the web server
address := env.Get("WEB_ADDRESS", ":8080")
return fasthttp.ListenAndServe(address, router.Handler)
return (&fasthttp.Server{
Handler: router.Handler,
Logger: new(nilLogger),
}).ListenAndServe(address)
}
// frontendHandler handles the frontend routing
func frontendHandler() fasthttp.RequestHandler {
// Create the file server
fs := &fasthttp.FS{
Root: "./web",
IndexNames: []string{"index.html"},
CacheDuration: 0,
}
fs.PathNotFound = func(ctx *fasthttp.RequestCtx) {
ctx.SendFile(filepath.Join(fs.Root, "index.html"))
}
return fs.NewRequestHandler()
}

49
web/index.html Normal file
View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>pasty</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="spinner hidden"></div>
<div class="navigation">
<button class="item" id="btn_new" title="Create a new paste (Ctrl + N)">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-circle-plus" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<circle cx="12" cy="12" r="9" />
<line x1="9" y1="12" x2="15" y2="12" />
<line x1="12" y1="9" x2="12" y2="15" />
</svg>
</button>
<button class="item" id="btn_save" title="Save the content to a new paste (Ctrl + S)">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-device-floppy" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<path d="M6 4h10l4 4v10a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2" />
<circle cx="12" cy="14" r="2" />
<polyline points="14 4 14 8 8 8 8 4" />
</svg>
</button>
<button class="item" id="btn_delete" title="Delete the current paste (Ctrl + X)">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-trash" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<line x1="4" y1="7" x2="20" y2="7" />
<line x1="10" y1="11" x2="10" y2="17" />
<line x1="14" y1="11" x2="14" y2="17" />
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
</svg>
</button>
<button class="item" id="btn_copy" title="Copy the paste content to your clipboard (Ctrl + C)">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-clipboard" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<path d="M9 5H7a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2V7a2 2 0 0 0 -2 -2h-2" />
<rect x="9" y="3" width="6" height="4" rx="2" />
</svg>
</button>
</div>
<div class="linenos"></div>
<div class="content"></div>
</body>
</html>

72
web/style.css Normal file
View File

@ -0,0 +1,72 @@
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: #222222;
}
@-webkit-keyframes spinner {
0% {
-webkit-transform: translate3d(-50%, -50%, 0) rotate(0deg);
transform: translate3d(-50%, -50%, 0) rotate(0deg);
}
100% {
-webkit-transform: translate3d(-50%, -50%, 0) rotate(360deg);
transform: translate3d(-50%, -50%, 0) rotate(360deg);
}
}
@keyframes spinner {
0% {
-webkit-transform: translate3d(-50%, -50%, 0) rotate(0deg);
transform: translate3d(-50%, -50%, 0) rotate(0deg);
}
100% {
-webkit-transform: translate3d(-50%, -50%, 0) rotate(360deg);
transform: translate3d(-50%, -50%, 0) rotate(360deg);
}
}
.spinner {
content: "";
-webkit-animation: .75s linear infinite spinner;
animation: .75s linear infinite spinner;
-webkit-animation-play-state: inherit;
animation-play-state: inherit;
border: solid 5px #000000;
border-bottom-color: transparent;
border-radius: 50%;
height: 50px;
width: 50px;
position: absolute;
top: 100px;
right: 100px;
-webkit-transform: translate3d(-50%, -50%, 0);
transform: translate3d(-50%, -50%, 0);
will-change: transform;
}
.spinner.hidden {
display: none;
}
.navigation {
width: 100vw;
height: 60px;
background-color: #111111;
display: flex;
align-items: center;
}
.navigation .item {
margin-left: 20px;
background-color: transparent;
border: none;
outline: none;
}
.navigation .item svg {
transition: all 250ms;
}
.navigation .item:hover {
cursor: pointer;
}
.navigation .item:hover svg {
stroke: #c0c0c0;
}