[server/handlers] Implement short url creation
This commit is contained in:
parent
fb59b69703
commit
37d93881e8
4 changed files with 68 additions and 1 deletions
|
@ -1,8 +1,10 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"../utils"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
@ -50,3 +52,36 @@ func (a *App) GetURL(w http.ResponseWriter, r *http.Request) {
|
|||
fmt.Fprintf(w, "No such link")
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) CreateShortURL(w http.ResponseWriter, r *http.Request) {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
log.Fatal("Could not parse JSON")
|
||||
}
|
||||
reqURL := r.PostFormValue("url")
|
||||
alias := r.PostFormValue("alias")
|
||||
// Verify URL is valid
|
||||
if !utils.IsValidUrl(reqURL) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
fmt.Fprintf(w, "Invalid URL")
|
||||
return
|
||||
}
|
||||
// Check if URL entry already exists
|
||||
var urlEntry URLEntry
|
||||
a.DB.Where("url = ?", reqURL).Find(&urlEntry)
|
||||
if urlEntry.URL != "" {
|
||||
alias = urlEntry.Alias
|
||||
} else {
|
||||
// Check if alias is already taken
|
||||
for alias == "" || !a.DB.Where("alias = ?", alias).First(&urlEntry).RecordNotFound() {
|
||||
alias = utils.RandString(6)
|
||||
}
|
||||
newURLEntry := &URLEntry{URL: reqURL, Alias: alias}
|
||||
a.DB.Create(newURLEntry)
|
||||
}
|
||||
|
||||
// Write HTTP Response
|
||||
shortlink := r.Host + "/s/" + alias
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Header().Set("Location", shortlink)
|
||||
fmt.Fprintf(w, shortlink)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ func main() {
|
|||
|
||||
r := mux.NewRouter()
|
||||
r.Handle("/", http.FileServer(http.Dir("./static"))).Methods("GET")
|
||||
r.HandleFunc("/", a.CreateShortURL).Methods("POST")
|
||||
r.HandleFunc("/all", a.ListAll).Methods("GET")
|
||||
r.HandleFunc("/s/{alias:.*}", a.GetURL).Methods("GET")
|
||||
http.Handle("/", r)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<body>
|
||||
<form method="POST" action="/">
|
||||
<input name="url" type="text" placeholder="paste a long url" value="" /></label>
|
||||
<input name="url" type="text" placeholder="paste a long url" value="" required />
|
||||
<br>
|
||||
<input name="alias" type="text" placeholder="custom alias (optional)" value="" />
|
||||
<br>
|
||||
|
|
31
utils/utils.go
Normal file
31
utils/utils.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Charset for random string generator
|
||||
const Charset = "abcdefghijklmnopqrstuvwxyz" +
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
|
||||
// Tests a string to determine if it is a well-structured url or not
|
||||
func IsValidUrl(str string) bool {
|
||||
u, err := url.Parse(str)
|
||||
return err == nil && u.Scheme != "" && u.Host != ""
|
||||
}
|
||||
|
||||
// Generate a random alphanumeric string of given length
|
||||
func RandString(length int) string {
|
||||
return randStringWithCharset(length, Charset)
|
||||
}
|
||||
|
||||
func randStringWithCharset(length int, charset string) string {
|
||||
seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
b := make([]byte, length)
|
||||
for i := range b {
|
||||
b[i] = charset[seededRand.Intn(len(charset))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
Loading…
Reference in a new issue