Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sgreben committed Nov 13, 2018
0 parents commit 94f3f0b
Show file tree
Hide file tree
Showing 9 changed files with 608 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/binaries/
/release/
/doc/screenshot.png
77 changes: 77 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
VERSION = 1.0.0

APP := http-file-server
PACKAGES := $(shell go list -f {{.Dir}} ./...)
GOFILES := $(addsuffix /*.go,$(PACKAGES))
GOFILES := $(wildcard $(GOFILES))

.PHONY: clean release README.md

clean:
rm -rf binaries/
rm -rf release/

# go get -u github.com/github/hub
release: README.md zip
git reset
git add README.md
git add Makefile
git commit -m "Release $(VERSION)" || true
git push
hub release create $(VERSION) -m "$(VERSION)" -a release/$(APP)_$(VERSION)_osx_x86_64.tar.gz -a release/$(APP)_$(VERSION)_windows_x86_64.zip -a release/$(APP)_$(VERSION)_linux_x86_64.tar.gz -a release/$(APP)_$(VERSION)_osx_x86_32.tar.gz -a release/$(APP)_$(VERSION)_windows_x86_32.zip -a release/$(APP)_$(VERSION)_linux_x86_32.tar.gz -a release/$(APP)_$(VERSION)_linux_arm64.tar.gz

README.md:
<README.template.md subst VERSION="$(VERSION)" APP="$(APP)" USAGE="$$(go get github.com/sgreben/$(APP); $(APP) -h 2>&1)" > README.md

zip: release/$(APP)_$(VERSION)_osx_x86_64.tar.gz release/$(APP)_$(VERSION)_windows_x86_64.zip release/$(APP)_$(VERSION)_linux_x86_64.tar.gz release/$(APP)_$(VERSION)_osx_x86_32.tar.gz release/$(APP)_$(VERSION)_windows_x86_32.zip release/$(APP)_$(VERSION)_linux_x86_32.tar.gz release/$(APP)_$(VERSION)_linux_arm64.tar.gz

binaries: binaries/osx_x86_64/$(APP) binaries/windows_x86_64/$(APP).exe binaries/linux_x86_64/$(APP) binaries/osx_x86_32/$(APP) binaries/windows_x86_32/$(APP).exe binaries/linux_x86_32/$(APP)

release/$(APP)_$(VERSION)_osx_x86_64.tar.gz: binaries/osx_x86_64/$(APP)
mkdir -p release
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) .

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 .

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) .

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

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

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 .

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) .

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) .
93 changes: 93 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# http-file-server

`http-file-server` is a dependency-free HTTP file server.

![screenshot](doc/screenshot.gif)

## Contents

<!-- TOC -->

- [Contents](#contents)
- [Examples](#examples)
- [Get it](#get-it)
- [Using `go get`](#using-go-get)
- [Pre-built binary](#pre-built-binary)
- [Use it](#use-it)

<!-- /TOC -->


## Examples

```sh
$ http-file-server /tmp
2018/11/13 23:00:03.946051 serving local path "/tmp" on "/tmp/"
2018/11/13 23:00:03.946087 redirecting to "/tmp/" from "/"
2018/11/13 23:00:03.946093 http-file-server listening on ":8080"
```

```sh
$ http-file-server -p 1234 /1=/tmp /2=/var/tmp
2018/11/13 23:01:44.502240 serving local path "/tmp" on "/1/"
2018/11/13 23:01:44.502274 serving local path "/var/tmp" on "/2/"
2018/11/13 23:01:44.502280 redirecting to "/1/" from "/"
2018/11/13 23:01:44.502285 http-file-server listening on ":1234"
```

```sh
$ export PORT=9999
$ http-file-server /abc/def/ghi=/tmp
2018/11/13 23:05:52.291485 serving local path "/tmp" on "/abc/def/ghi/"
2018/11/13 23:05:52.291606 redirecting to "/abc/def/ghi/" from "/"
2018/11/13 23:05:52.291611 http-file-server listening on ":9999"
```

## Get it

### Using `go get`

```sh
go get -u github.com/sgreben/http-file-server
```

### Pre-built binary

Or [download a binary](https://github.com/sgreben/http-file-server/releases/latest) from the releases page, or from the shell:

```sh
# Linux
curl -L https://github.com/sgreben/http-file-server/releases/download/1.0.0/http-file-server_1.0.0_linux_x86_64.tar.gz | tar xz

# OS X
curl -L https://github.com/sgreben/http-file-server/releases/download/1.0.0/http-file-server_1.0.0_osx_x86_64.tar.gz | tar xz

# Windows
curl -LO https://github.com/sgreben/http-file-server/releases/download/1.0.0/http-file-server_1.0.0_windows_x86_64.zip
unzip versions_1.0.0_windows_x86_64.zip
```

## Use it

```text
http-file-server [OPTIONS] [[ROUTE=]PATH] [[ROUTE=]PATH...]
```

```text
Usage of http-file-server:
-a string
(alias for -addr) (default ":8080")
-addr string
address to listen on (environment variable "ADDR") (default ":8080")
-p int
(alias for -port)
-port int
port to listen on (overrides -addr port) (environment variable "PORT")
-q (alias for -quiet)
-quiet
disable all log output (environment variable "QUIET")
-r value
(alias for -route)
-route value
a route definition ROUTE=PATH (ROUTE defaults to basename of PATH if omitted)
```
78 changes: 78 additions & 0 deletions README.template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# http-file-server

`http-file-server` is a dependency-free HTTP file server.

![screenshot](doc/screenshot.gif)

## Contents

<!-- TOC -->

- [Contents](#contents)
- [Examples](#examples)
- [Get it](#get-it)
- [Using `go get`](#using-go-get)
- [Pre-built binary](#pre-built-binary)
- [Use it](#use-it)

<!-- /TOC -->


## Examples

```sh
$ http-file-server /tmp
2018/11/13 23:00:03.946051 serving local path "/tmp" on "/tmp/"
2018/11/13 23:00:03.946087 redirecting to "/tmp/" from "/"
2018/11/13 23:00:03.946093 http-file-server listening on ":8080"
```

```sh
$ http-file-server -p 1234 /1=/tmp /2=/var/tmp
2018/11/13 23:01:44.502240 serving local path "/tmp" on "/1/"
2018/11/13 23:01:44.502274 serving local path "/var/tmp" on "/2/"
2018/11/13 23:01:44.502280 redirecting to "/1/" from "/"
2018/11/13 23:01:44.502285 http-file-server listening on ":1234"
```

```sh
$ export PORT=9999
$ http-file-server /abc/def/ghi=/tmp
2018/11/13 23:05:52.291485 serving local path "/tmp" on "/abc/def/ghi/"
2018/11/13 23:05:52.291606 redirecting to "/abc/def/ghi/" from "/"
2018/11/13 23:05:52.291611 http-file-server listening on ":9999"
```

## Get it

### Using `go get`

```sh
go get -u github.com/sgreben/http-file-server
```

### Pre-built binary

Or [download a binary](https://github.com/sgreben/http-file-server/releases/latest) from the releases page, or from the shell:

```sh
# Linux
curl -L https://github.com/sgreben/${APP}/releases/download/${VERSION}/${APP}_${VERSION}_linux_x86_64.tar.gz | tar xz

# OS X
curl -L https://github.com/sgreben/${APP}/releases/download/${VERSION}/${APP}_${VERSION}_osx_x86_64.tar.gz | tar xz

# Windows
curl -LO https://github.com/sgreben/${APP}/releases/download/${VERSION}/${APP}_${VERSION}_windows_x86_64.zip
unzip versions_${VERSION}_windows_x86_64.zip
```

## Use it

```text
http-file-server [OPTIONS] [[ROUTE=]PATH] [[ROUTE=]PATH...]
```

```text
${USAGE}
```
Binary file added doc/screenshot.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
130 changes: 130 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package main

import (
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"path/filepath"
"strconv"
)

const (
defaultAddr = ":8080"
addrEnvVarName = "ADDR"
portEnvVarName = "PORT"
quietEnvVarName = "QUIET"
rootRoute = "/"
)

var (
addrFlag = os.Getenv(addrEnvVarName)
portFlag64, _ = strconv.ParseInt(os.Getenv(portEnvVarName), 10, 64)
portFlag = int(portFlag64)
quietFlag bool
routesFlag routes
)

func init() {
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.Var(&routesFlag, "route", routesFlag.help())
flag.Var(&routesFlag, "r", "(alias for -route)")
flag.Parse()
if quietFlag {
log.SetOutput(ioutil.Discard)
}
for i := 0; i < flag.NArg(); i++ {
arg := flag.Arg(i)
err := routesFlag.Set(arg)
if err != nil {
log.Fatalf("%q: %v", arg, err)
}
}
}

func main() {
addr, err := addr()
if err != nil {
log.Fatalf("address/port: %v", err)
}
err = server(addr, routesFlag)
if err != nil {
log.Fatalf("start server: %v", err)
}
}

func server(addr string, routes routes) error {
mux := http.DefaultServeMux
handlers := make(map[string]http.Handler)
paths := make(map[string]string)

if len(routes.Values) == 0 {
log.Printf("WARNING: no routes specified - every request will return %d (%s)", http.StatusNotFound, http.StatusText(http.StatusNotFound))
http.HandleFunc(rootRoute, http.NotFound)
}

for _, route := range routes.Values {
handlers[route.Route] = &fileHandler{
route: route.Route,
path: route.Path,
}
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)
}

if _, ok := handlers[rootRoute]; !ok && len(routes.Values) > 0 {
route := routes.Values[0].Route
mux.Handle(rootRoute, http.RedirectHandler(route, http.StatusTemporaryRedirect))
log.Printf("redirecting to %q from %q", route, rootRoute)
}

binaryPath, _ := os.Executable()
if binaryPath == "" {
binaryPath = "server"
}
log.Printf("%s listening on %q", filepath.Base(binaryPath), addr)
return http.ListenAndServe(addr, mux)
}

func addr() (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
}
}
Loading

0 comments on commit 94f3f0b

Please sign in to comment.