[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
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"../utils"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
@ -50,3 +52,36 @@ func (a *App) GetURL(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintf(w, "No such link")
|
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 := mux.NewRouter()
|
||||||
r.Handle("/", http.FileServer(http.Dir("./static"))).Methods("GET")
|
r.Handle("/", http.FileServer(http.Dir("./static"))).Methods("GET")
|
||||||
|
r.HandleFunc("/", a.CreateShortURL).Methods("POST")
|
||||||
r.HandleFunc("/all", a.ListAll).Methods("GET")
|
r.HandleFunc("/all", a.ListAll).Methods("GET")
|
||||||
r.HandleFunc("/s/{alias:.*}", a.GetURL).Methods("GET")
|
r.HandleFunc("/s/{alias:.*}", a.GetURL).Methods("GET")
|
||||||
http.Handle("/", r)
|
http.Handle("/", r)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<form method="POST" action="/">
|
<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>
|
<br>
|
||||||
<input name="alias" type="text" placeholder="custom alias (optional)" value="" />
|
<input name="alias" type="text" placeholder="custom alias (optional)" value="" />
|
||||||
<br>
|
<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