├── run.sh ├── .gitignore ├── Makefile ├── README.md └── web.go /run.sh: -------------------------------------------------------------------------------- 1 | LD_LIBRARY_PATH=./leveldb-1.7.0 ./boomerang60 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | slugs.leveldb/ 2 | pkg/ 3 | src/ 4 | boomerang60 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export GOPATH=$(CURDIR) 2 | 3 | all: src/github.com/stretchr/goweb src/github.com/jmhodges/levigo boomerang 4 | 5 | boomerang: web.go 6 | @echo building in $$GOPATH 7 | go build 8 | 9 | src/github.com/stretchr/goweb: 10 | go get github.com/stretchr/goweb 11 | 12 | src/github.com/jmhodges/levigo: 13 | go get github.com/jmhodges/levigo 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A simple URL shortener/redirect. 2 | 3 | To create a new redirect, do an HTTP POST to the slug or short-name that 4 | you'd like to use in the future. Put the destination URL in the body of the POST. 5 | 6 | ``` 7 | POST / 8 | 9 | ``` 10 | 11 | Then use the slug normally, http://my_server/slug will redirect to the associated URL. 12 | 13 | ``` 14 | GET / 15 | ``` 16 | -------------------------------------------------------------------------------- /web.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "bufio" 6 | "net/http" 7 | "github.com/stretchr/goweb" 8 | "github.com/stretchr/goweb/context" 9 | "github.com/jmhodges/levigo" 10 | ) 11 | 12 | func main() { 13 | 14 | opts := levigo.NewOptions() 15 | opts.SetCreateIfMissing(true) 16 | ro := levigo.NewReadOptions() 17 | wo := levigo.NewWriteOptions() 18 | 19 | db, err := levigo.Open("slugs.leveldb", opts) 20 | if err != nil { fmt.Printf("db %v\n", err) } 21 | 22 | goweb.Map("GET", "/{slug}", func(c context.Context) error { 23 | key := c.PathValue("slug") 24 | fmt.Printf("GET %s\n", key) 25 | data, err := db.Get(ro, []byte(key)) 26 | if err == nil { 27 | responseCode := 0 28 | responseBytes := []byte("") 29 | if data == nil { 30 | responseBytes = []byte("Not found") 31 | responseCode = 404 32 | } else { 33 | c.HttpResponseWriter().Header().Set("Location", string(data)) 34 | responseBytes = data 35 | responseCode = 307 36 | } 37 | return goweb.Respond.With(c, responseCode, responseBytes) 38 | } else { 39 | return goweb.Respond.With(c, http.StatusInternalServerError, nil) 40 | } 41 | }) 42 | 43 | goweb.Map("POST", "/{slug}", func(c context.Context) error { 44 | key := c.PathValue("slug") 45 | 46 | bodyio := bufio.NewReader(c.HttpRequest().Body) 47 | body, err := bodyio.ReadString('\n') 48 | if err == nil { 49 | fmt.Printf("POST %s %s\n", key, body) 50 | err = db.Put(wo, []byte(key), []byte(body)) 51 | fmt.Printf("POST2 %s %s\n", key, body) 52 | if err == nil { 53 | fmt.Printf("POST db good\n") 54 | return goweb.Respond.With(c, 200, nil) 55 | } else { 56 | fmt.Printf("POST db %s %v\n", key, err) 57 | return goweb.Respond.With(c, http.StatusInternalServerError, nil) 58 | } 59 | } else { 60 | fmt.Printf("POST body err %v\n", key, err) 61 | return goweb.Respond.With(c, http.StatusInternalServerError, nil) 62 | } 63 | }) 64 | 65 | addr := ":8080" 66 | fmt.Printf("ready %s\n", addr) 67 | s := &http.Server{Addr: addr, Handler: goweb.DefaultHttpHandler()} 68 | s.ListenAndServe() 69 | fmt.Println("bye bye") 70 | } 71 | --------------------------------------------------------------------------------