Add log channel, add --exit-on-error option

This commit is contained in:
Seednode 2023-09-15 14:28:21 -05:00
parent f5eb1f56f4
commit 1ed9df3932
13 changed files with 139 additions and 90 deletions

View File

@ -112,33 +112,34 @@ Usage:
roulette <path> [path]... [flags] roulette <path> [path]... [flags]
Flags: Flags:
-a, --all enable all supported file types -a, --all enable all supported file types
--audio enable support for audio files --audio enable support for audio files
-b, --bind string address to bind to (default "0.0.0.0") -b, --bind string address to bind to (default "0.0.0.0")
-c, --cache generate directory cache at startup -c, --cache generate directory cache at startup
--cache-file string path to optional persistent cache file --cache-file string path to optional persistent cache file
--code enable support for source code files --code enable support for source code files
--code-theme string theme for source code syntax highlighting (default "solarized-dark256") --code-theme string theme for source code syntax highlighting (default "solarized-dark256")
-f, --filter enable filtering --exit-on-error shut down webserver on error, instead of just printing the error
--flash enable support for shockwave flash files (via ruffle.rs) -f, --filter enable filtering
--handlers display registered handlers (for debugging) --flash enable support for shockwave flash files (via ruffle.rs)
-h, --help help for roulette --handlers display registered handlers (for debugging)
--images enable support for image files -h, --help help for roulette
-i, --info expose informational endpoints --images enable support for image files
--maximum-files uint32 skip directories with file counts above this value (default 4294967295) -i, --info expose informational endpoints
--minimum-files uint32 skip directories with file counts below this value (default 1) --maximum-files uint skip directories with file counts above this value (default 4294967295)
--page-length uint32 pagination length for info pages --minimum-files uint skip directories with file counts below this value (default 1)
-p, --port uint16 port to listen on (default 8080) --page-length uint32 pagination length for info pages
--prefix string root path for http handlers (for reverse proxying) (default "/") -p, --port uint16 port to listen on (default 8080)
--profile register net/http/pprof handlers --prefix string root path for http handlers (for reverse proxying) (default "/")
-r, --recursive recurse into subdirectories --profile register net/http/pprof handlers
--refresh enable automatic page refresh via query parameter -r, --recursive recurse into subdirectories
--russian remove selected images after serving --refresh enable automatic page refresh via query parameter
-s, --sort enable sorting --russian remove selected images after serving
--text enable support for text files -s, --sort enable sorting
-v, --verbose log accessed files and other information to stdout --text enable support for text files
-V, --version display version and exit -v, --verbose log accessed files and other information to stdout
--video enable support for video files -V, --version display version and exit
--video enable support for video files
``` ```
## Building the Docker container ## Building the Docker container

View File

@ -6,7 +6,6 @@ package cmd
import ( import (
"encoding/gob" "encoding/gob"
"fmt"
"net/http" "net/http"
"os" "os"
"sync" "sync"
@ -129,11 +128,11 @@ func (cache *fileCache) Import(path string) error {
return nil return nil
} }
func serveCacheClear(args []string, cache *fileCache, formats *types.Types) httprouter.Handle { func serveCacheClear(args []string, cache *fileCache, formats *types.Types, errorChannel chan<- error) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
list, err := fileList(args, &filters{}, "", &fileCache{}, formats) list, err := fileList(args, &filters{}, "", &fileCache{}, formats)
if err != nil { if err != nil {
fmt.Println(err) errorChannel <- err
return return
} }
@ -146,7 +145,7 @@ func serveCacheClear(args []string, cache *fileCache, formats *types.Types) http
} }
} }
func registerCacheHandlers(mux *httprouter.Router, args []string, cache *fileCache, formats *types.Types) error { func registerCacheHandlers(mux *httprouter.Router, args []string, cache *fileCache, formats *types.Types, errorChannel chan<- error) error {
skipIndex := false skipIndex := false
if CacheFile != "" { if CacheFile != "" {
@ -165,7 +164,7 @@ func registerCacheHandlers(mux *httprouter.Router, args []string, cache *fileCac
cache.set(list) cache.set(list)
} }
register(mux, Prefix+"/clear_cache", serveCacheClear(args, cache, formats)) register(mux, Prefix+"/clear_cache", serveCacheClear(args, cache, formats, errorChannel))
return nil return nil
} }

View File

@ -7,6 +7,7 @@ package cmd
import ( import (
"bytes" "bytes"
"embed" "embed"
"errors"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
@ -27,12 +28,16 @@ const (
<meta name="theme-color" content="#ffffff">` <meta name="theme-color" content="#ffffff">`
) )
func serveFavicons() httprouter.Handle { func serveFavicons(errorChannel chan<- error) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
errorChannel <- errors.New("test")
fname := strings.TrimPrefix(r.URL.Path, "/") fname := strings.TrimPrefix(r.URL.Path, "/")
data, err := favicons.ReadFile(fname) data, err := favicons.ReadFile(fname)
if err != nil { if err != nil {
errorChannel <- err
return return
} }

View File

@ -133,7 +133,7 @@ func serveIndexHtml(args []string, cache *fileCache, paginate bool) httprouter.H
} }
} }
func serveIndexJson(args []string, index *fileCache) httprouter.Handle { func serveIndexJson(args []string, index *fileCache, errorChannel chan<- error) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
@ -168,7 +168,7 @@ func serveIndexJson(args []string, index *fileCache) httprouter.Handle {
response, err := json.MarshalIndent(cachedFiles[startIndex:stopIndex], "", " ") response, err := json.MarshalIndent(cachedFiles[startIndex:stopIndex], "", " ")
if err != nil { if err != nil {
fmt.Println(err) errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
@ -272,16 +272,16 @@ func serveEnabledMimeTypes(formats *types.Types) httprouter.Handle {
} }
} }
func registerInfoHandlers(mux *httprouter.Router, args []string, cache *fileCache, formats *types.Types) { func registerInfoHandlers(mux *httprouter.Router, args []string, cache *fileCache, formats *types.Types, errorChannel chan<- error) {
if Cache { if Cache {
register(mux, Prefix+"/html/", serveIndexHtml(args, cache, false)) register(mux, Prefix+"/html/", serveIndexHtml(args, cache, false))
if PageLength != 0 { if PageLength != 0 {
register(mux, Prefix+"/html/:page", serveIndexHtml(args, cache, true)) register(mux, Prefix+"/html/:page", serveIndexHtml(args, cache, true))
} }
register(mux, Prefix+"/json", serveIndexJson(args, cache)) register(mux, Prefix+"/json", serveIndexJson(args, cache, errorChannel))
if PageLength != 0 { if PageLength != 0 {
register(mux, Prefix+"/json/:page", serveIndexJson(args, cache)) register(mux, Prefix+"/json/:page", serveIndexJson(args, cache, errorChannel))
} }
} }

View File

@ -11,7 +11,7 @@ import (
) )
const ( const (
ReleaseVersion string = "0.88.1" ReleaseVersion string = "0.89.0"
) )
var ( var (
@ -22,6 +22,7 @@ var (
CacheFile string CacheFile string
Code bool Code bool
CodeTheme string CodeTheme string
ExitOnError bool
Filtering bool Filtering bool
Flash bool Flash bool
Handlers bool Handlers bool
@ -72,6 +73,7 @@ func init() {
rootCmd.Flags().StringVar(&CacheFile, "cache-file", "", "path to optional persistent cache file") rootCmd.Flags().StringVar(&CacheFile, "cache-file", "", "path to optional persistent cache file")
rootCmd.Flags().BoolVar(&Code, "code", false, "enable support for source code files") rootCmd.Flags().BoolVar(&Code, "code", false, "enable support for source code files")
rootCmd.Flags().StringVar(&CodeTheme, "code-theme", "solarized-dark256", "theme for source code syntax highlighting") rootCmd.Flags().StringVar(&CodeTheme, "code-theme", "solarized-dark256", "theme for source code syntax highlighting")
rootCmd.Flags().BoolVar(&ExitOnError, "exit-on-error", false, "shut down webserver on error, instead of just printing the error")
rootCmd.Flags().BoolVarP(&Filtering, "filter", "f", false, "enable filtering") rootCmd.Flags().BoolVarP(&Filtering, "filter", "f", false, "enable filtering")
rootCmd.Flags().BoolVar(&Flash, "flash", false, "enable support for shockwave flash files (via ruffle.rs)") rootCmd.Flags().BoolVar(&Flash, "flash", false, "enable support for shockwave flash files (via ruffle.rs)")
rootCmd.Flags().BoolVar(&Handlers, "handlers", false, "display registered handlers (for debugging)") rootCmd.Flags().BoolVar(&Handlers, "handlers", false, "display registered handlers (for debugging)")

View File

@ -6,6 +6,7 @@ package cmd
import ( import (
"bytes" "bytes"
"context"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -39,7 +40,7 @@ const (
timeout time.Duration = 10 * time.Second timeout time.Duration = 10 * time.Second
) )
func serveStaticFile(paths []string, cache *fileCache) httprouter.Handle { func serveStaticFile(paths []string, cache *fileCache, errorChannel chan<- error) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
prefix := Prefix + sourcePrefix prefix := Prefix + sourcePrefix
@ -47,7 +48,7 @@ func serveStaticFile(paths []string, cache *fileCache) httprouter.Handle {
prefixedFilePath, err := stripQueryParams(path) prefixedFilePath, err := stripQueryParams(path)
if err != nil { if err != nil {
fmt.Println(err) errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
@ -56,7 +57,7 @@ func serveStaticFile(paths []string, cache *fileCache) httprouter.Handle {
filePath, err := filepath.EvalSymlinks(strings.TrimPrefix(prefixedFilePath, prefix)) filePath, err := filepath.EvalSymlinks(strings.TrimPrefix(prefixedFilePath, prefix))
if err != nil { if err != nil {
fmt.Println(err) errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
@ -71,6 +72,8 @@ func serveStaticFile(paths []string, cache *fileCache) httprouter.Handle {
exists, err := fileExists(filePath) exists, err := fileExists(filePath)
if err != nil { if err != nil {
errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
return return
@ -86,6 +89,8 @@ func serveStaticFile(paths []string, cache *fileCache) httprouter.Handle {
buf, err := os.ReadFile(filePath) buf, err := os.ReadFile(filePath)
if err != nil { if err != nil {
errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
return return
@ -98,6 +103,8 @@ func serveStaticFile(paths []string, cache *fileCache) httprouter.Handle {
if Russian { if Russian {
err = os.Remove(filePath) err = os.Remove(filePath)
if err != nil { if err != nil {
errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
return return
@ -120,11 +127,11 @@ func serveStaticFile(paths []string, cache *fileCache) httprouter.Handle {
} }
} }
func serveRoot(paths []string, regexes *regexes, cache *fileCache, formats *types.Types) httprouter.Handle { func serveRoot(paths []string, regexes *regexes, cache *fileCache, formats *types.Types, errorChannel chan<- error) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
refererUri, err := stripQueryParams(refererToUri(r.Referer())) refererUri, err := stripQueryParams(refererToUri(r.Referer()))
if err != nil { if err != nil {
fmt.Println(err) errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
@ -147,7 +154,7 @@ func serveRoot(paths []string, regexes *regexes, cache *fileCache, formats *type
if refererUri != "" { if refererUri != "" {
filePath, err = nextFile(strippedRefererUri, sortOrder, regexes, formats) filePath, err = nextFile(strippedRefererUri, sortOrder, regexes, formats)
if err != nil { if err != nil {
fmt.Println(err) errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
@ -174,7 +181,7 @@ func serveRoot(paths []string, regexes *regexes, cache *fileCache, formats *type
return return
case err != nil: case err != nil:
fmt.Println(err) errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
@ -194,7 +201,7 @@ func serveRoot(paths []string, regexes *regexes, cache *fileCache, formats *type
} }
} }
func serveMedia(paths []string, regexes *regexes, formats *types.Types) httprouter.Handle { func serveMedia(paths []string, regexes *regexes, formats *types.Types, errorChannel chan<- error) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
filters := &filters{ filters := &filters{
included: splitQueryParams(r.URL.Query().Get("include"), regexes), included: splitQueryParams(r.URL.Query().Get("include"), regexes),
@ -211,7 +218,7 @@ func serveMedia(paths []string, regexes *regexes, formats *types.Types) httprout
exists, err := fileExists(path) exists, err := fileExists(path)
if err != nil { if err != nil {
fmt.Println(err) errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
@ -252,19 +259,37 @@ func serveMedia(paths []string, regexes *regexes, formats *types.Types) httprout
htmlBody.WriteString(`<!DOCTYPE html><html class="bg" lang="en"><head>`) htmlBody.WriteString(`<!DOCTYPE html><html class="bg" lang="en"><head>`)
htmlBody.WriteString(faviconHtml) htmlBody.WriteString(faviconHtml)
htmlBody.WriteString(fmt.Sprintf(`<style>%s</style>`, format.Css())) htmlBody.WriteString(fmt.Sprintf(`<style>%s</style>`, format.Css()))
htmlBody.WriteString((format.Title(rootUrl, fileUri, path, fileName, Prefix, mimeType)))
title, err := format.Title(rootUrl, fileUri, path, fileName, Prefix, mimeType)
if err != nil {
errorChannel <- err
serverError(w, r, nil)
return
}
htmlBody.WriteString(title)
htmlBody.WriteString(`</head><body>`) htmlBody.WriteString(`</head><body>`)
if refreshInterval != "0ms" { if refreshInterval != "0ms" {
htmlBody.WriteString(fmt.Sprintf("<script>window.onload = function(){setInterval(function(){window.location.href = '%s';}, %d);};</script>", htmlBody.WriteString(fmt.Sprintf("<script>window.onload = function(){setInterval(function(){window.location.href = '%s';}, %d);};</script>",
rootUrl, rootUrl,
refreshTimer)) refreshTimer))
} }
htmlBody.WriteString((format.Body(rootUrl, fileUri, path, fileName, Prefix, mimeType)))
body, err := format.Body(rootUrl, fileUri, path, fileName, Prefix, mimeType)
if err != nil {
errorChannel <- err
serverError(w, r, nil)
return
}
htmlBody.WriteString(body)
htmlBody.WriteString(`</body></html>`) htmlBody.WriteString(`</body></html>`)
_, err = io.WriteString(w, gohtml.Format(htmlBody.String())) _, err = io.WriteString(w, gohtml.Format(htmlBody.String()))
if err != nil { if err != nil {
fmt.Println(err) errorChannel <- err
serverError(w, r, nil) serverError(w, r, nil)
@ -387,7 +412,9 @@ func ServePage(args []string) error {
Prefix = Prefix + "/" Prefix = Prefix + "/"
} }
register(mux, Prefix, serveRoot(paths, regexes, cache, formats)) errorChannel := make(chan error)
register(mux, Prefix, serveRoot(paths, regexes, cache, formats, errorChannel))
Prefix = strings.TrimSuffix(Prefix, "/") Prefix = strings.TrimSuffix(Prefix, "/")
@ -395,22 +422,25 @@ func ServePage(args []string) error {
register(mux, "/", redirectRoot()) register(mux, "/", redirectRoot())
} }
register(mux, Prefix+"/favicons/*favicon", serveFavicons()) register(mux, Prefix+"/favicons/*favicon", serveFavicons(errorChannel))
register(mux, Prefix+"/favicon.ico", serveFavicons()) register(mux, Prefix+"/favicon.ico", serveFavicons(errorChannel))
register(mux, Prefix+mediaPrefix+"/*media", serveMedia(paths, regexes, formats)) register(mux, Prefix+mediaPrefix+"/*media", serveMedia(paths, regexes, formats, errorChannel))
register(mux, Prefix+sourcePrefix+"/*static", serveStaticFile(paths, cache)) register(mux, Prefix+sourcePrefix+"/*static", serveStaticFile(paths, cache, errorChannel))
register(mux, Prefix+"/version", serveVersion()) register(mux, Prefix+"/version", serveVersion())
if Cache { if Cache {
registerCacheHandlers(mux, args, cache, formats) err = registerCacheHandlers(mux, args, cache, formats, errorChannel)
if err != nil {
return err
}
} }
if Info { if Info {
registerInfoHandlers(mux, args, cache, formats) registerInfoHandlers(mux, args, cache, formats, errorChannel)
} }
if Profile { if Profile {
@ -421,6 +451,18 @@ func ServePage(args []string) error {
fmt.Printf("WARNING! Files *will* be deleted after serving!\n\n") fmt.Printf("WARNING! Files *will* be deleted after serving!\n\n")
} }
go func() {
for err := range errorChannel {
fmt.Printf("%s | Error: %v\n", time.Now().Format(logDate), err)
if ExitOnError {
fmt.Printf("%s | Shutting down...\n", time.Now().Format(logDate))
srv.Shutdown(context.Background())
}
}
}()
err = srv.ListenAndServe() err = srv.ListenAndServe()
if !errors.Is(err, http.ErrServerClosed) { if !errors.Is(err, http.ErrServerClosed) {
return err return err

View File

@ -22,16 +22,16 @@ func (t Format) Css() string {
return css.String() return css.String()
} }
func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
return fmt.Sprintf(`<title>%s</title>`, fileName) return fmt.Sprintf(`<title>%s</title>`, fileName), nil
} }
func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
return fmt.Sprintf(`<a href="%s"><audio controls autoplay loop preload="auto"><source src="%s" type="%s" alt="Roulette selected: %s">Your browser does not support the audio tag.</audio></a>`, return fmt.Sprintf(`<a href="%s"><audio controls autoplay loop preload="auto"><source src="%s" type="%s" alt="Roulette selected: %s">Your browser does not support the audio tag.</audio></a>`,
rootUrl, rootUrl,
fileUri, fileUri,
mime, mime,
fileName) fileName), nil
} }
func (t Format) Extensions() map[string]string { func (t Format) Extensions() map[string]string {

View File

@ -60,14 +60,14 @@ func (t Format) Css() string {
return css.String() return css.String()
} }
func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
return fmt.Sprintf(`<title>%s</title>`, fileName) return fmt.Sprintf(`<title>%s</title>`, fileName), nil
} }
func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
contents, err := os.ReadFile(filePath) contents, err := os.ReadFile(filePath)
if err != nil { if err != nil {
return "" return "", err
} }
contentString := string(contents) contentString := string(contents)
@ -97,24 +97,24 @@ func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string)
iterator, err := lexer.Tokenise(nil, contentString) iterator, err := lexer.Tokenise(nil, contentString)
if err != nil { if err != nil {
return "" return "", err
} }
err = formatter.Format(w, style, iterator) err = formatter.Format(w, style, iterator)
if err != nil { if err != nil {
return "" return "", err
} }
w.Flush() w.Flush()
b, err := io.ReadAll(r) b, err := io.ReadAll(r)
if err != nil { if err != nil {
return "" return "", err
} }
return fmt.Sprintf(`<a href="%s">%s</a>`, return fmt.Sprintf(`<a href="%s">%s</a>`,
rootUrl, rootUrl,
string(b)) string(b)), nil
} }
func (t Format) Extensions() map[string]string { func (t Format) Extensions() map[string]string {

View File

@ -22,17 +22,17 @@ func (t Format) Css() string {
return css.String() return css.String()
} }
func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
return fmt.Sprintf(`<title>%s</title>`, fileName) return fmt.Sprintf(`<title>%s</title>`, fileName), nil
} }
func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
var html strings.Builder var html strings.Builder
html.WriteString(fmt.Sprintf(`<script src="https://unpkg.com/@ruffle-rs/ruffle"></script><script>window.RufflePlayer.config = {autoplay:"on"};</script><embed src="%s"></embed>`, fileUri)) html.WriteString(fmt.Sprintf(`<script src="https://unpkg.com/@ruffle-rs/ruffle"></script><script>window.RufflePlayer.config = {autoplay:"on"};</script><embed src="%s"></embed>`, fileUri))
html.WriteString(fmt.Sprintf(`<br /><button onclick="window.location.href = '%s';">Next</button>`, rootUrl)) html.WriteString(fmt.Sprintf(`<br /><button onclick="window.location.href = '%s';">Next</button>`, rootUrl))
return html.String() return html.String(), nil
} }
func (t Format) Extensions() map[string]string { func (t Format) Extensions() map[string]string {

View File

@ -37,22 +37,22 @@ func (t Format) Css() string {
return css.String() return css.String()
} }
func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
dimensions, err := ImageDimensions(filePath) dimensions, err := ImageDimensions(filePath)
if err != nil { if err != nil {
fmt.Println(err) return "", err
} }
return fmt.Sprintf(`<title>%s (%dx%d)</title>`, return fmt.Sprintf(`<title>%s (%dx%d)</title>`,
fileName, fileName,
dimensions.width, dimensions.width,
dimensions.height) dimensions.height), nil
} }
func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
dimensions, err := ImageDimensions(filePath) dimensions, err := ImageDimensions(filePath)
if err != nil { if err != nil {
fmt.Println(err) return "", err
} }
return fmt.Sprintf(`<a href="%s"><img src="%s" width="%d" height="%d" type="%s" alt="Roulette selected: %s"></a>`, return fmt.Sprintf(`<a href="%s"><img src="%s" width="%d" height="%d" type="%s" alt="Roulette selected: %s"></a>`,
@ -61,7 +61,7 @@ func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string)
dimensions.width, dimensions.width,
dimensions.height, dimensions.height,
mime, mime,
fileName) fileName), nil
} }
func (t Format) Extensions() map[string]string { func (t Format) Extensions() map[string]string {

View File

@ -27,11 +27,11 @@ func (t Format) Css() string {
return css.String() return css.String()
} }
func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
return fmt.Sprintf(`<title>%s</title>`, fileName) return fmt.Sprintf(`<title>%s</title>`, fileName), nil
} }
func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
body, err := os.ReadFile(filePath) body, err := os.ReadFile(filePath)
if err != nil { if err != nil {
body = []byte{} body = []byte{}
@ -39,7 +39,7 @@ func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string)
return fmt.Sprintf(`<a href="%s"><textarea autofocus readonly>%s</textarea></a>`, return fmt.Sprintf(`<a href="%s"><textarea autofocus readonly>%s</textarea></a>`,
rootUrl, rootUrl,
body) body), nil
} }
func (t Format) Extensions() map[string]string { func (t Format) Extensions() map[string]string {

View File

@ -16,8 +16,8 @@ var SupportedFormats = &Types{
type Type interface { type Type interface {
Css() string Css() string
Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) string Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error)
Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) string Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error)
Extensions() map[string]string Extensions() map[string]string
MimeType(string) string MimeType(string) string
Validate(filePath string) bool Validate(filePath string) bool

View File

@ -25,16 +25,16 @@ func (t Format) Css() string {
return css.String() return css.String()
} }
func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
return fmt.Sprintf(`<title>%s</title>`, fileName) return fmt.Sprintf(`<title>%s</title>`, fileName), nil
} }
func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) string { func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
return fmt.Sprintf(`<a href="%s"><video controls autoplay loop preload="auto"><source src="%s" type="%s" alt="Roulette selected: %s">Your browser does not support the video tag.</video></a>`, return fmt.Sprintf(`<a href="%s"><video controls autoplay loop preload="auto"><source src="%s" type="%s" alt="Roulette selected: %s">Your browser does not support the video tag.</video></a>`,
rootUrl, rootUrl,
fileUri, fileUri,
mime, mime,
fileName) fileName), nil
} }
func (t Format) Extensions() map[string]string { func (t Format) Extensions() map[string]string {