BIN
android-chrome-192x192.png
Normal file
BIN
android-chrome-192x192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
BIN
android-chrome-512x512.png
Normal file
BIN
android-chrome-512x512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 230 KiB |
BIN
apple-touch-icon.png
Normal file
BIN
apple-touch-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
BIN
favicon-16x16.png
Normal file
BIN
favicon-16x16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 838 B |
BIN
favicon-32x32.png
Normal file
BIN
favicon-32x32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -17,7 +17,7 @@
|
||||
packages = rec {
|
||||
slenpaste = pkgs.buildGoModule {
|
||||
pname = "slenpaste";
|
||||
version = "0.2.0";
|
||||
version = "0.2.1";
|
||||
src = ./.;
|
||||
goPackagePath = "github.com/slendidev/slenpaste";
|
||||
vendorHash = "sha256-MUvodL6K71SCfxu51T/Ka2/w32Kz+IXem1bYqXQLSaU=";
|
||||
|
||||
61
main.go
61
main.go
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
@@ -27,11 +28,19 @@ var (
|
||||
useHTTPS bool
|
||||
)
|
||||
|
||||
//go:embed android-chrome-192x192.png android-chrome-512x512.png apple-touch-icon.png favicon-16x16.png favicon-32x32.png favicon.ico site.webmanifest
|
||||
var assetsFS embed.FS
|
||||
|
||||
type meta struct {
|
||||
Expiry time.Time `json:"expiry"`
|
||||
ExpireOnView bool `json:"expire_on_view"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Ensure correct types for webmanifest on some systems
|
||||
_ = mime.AddExtensionType(".webmanifest", "application/manifest+json")
|
||||
}
|
||||
|
||||
func getLimiter(ip string) *rate.Limiter {
|
||||
limMu.Lock()
|
||||
defer limMu.Unlock()
|
||||
@@ -68,7 +77,7 @@ func randomID(n int) string {
|
||||
}
|
||||
|
||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", "text/html")
|
||||
w.Header().Add("Content-Type", "text/html; charset=utf-8")
|
||||
scheme := "http"
|
||||
if useHTTPS {
|
||||
scheme = "https"
|
||||
@@ -80,7 +89,17 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>slenpaste</title>
|
||||
|
||||
<!-- Icons / PWA -->
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<link rel="manifest" href="/site.webmanifest">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<style>
|
||||
body { font-family: system-ui, sans-serif; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
|
||||
pre { background: #f6f6f6; padding: .75rem 1rem; border-radius: .5rem; overflow: auto; }
|
||||
@@ -344,7 +363,7 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if n == 0 {
|
||||
os.Remove(path)
|
||||
_ = os.Remove(path)
|
||||
http.Error(w, "Empty upload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@@ -386,8 +405,8 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var m meta
|
||||
if err := json.Unmarshal(data, &m); err == nil {
|
||||
if !m.Expiry.IsZero() && time.Now().After(m.Expiry) {
|
||||
os.Remove(path)
|
||||
os.Remove(metaPath)
|
||||
_ = os.Remove(path)
|
||||
_ = os.Remove(metaPath)
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
@@ -405,7 +424,6 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// set correct content type based on extension
|
||||
ext := filepath.Ext(id)
|
||||
mimeType := mime.TypeByExtension(ext)
|
||||
if mimeType == "" {
|
||||
@@ -413,7 +431,26 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
w.Header().Set("Content-Type", mimeType)
|
||||
|
||||
io.Copy(w, f)
|
||||
_, _ = io.Copy(w, f)
|
||||
}
|
||||
|
||||
func serveEmbedded(embeddedName, contentType string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
b, err := assetsFS.ReadFile(embeddedName)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if contentType == "" {
|
||||
if ct := mime.TypeByExtension(filepath.Ext(embeddedName)); ct != "" {
|
||||
contentType = ct
|
||||
}
|
||||
}
|
||||
if contentType != "" {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
}
|
||||
http.ServeContent(w, r, embeddedName, time.Time{}, strings.NewReader(string(b)))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -425,6 +462,7 @@ func main() {
|
||||
flag.BoolVar(&useHTTPS, "https", false, "use https:// in generated URLs")
|
||||
flag.Parse()
|
||||
|
||||
// Uploads + index
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodPost {
|
||||
rateLimitMiddleware(uploadHandler)(w, r)
|
||||
@@ -433,6 +471,15 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
// Embedded favicon/PWA assets
|
||||
http.HandleFunc("/favicon.ico", serveEmbedded("favicon.ico", "image/x-icon"))
|
||||
http.HandleFunc("/apple-touch-icon.png", serveEmbedded("apple-touch-icon.png", "image/png"))
|
||||
http.HandleFunc("/favicon-16x16.png", serveEmbedded("favicon-16x16.png", "image/png"))
|
||||
http.HandleFunc("/favicon-32x32.png", serveEmbedded("favicon-32x32.png", "image/png"))
|
||||
http.HandleFunc("/android-chrome-192x192.png", serveEmbedded("android-chrome-192x192.png", "image/png"))
|
||||
http.HandleFunc("/android-chrome-512x512.png", serveEmbedded("android-chrome-512x512.png", "image/png"))
|
||||
http.HandleFunc("/site.webmanifest", serveEmbedded("site.webmanifest", "application/manifest+json"))
|
||||
|
||||
fmt.Printf("slenpaste running at http://%s, storing in %s\n", listenAddr, staticDir)
|
||||
http.ListenAndServe(listenAddr, nil)
|
||||
_ = http.ListenAndServe(listenAddr, nil)
|
||||
}
|
||||
|
||||
1
site.webmanifest
Normal file
1
site.webmanifest
Normal file
@@ -0,0 +1 @@
|
||||
{"name":"slenpaste","short_name":"slenpaste","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
||||
Reference in New Issue
Block a user