Skip to content

API/UI Layout and Refactor #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,39 +31,39 @@ release/$(APP)_$(VERSION)_osx_x86_64.tar.gz: binaries/osx_x86_64/$(APP)
tar cfz release/$(APP)_$(VERSION)_osx_x86_64.tar.gz -C binaries/osx_x86_64 $(APP)

binaries/osx_x86_64/$(APP): $(GOFILES)
GOOS=darwin GOARCH=amd64 go build -ldflags "-X main.version=$(VERSION)" -o binaries/osx_x86_64/$(APP) .
GOOS=darwin GOARCH=amd64 go build -ldflags "-X main.version=$(VERSION)" -o binaries/osx_x86_64/$(APP) ./cmd/...

release/$(APP)_$(VERSION)_windows_x86_64.zip: binaries/windows_x86_64/$(APP).exe
mkdir -p release
cd ./binaries/windows_x86_64 && zip -r -D ../../release/$(APP)_$(VERSION)_windows_x86_64.zip $(APP).exe

binaries/windows_x86_64/$(APP).exe: $(GOFILES)
GOOS=windows GOARCH=amd64 go build -ldflags "-X main.version=$(VERSION)" -o binaries/windows_x86_64/$(APP).exe .
GOOS=windows GOARCH=amd64 go build -ldflags "-X main.version=$(VERSION)" -o binaries/windows_x86_64/$(APP).exe ./cmd/...

release/$(APP)_$(VERSION)_linux_x86_64.tar.gz: binaries/linux_x86_64/$(APP)
mkdir -p release
tar cfz release/$(APP)_$(VERSION)_linux_x86_64.tar.gz -C binaries/linux_x86_64 $(APP)

binaries/linux_x86_64/$(APP): $(GOFILES)
GOOS=linux GOARCH=amd64 go build -ldflags "-X main.version=$(VERSION)" -o binaries/linux_x86_64/$(APP) .
GOOS=linux GOARCH=amd64 go build -ldflags "-X main.Version=$(VERSION)" -o binaries/linux_x86_64/$(APP) ./cmd/...

release/$(APP)_$(VERSION)_windows_x86_32.zip: binaries/windows_x86_32/$(APP).exe
mkdir -p release
cd ./binaries/windows_x86_32 && zip -r -D ../../release/$(APP)_$(VERSION)_windows_x86_32.zip $(APP).exe

binaries/windows_x86_32/$(APP).exe: $(GOFILES)
GOOS=windows GOARCH=386 go build -ldflags "-X main.version=$(VERSION)" -o binaries/windows_x86_32/$(APP).exe .
GOOS=windows GOARCH=386 go build -ldflags "-X main.version=$(VERSION)" -o binaries/windows_x86_32/$(APP).exe ./cmd/...

release/$(APP)_$(VERSION)_linux_x86_32.tar.gz: binaries/linux_x86_32/$(APP)
mkdir -p release
tar cfz release/$(APP)_$(VERSION)_linux_x86_32.tar.gz -C binaries/linux_x86_32 $(APP)

binaries/linux_x86_32/$(APP): $(GOFILES)
GOOS=linux GOARCH=386 go build -ldflags "-X main.version=$(VERSION)" -o binaries/linux_x86_32/$(APP) .
GOOS=linux GOARCH=386 go build -ldflags "-X main.version=$(VERSION)" -o binaries/linux_x86_32/$(APP) ./cmd/...

release/$(APP)_$(VERSION)_linux_arm64.tar.gz: binaries/linux_arm64/$(APP)
mkdir -p release
tar cfz release/$(APP)_$(VERSION)_linux_arm64.tar.gz -C binaries/linux_arm64 $(APP)

binaries/linux_arm64/$(APP): $(GOFILES)
GOOS=linux GOARCH=arm64 go build -ldflags "-X main.version=$(VERSION)" -o binaries/linux_arm64/$(APP) .
GOOS=linux GOARCH=arm64 go build -ldflags "-X main.version=$(VERSION)" -o binaries/linux_arm64/$(APP) ./cmd/...
119 changes: 119 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package main

import (
"context"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"os"
"strconv"

"github.com/sgreben/httpfileserver"
)

const (
addrEnvVarName = "ADDR"
allowUploadsEnvVarName = "UPLOADS"
defaultAddr = ":8080"
portEnvVarName = "PORT"
quietEnvVarName = "QUIET"
sslCertificateEnvVarName = "SSL_CERTIFICATE"
sslKeyEnvVarName = "SSL_KEY"
)

var Version = ":unknown:"

var addrFlag string
var portFlag int

func addr(cfg httpfileserver.Config) (string, error) {
portSet := portFlag != 0
addrSet := addrFlag != ""
switch {
case portSet && addrSet:
a, err := net.ResolveTCPAddr("tcp", addrFlag)
if err != nil {
return "", err
}
a.Port = portFlag
return a.String(), nil
case !portSet && addrSet:
a, err := net.ResolveTCPAddr("tcp", addrFlag)
if err != nil {
return "", err
}
return a.String(), nil
case portSet && !addrSet:
return fmt.Sprintf(":%d", portFlag), nil
case !portSet && !addrSet:
fallthrough
default:
return defaultAddr, nil
}
}

func configureRuntime(cfg httpfileserver.Config) httpfileserver.Config {
var quietFlag bool

log.SetFlags(log.LUTC | log.Ldate | log.Ltime)
log.SetOutput(os.Stderr)
if addrFlag == "" {
addrFlag = defaultAddr
}
flag.StringVar(&addrFlag, "addr", addrFlag, fmt.Sprintf("address to listen on (environment variable %q)", addrEnvVarName))
flag.StringVar(&addrFlag, "a", addrFlag, "(alias for -addr)")
flag.IntVar(&portFlag, "port", portFlag, fmt.Sprintf("port to listen on (overrides -addr port) (environment variable %q)", portEnvVarName))
flag.IntVar(&portFlag, "p", portFlag, "(alias for -port)")
flag.BoolVar(&quietFlag, "quiet", quietFlag, fmt.Sprintf("disable all log output (environment variable %q)", quietEnvVarName))
flag.BoolVar(&quietFlag, "q", quietFlag, "(alias for -quiet)")
flag.BoolVar(&cfg.AllowUploadsFlag, "uploads", cfg.AllowUploadsFlag, fmt.Sprintf("allow uploads (environment variable %q)", allowUploadsEnvVarName))
flag.BoolVar(&cfg.AllowUploadsFlag, "u", cfg.AllowUploadsFlag, "(alias for -uploads)")
flag.Var(&cfg.Routes, "route", cfg.Routes.Help())
flag.Var(&cfg.Routes, "r", "(alias for -route)")
flag.StringVar(&cfg.SslCertificate, "ssl-cert", cfg.SslCertificate, fmt.Sprintf("path to SSL server certificate (environment variable %q)", sslCertificateEnvVarName))
flag.StringVar(&cfg.SslKey, "ssl-key", cfg.SslKey, fmt.Sprintf("path to SSL private key (environment variable %q)", sslKeyEnvVarName))
flag.Parse()
if quietFlag {
log.SetOutput(ioutil.Discard)
}
for i := 0; i < flag.NArg(); i++ {
arg := flag.Arg(i)
err := cfg.Routes.Set(arg)
if err != nil {
log.Fatalf("%q: %v", arg, err)
}
}

return cfg
}

func newConfig() httpfileserver.Config {
portFlag64, _ := strconv.ParseInt(os.Getenv(portEnvVarName), 10, 64)
portFlag = int(portFlag64)

cfg := httpfileserver.NewConfig()
cfg.AllowUploadsFlag = os.Getenv(allowUploadsEnvVarName) == "true"
cfg.SslCertificate = os.Getenv(sslCertificateEnvVarName)
cfg.SslKey = os.Getenv(sslKeyEnvVarName)
cfg.RootRoute = "/"

return cfg
}

func main() {
cfg := configureRuntime(newConfig())
log.Printf("httpfileserver v%s", Version)

addr, err := addr(cfg)
if err != nil {
log.Fatalf("address/port: %v", err)
}

cfg.Addr = addr
err = httpfileserver.Serve(context.Background(), cfg)
if err != nil {
log.Fatalf("start server: %v", err)
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/sgreben/http-file-server
module github.com/sgreben/httpfileserver

go 1.16
72 changes: 72 additions & 0 deletions httpfileserver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package httpfileserver

import (
"context"
"log"
"net/http"
"os"
"path/filepath"

"github.com/sgreben/httpfileserver/internal/routes"
)

type Config struct {
Addr string
AllowUploadsFlag bool
RootRoute string
SslCertificate string
SslKey string
Routes routes.Routes
}

func NewConfig() Config {
return Config{
Addr: ":8080",
AllowUploadsFlag: false,
RootRoute: "/",
SslCertificate: "",
SslKey: "",
}
}

func Serve(ctx context.Context, cfg Config) error {
mux := http.DefaultServeMux
handlers := make(map[string]http.Handler)
paths := make(map[string]string)

if len(cfg.Routes.Values) == 0 {
_ = cfg.Routes.Set(".")
}

for _, route := range cfg.Routes.Values {
handlers[route.Route] = &fileHandler{
route: route.Route,
path: route.Path,
allowUpload: cfg.AllowUploadsFlag,
}
paths[route.Route] = route.Path
}

for route, path := range paths {
mux.Handle(route, handlers[route])
log.Printf("serving local path %q on %q", path, route)
}

_, rootRouteTaken := handlers[cfg.RootRoute]
if !rootRouteTaken {
route := cfg.Routes.Values[0].Route
mux.Handle(cfg.RootRoute, http.RedirectHandler(route, http.StatusTemporaryRedirect))
log.Printf("redirecting to %q from %q", route, cfg.RootRoute)
}

binaryPath, _ := os.Executable()
if binaryPath == "" {
binaryPath = "server"
}
if cfg.SslCertificate != "" && cfg.SslKey != "" {
log.Printf("%s (HTTPS) listening on %q", filepath.Base(binaryPath), cfg.Addr)
return http.ListenAndServeTLS(cfg.Addr, cfg.SslCertificate, cfg.SslKey, mux)
}
log.Printf("%s listening on %q", filepath.Base(binaryPath), cfg.Addr)
return http.ListenAndServe(cfg.Addr, mux)
}
10 changes: 5 additions & 5 deletions routes.go → internal/routes/routes.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package main
package routes

import (
"fmt"
"path/filepath"
"strings"
)

type routes struct {
type Routes struct {
Separator string

Values []struct {
Expand All @@ -16,7 +16,7 @@ type routes struct {
Texts []string
}

func (fv *routes) help() string {
func (fv *Routes) Help() string {
separator := "="
if fv.Separator != "" {
separator = fv.Separator
Expand All @@ -25,7 +25,7 @@ func (fv *routes) help() string {
}

// Set is flag.Value.Set
func (fv *routes) Set(v string) error {
func (fv *Routes) Set(v string) error {
separator := "="
if fv.Separator != "" {
separator = fv.Separator
Expand Down Expand Up @@ -65,6 +65,6 @@ func (fv *routes) Set(v string) error {
return nil
}

func (fv *routes) String() string {
func (fv *Routes) String() string {
return strings.Join(fv.Texts, ", ")
}
4 changes: 2 additions & 2 deletions tar.gz.go → internal/targz/tar.gz.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package targz

import (
"archive/tar"
Expand All @@ -9,7 +9,7 @@ import (
"path/filepath"
)

func tarGz(w io.Writer, path string) error {
func TarGz(w io.Writer, path string) error {
basePath := path
addFile := func(w *tar.Writer, path string, stat os.FileInfo) error {
if stat.IsDir() {
Expand Down
4 changes: 2 additions & 2 deletions zip.go → internal/zip/zip.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package zip

import (
zipper "archive/zip"
Expand All @@ -8,7 +8,7 @@ import (
"path/filepath"
)

func zip(w io.Writer, path string) error {
func Zip(w io.Writer, path string) error {
basePath := path
addFile := func(w *zipper.Writer, path string, stat os.FileInfo) error {
if stat.IsDir() {
Expand Down
Loading