Updates
A bunch of updatesss
This commit is contained in:
parent
56ddd764ee
commit
cbc66c5651
14 changed files with 227 additions and 13 deletions
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
|
@ -9,7 +10,19 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
cfg, err := config.LoadConfig("config.yaml")
|
||||
var cfgFlag = flag.String("c", "config.yaml", "Configuration file to load")
|
||||
var genFlag = flag.String("g", "", "Generate an example configuration to the given file")
|
||||
flag.Parse()
|
||||
|
||||
if *genFlag != "" {
|
||||
if err := config.WriteExampleConfig(*genFlag); err != nil {
|
||||
log.Fatalf("Failed to create example config: %v", err)
|
||||
}
|
||||
log.Printf("Generated example configuration at: %s\n", *genFlag)
|
||||
return
|
||||
}
|
||||
|
||||
cfg, err := config.LoadConfig(*cfgFlag)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load config: %v", err)
|
||||
}
|
||||
|
|
3
embed.go
3
embed.go
|
@ -4,3 +4,6 @@ import "embed"
|
|||
|
||||
//go:embed templates/*
|
||||
var TemplateFS embed.FS
|
||||
|
||||
//go:embed static/*
|
||||
var StaticFS embed.FS
|
||||
|
|
|
@ -6,12 +6,34 @@ import (
|
|||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ServeDirectory string `yaml:"serveDirectory"`
|
||||
Port int `int:"port"`
|
||||
var defaultCfg = Config{
|
||||
ServerName: "My Fileserver",
|
||||
Port: 8080,
|
||||
Directories: []Directory{
|
||||
{
|
||||
Id: "example",
|
||||
DisplayName: "Example Directory",
|
||||
Path: "/path/to/directory",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// LoadConfig loads a Config from the given path.
|
||||
// Directory represents a configuration for a directory to be served.
|
||||
type Directory struct {
|
||||
Id string `yaml:"id"`
|
||||
DisplayName string `yaml:"display_name"`
|
||||
Description string `yaml:"description"`
|
||||
Path string `yaml:"path"`
|
||||
}
|
||||
|
||||
// Config represents a configuration for the fileserver.
|
||||
type Config struct {
|
||||
ServerName string `yaml:"server_name"`
|
||||
Port int `yaml:"port"`
|
||||
Directories []Directory `yaml:"directories"`
|
||||
}
|
||||
|
||||
// LoadConfig loads configuration from a YAML file.
|
||||
func LoadConfig(path string) (*Config, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
|
@ -25,3 +47,13 @@ func LoadConfig(path string) (*Config, error) {
|
|||
|
||||
return &cfg, nil
|
||||
}
|
||||
|
||||
// WriteExampleConfig writes an example configuration to a YAML file.
|
||||
func WriteExampleConfig(filepath string) error {
|
||||
data, err := yaml.Marshal(&defaultCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(filepath, data, 0644)
|
||||
}
|
||||
|
|
16
internal/server/controllers/directories.go
Normal file
16
internal/server/controllers/directories.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"git.zervo.org/zervo/fileserver/internal/config"
|
||||
"git.zervo.org/zervo/fileserver/internal/server/views"
|
||||
"github.com/kataras/iris/v12"
|
||||
)
|
||||
|
||||
// DirectoriesRoute registers all routes under /directories
|
||||
func DirectoriesRoute(app *iris.Application, cfg *config.Config) {
|
||||
party := app.Party("/directories")
|
||||
|
||||
party.Get("/", func(ctx iris.Context) {
|
||||
views.DirectoriesView(ctx, cfg)
|
||||
})
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
|
@ -9,6 +10,7 @@ import (
|
|||
|
||||
"git.zervo.org/zervo/fileserver"
|
||||
"git.zervo.org/zervo/fileserver/internal/config"
|
||||
"git.zervo.org/zervo/fileserver/internal/server/controllers"
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/kataras/iris/v12/view"
|
||||
)
|
||||
|
@ -17,16 +19,23 @@ import (
|
|||
func Start(cfg *config.Config) error {
|
||||
app := iris.New()
|
||||
|
||||
subFs, err := fs.Sub(fileserver.TemplateFS, "templates")
|
||||
templates, err := fs.Sub(fileserver.TemplateFS, "templates")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to sub fs")
|
||||
return errors.New("fs.Sub operation on TemplateFS")
|
||||
}
|
||||
|
||||
tmpl := view.HTML(subFs, ".html")
|
||||
app.RegisterView(tmpl)
|
||||
templater := view.HTML(templates, ".html").Layout("layouts/main.html")
|
||||
app.RegisterView(templater)
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
files, err := os.ReadDir(cfg.ServeDirectory)
|
||||
// Register core routes
|
||||
app.Get("/", index)
|
||||
app.Get("/favicon.ico", favicon)
|
||||
|
||||
// Register controller routes
|
||||
controllers.DirectoriesRoute(app, cfg)
|
||||
|
||||
app.Get("/aaa", func(ctx iris.Context) {
|
||||
files, err := os.ReadDir("test")
|
||||
if err != nil {
|
||||
ctx.StatusCode(http.StatusInternalServerError)
|
||||
ctx.WriteString("Could not read directory")
|
||||
|
@ -48,9 +57,25 @@ func Start(cfg *config.Config) error {
|
|||
|
||||
app.Get("/download/{filename:string}", func(ctx iris.Context) {
|
||||
filename := ctx.Params().Get("filename")
|
||||
filePath := filepath.Join(cfg.ServeDirectory, filename)
|
||||
filePath := filepath.Join("test", filename)
|
||||
ctx.SendFile(filePath, filename)
|
||||
})
|
||||
|
||||
return app.Listen(":" + fmt.Sprint(cfg.Port))
|
||||
}
|
||||
|
||||
// index redirects request from '/' to '/directories'.
|
||||
func index(ctx iris.Context) {
|
||||
ctx.Redirect("/directories")
|
||||
}
|
||||
|
||||
// favicon returns favicon data upon request.
|
||||
func favicon(ctx iris.Context) {
|
||||
data, err := fileserver.StaticFS.ReadFile("static/favicon.ico")
|
||||
if err != nil {
|
||||
ctx.StatusCode(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
ctx.ContentType("image/x-icon")
|
||||
ctx.Write(data)
|
||||
}
|
||||
|
|
29
internal/server/views/directories.go
Normal file
29
internal/server/views/directories.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package views
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.zervo.org/zervo/fileserver/internal/config"
|
||||
"git.zervo.org/zervo/fileserver/internal/util/data"
|
||||
"github.com/kataras/iris/v12"
|
||||
)
|
||||
|
||||
type directorypage struct {
|
||||
Directories []config.Directory
|
||||
}
|
||||
|
||||
// DirectoriesView renders the view for '/directories'.
|
||||
func DirectoriesView(ctx iris.Context, cfg *config.Config) {
|
||||
ctx.CompressWriter(true)
|
||||
ctx.ViewData("", data.LayoutData{
|
||||
ServerName: cfg.ServerName,
|
||||
ServerVersion: "0.0.1",
|
||||
Page: directorypage{
|
||||
Directories: cfg.Directories,
|
||||
},
|
||||
})
|
||||
if err := ctx.View("directories.html"); err != nil {
|
||||
errorView(ctx, fmt.Errorf("Failed to render DirectoriesView: %v", err))
|
||||
return
|
||||
}
|
||||
}
|
8
internal/server/views/error.go
Normal file
8
internal/server/views/error.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
package views
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
// errorView renders a view for unexpected errors.
|
||||
func errorView(ctx iris.Context, err error) {
|
||||
ctx.HTML(`<h2>Unexpected Error</h2><br><p style="color:red;">%s</p>`, err.Error())
|
||||
}
|
13
internal/util/data/layout.go
Normal file
13
internal/util/data/layout.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package data
|
||||
|
||||
// LayoutData holds templating data for a layout.
|
||||
type LayoutData struct {
|
||||
// ServerName is the custom name of the server instance.
|
||||
ServerName string
|
||||
|
||||
// ServerVersion is a string representing the server version.
|
||||
ServerVersion string
|
||||
|
||||
// Page contains page/view-specific data.
|
||||
Page any
|
||||
}
|
BIN
static/favicon.ico
Normal file
BIN
static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 KiB |
23
templates/directories.html
Normal file
23
templates/directories.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body class="ma-6">
|
||||
<h4 class="mt-4 mb-3">Welcome To</h4>
|
||||
{{ render "partials/badge.html" . }}
|
||||
<h3 class="p-3 mb-3">Select Directory</h3>
|
||||
<div class="d-flex flex-column align-items-center gap-4 mb-3">
|
||||
{{range .Page.Directories}}
|
||||
<div class="card shadow w-100 text-start bg-dark-subtle" style="max-width: 500px;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-primary"><i class="bi bi-folder2-open me-2"></i>{{.DisplayName}}</h5>
|
||||
<p class="card-text">{{.Description}}</p>
|
||||
<a href="/b/{{.Id}}" class="btn btn-primary"><i class="bi bi-arrow-up-right-square-fill me-1"></i>Open</a>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<h5 class="text-warning-emphasis">
|
||||
No directories found.<br>If you are the administrator of this server,<br>you can add directories in the server configuration.
|
||||
</h5>
|
||||
{{end}}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
27
templates/layouts/main.html
Normal file
27
templates/layouts/main.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-LN+7fdVzj6u52u30Kp6M/trliBMCMKTyK833zpbD+pXdCLuTusPj697FH4R/5mcr" crossorigin="anonymous">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css " rel="stylesheet">
|
||||
<title>{{.ServerName}}</title>
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="d-flex flex-column min-vh-100">
|
||||
|
||||
<main class="flex-grow-1 d-flex justify-content-center">
|
||||
<div class="container text-center">
|
||||
{{ yield . }}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{{ render "partials/footer.html" . }}
|
||||
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -2,7 +2,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Go FileServer</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-LN+7fdVzj6u52u30Kp6M/trliBMCMKTyK833zpbD+pXdCLuTusPj697FH4R/5mcr" crossorigin="anonymous">
|
||||
</head>
|
||||
<body class="container mt-5">
|
||||
<h1 class="mb-4">File Server</h1>
|
3
templates/partials/badge.html
Normal file
3
templates/partials/badge.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
<div class="d-inline-block shadow p-2 px-3 mb-5 border rounded bg-dark-subtle">
|
||||
<h1><i class="bi bi-file-zip me-2"></i>{{if .ServerName}}{{.ServerName}}{{else}}My Fileserver{{end}}</h1>
|
||||
</div>
|
23
templates/partials/footer.html
Normal file
23
templates/partials/footer.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<footer class="bg-secondary-subtle text-secondary-emphasis py-1 mt-auto w-100">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-row justify-content-between text-center">
|
||||
<div class="mt-2">
|
||||
<h5>Fileserver</h5>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<a href="http://git.zervo.org/zervo/Fileserver" class="text-secondary-emphasis text-decoration-none mx-2">
|
||||
<i class="bi bi-git me-1"></i>Source
|
||||
</a>
|
||||
<a href="/directories" class="text-secondary-emphasis text-decoration-none mx-2">
|
||||
<i class="bi bi-folder-fill me-1"></i>Directories
|
||||
</a>
|
||||
<a href="#" class="text-secondary-emphasis text-decoration-none mx-2">
|
||||
<i class="bi bi-info-circle-fill me-1"></i>Information
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<h5>v{{.ServerVersion}}</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
Loading…
Add table
Reference in a new issue