aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan <me@jordan.im>2021-02-24 23:51:33 -0700
committerJordan <me@jordan.im>2021-02-24 23:51:33 -0700
commit6fba4c80ed803fb806d03ea740c1035725b7f282 (patch)
tree3258ea8b4f7a5f645ba3a4efb088ea5a1b845321
downloadtent-6fba4c80ed803fb806d03ea740c1035725b7f282.tar.gz
tent-6fba4c80ed803fb806d03ea740c1035725b7f282.zip
initial commit
-rw-r--r--.gitignore3
-rw-r--r--Makefile23
-rw-r--r--README.md24
-rw-r--r--UNLICENSE24
-rw-r--r--go.mod3
-rw-r--r--tent.go54
6 files changed, 131 insertions, 0 deletions
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 <http://unlicense.org/>
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))
+}