From 6fba4c80ed803fb806d03ea740c1035725b7f282 Mon Sep 17 00:00:00 2001 From: Jordan Date: Wed, 24 Feb 2021 23:51:33 -0700 Subject: initial commit --- .gitignore | 3 +++ Makefile | 23 +++++++++++++++++++++++ README.md | 24 ++++++++++++++++++++++++ UNLICENSE | 24 ++++++++++++++++++++++++ go.mod | 3 +++ tent.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 UNLICENSE create mode 100644 go.mod create mode 100644 tent.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9773c1d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.swp +*.swo +tent diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..52aeb31 --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +.POSIX: +.SUFFIXES: + +GO = go +RM = rm +GOFLAGS = +PREFIX = /usr/local +BINDIR = $(PREFIX)/bin + +goflags = $(GOFLAGS) + +all: tent + +tent: + $(GO) build $(goflags) + +clean: + $(RM) -f tent + +install: all + mkdir -p $(DESTDIR)$(BINDIR) + cp -f tent $(DESTDIR)$(BINDIR) + diff --git a/README.md b/README.md new file mode 100644 index 0000000..59122d3 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Tent + +Tent is a tiny webserver intended for serving files and directories from +a single path on the filesystem. Kinda like Python's http.server but with better +defaults. + +No non-standard dependencies. Essentially an http.ServeFile() wrapper. + +## Installation + +Tent can be compiled with `make` or `go build`, and installed system-wide by +running `make install` with root-level permissions. + +## Usage + +``` +Usage of ./tent: + -host string + IP address to listen on (default "127.0.0.1") + -port uint + Port to listen on (default random) + -path string + Absolute or relative path to serve (default "./") +``` diff --git a/UNLICENSE b/UNLICENSE new file mode 100644 index 0000000..68a49da --- /dev/null +++ b/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e7d58ec --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module tent + +go 1.14 diff --git a/tent.go b/tent.go new file mode 100644 index 0000000..65d65dd --- /dev/null +++ b/tent.go @@ -0,0 +1,54 @@ +package main + +import ( + "flag" + "fmt" + "log" + "math/rand" + "net" + "net/http" + "os" + "path/filepath" + "strconv" + "strings" + "time" +) + +var path string + +func RequestHandler(w http.ResponseWriter, r *http.Request) { + p := filepath.Join(path, strings.Replace(r.URL.Path, "..", "", -1)) + http.ServeFile(w, r, p) +} + +func main() { + var host string + var port uint64 + + flag.StringVar(&host, "host", "127.0.0.1", "IP address to listen on") + flag.Uint64Var(&port, "port", 0, "Port to listen on (default random)") + flag.StringVar(&path, "path", "./", "Absolute or relative path to serve") + flag.Parse() + + if _, err := os.Stat(path); err != nil { + panic(err) + } + + if port == 0 { + rand.Seed(time.Now().UnixNano()) + for { + port = uint64(rand.Intn(65535-1024) + 1024) + conn, _ := net.DialTimeout("tcp", net.JoinHostPort(host, + strconv.Itoa(int(port))), time.Second) + if conn != nil { + conn.Close() + } else { + break + } + } + } + + http.HandleFunc("/", RequestHandler) + fmt.Printf("Listening on %v port %v (http://%v:%v/)\n", host, port, host, port) + log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), nil)) +} -- cgit v1.2.3-54-g00ecf