Add HTML forms for actions
This commit is contained in:
parent
280c68d77a
commit
4821887b07
21
README.md
21
README.md
|
@ -8,7 +8,7 @@ Configuration can be done with a simple `config.{json|yaml|toml}` file in the wo
|
|||
|
||||
These are the required config values:
|
||||
|
||||
* `password`: Password to create or delete short links
|
||||
* `password`: Password to create, update or delete short links
|
||||
* `shortUrl`: The short base URL (without trailing slash!)
|
||||
* `defaultUrl`: The default URL to which should be redirected when no slug is specified
|
||||
|
||||
|
@ -22,17 +22,18 @@ See the `example-config.yaml` file for an example configuration.
|
|||
|
||||
The preferred authentication method is Basic Authentication. If you try to create, modify or delete a short link, in the browser a popup will appear asking for username and password. Enter just the password you configured. Alternatively you can append a URL query parameter `password` with your configured password.
|
||||
|
||||
## Create a new short link
|
||||
## Usage
|
||||
|
||||
To create a new short link, call "`shortUrl` + `/s?url=` + URL to shorten". If you want, you can append `&slug=` with the preferred slug.
|
||||
You can either create, update or delete short links using a browser by entering the short URL and the path for the method. Or you can make a HTTP `POST` request with the parameters.
|
||||
|
||||
## Update a short link
|
||||
|
||||
To update a short link, call "`shortUrl` + `/d?slug=` + slug to update + `&new=` + new long URL"
|
||||
|
||||
## Delete a short link
|
||||
|
||||
To delete a short link, call "`shortUrl` + `/d?slug=` + slug to delete".
|
||||
- Create a new short link: `/s`
|
||||
- `url`: URL to shorten
|
||||
- (optional) `slug`: the preferred slug
|
||||
- Update a short link: `/u`
|
||||
- `slug`: slug to update
|
||||
- `new`: new long URL
|
||||
- Delete a short link: `/d`
|
||||
- `slug`: slug to delete
|
||||
|
||||
## License
|
||||
|
||||
|
|
87
main.go
87
main.go
|
@ -6,6 +6,7 @@ import (
|
|||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/rubenv/sql-migrate"
|
||||
"github.com/spf13/viper"
|
||||
"html/template"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
|
@ -50,9 +51,12 @@ func main() {
|
|||
}()
|
||||
|
||||
r := mux.NewRouter()
|
||||
r.HandleFunc("/s", ShortenHandler)
|
||||
r.HandleFunc("/u", UpdateHandler)
|
||||
r.HandleFunc("/d", DeleteHandler)
|
||||
r.HandleFunc("/s", ShortenFormHandler).Methods(http.MethodGet)
|
||||
r.HandleFunc("/s", ShortenHandler).Methods(http.MethodPost)
|
||||
r.HandleFunc("/u", UpdateFormHandler).Methods(http.MethodGet)
|
||||
r.HandleFunc("/u", UpdateHandler).Methods(http.MethodPost)
|
||||
r.HandleFunc("/d", DeleteFormHandler).Methods(http.MethodGet)
|
||||
r.HandleFunc("/d", DeleteHandler).Methods(http.MethodPost)
|
||||
r.HandleFunc("/{slug}", ShortenedUrlHandler)
|
||||
r.HandleFunc("/", CatchAllHandler)
|
||||
|
||||
|
@ -76,7 +80,68 @@ func MigrateDatabase() {
|
|||
}
|
||||
}
|
||||
|
||||
func ShortenFormHandler(w http.ResponseWriter, r *http.Request) {
|
||||
_ = r.ParseForm()
|
||||
|
||||
if !checkPassword(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
err := generateForm(w, "Shorten URL", "s", []string{"url", "slug"})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateFormHandler(w http.ResponseWriter, r *http.Request) {
|
||||
_ = r.ParseForm()
|
||||
|
||||
if !checkPassword(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
err := generateForm(w, "Update short link", "u", []string{"slug", "new"})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteFormHandler(w http.ResponseWriter, r *http.Request) {
|
||||
_ = r.ParseForm()
|
||||
|
||||
if !checkPassword(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
err := generateForm(w, "Delete short link", "d", []string{"slug"})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func generateForm(w http.ResponseWriter, title string, url string, fields []string) error {
|
||||
tmpl, err := template.New("Form").Parse("<!doctype html><html lang=en><title>{{.Title}}</title><h1>{{.Title}}</h1><form action={{.Url}} method=post>{{range .Fields}}<input type=text name={{.}} placeholder={{.}} /><br><br>{{end}}<input type=submit value={{.Title}}></form></html>")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tmpl.Execute(w, &struct {
|
||||
Title string
|
||||
Url string
|
||||
Fields []string
|
||||
}{
|
||||
Title: title,
|
||||
Url: url,
|
||||
Fields: fields,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ShortenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
_ = r.ParseForm()
|
||||
|
||||
if !checkPassword(w, r) {
|
||||
return
|
||||
}
|
||||
|
@ -85,13 +150,13 @@ func ShortenHandler(w http.ResponseWriter, r *http.Request) {
|
|||
_, _ = w.Write([]byte(viper.GetString("shortUrl") + "/" + slug))
|
||||
}
|
||||
|
||||
requestUrl := r.URL.Query().Get("url")
|
||||
requestUrl := r.FormValue("url")
|
||||
if requestUrl == "" {
|
||||
http.Error(w, "url parameter not set", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
slug := r.URL.Query().Get("slug")
|
||||
slug := r.FormValue("slug")
|
||||
manualSlug := false
|
||||
if slug == "" {
|
||||
_ = db.QueryRow("SELECT slug FROM redirect WHERE url = ?", requestUrl).Scan(&slug)
|
||||
|
@ -132,17 +197,19 @@ func ShortenHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func UpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
_ = r.ParseForm()
|
||||
|
||||
if !checkPassword(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
slug := r.URL.Query().Get("slug")
|
||||
slug := r.FormValue("slug")
|
||||
if slug == "" {
|
||||
http.Error(w, "Specify the slug to update", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
newUrl := r.URL.Query().Get("new")
|
||||
newUrl := r.FormValue("new")
|
||||
if newUrl == "" {
|
||||
http.Error(w, "Specify the new URL", http.StatusBadRequest)
|
||||
return
|
||||
|
@ -164,11 +231,13 @@ func UpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func DeleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
_ = r.ParseForm()
|
||||
|
||||
if !checkPassword(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
slug := r.URL.Query().Get("slug")
|
||||
slug := r.FormValue("slug")
|
||||
if slug == "" {
|
||||
http.Error(w, "Specify the slug to delete", http.StatusBadRequest)
|
||||
return
|
||||
|
@ -190,7 +259,7 @@ func DeleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func checkPassword(w http.ResponseWriter, r *http.Request) bool {
|
||||
if r.URL.Query().Get("password") == viper.GetString("password") {
|
||||
if r.FormValue("password") == viper.GetString("password") {
|
||||
return true
|
||||
}
|
||||
_, pass, ok := r.BasicAuth()
|
||||
|
|
Loading…
Reference in New Issue