Skip to content

Instantly share code, notes, and snippets.

@xor-gate
Last active August 29, 2015 14:27
Show Gist options
  • Save xor-gate/d167c15b742987713835 to your computer and use it in GitHub Desktop.
Save xor-gate/d167c15b742987713835 to your computer and use it in GitHub Desktop.
URL shortener
package main
import (
"fmt"
"log"
"math/rand"
"net/http"
"time"
"github.com/garyburd/redigo/redis"
)
func main() {
rand.Seed(time.Now().UnixNano())
db, err := redis.Dial("tcp", ":6379")
if err != nil {
log.Fatalln("Error connecting to redis:", err)
}
http.ListenAndServe(":8080", &handler{db})
}
type handler struct{ redis.Conn }
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
h.redirectShortURL(w, r)
case "POST":
h.createShortURL(w, r)
}
}
func (h *handler) redirectShortURL(w http.ResponseWriter, r *http.Request) {
url, err := h.Do("GET", r.URL.Path[1:])
if err != nil || url == nil {
http.NotFound(w, r)
return
}
http.Redirect(w, r, string(url.([]byte)), 301)
}
func (h *handler) createShortURL(w http.ResponseWriter, r *http.Request) {
url := r.FormValue("url")
if url == "" {
http.Error(w, "URL must be provided", 400)
return
}
code := randCode(7)
_, err := h.Do("SET", code, url)
if err != nil {
http.Error(w, "Something failed internally: "+err.Error(), 500)
return
}
fmt.Fprintf(w, "http://localhost:8080/%s\n", string(code))
}
func randCode(length int) []byte {
src := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
result := make([]byte, length)
for i := range result {
result[i] = src[rand.Intn(len(src))]
}
return result
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment