123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- package web
- import (
- "fmt"
- "net/http"
- "time"
- "code.osinet.fr/fgm/kurz/domain"
- "github.com/gorilla/mux"
- )
- /*
- Template variables:
- - FullyQualifiedAssetsBaseURL http://plusvite-cdn.osinet.eu
- - FullyQualifiedShortURL (short string)
- - FullyQualifiedSiteURL http://plusvite.net/
- - FullyQualifiedTargetURL (target string)
- - RefreshDelay (seconds int)
- - SiteName PlusVite
- */
- type bytes = []byte
- func build403(w http.ResponseWriter, short string) (bytes, error) {
- type Short403Data struct {
- FullyQualifiedAssetsBaseURL string
- FullyQualifiedShortURL string
- FullyQualifiedSiteURL string
- RefreshDelay time.Duration
- SiteName string
- }
- data := Short403Data{}
- tmpl.Execute(w, data)
- return bytes(""), nil
- }
- func build404(w http.ResponseWriter, short string) (bytes, error) {
- type Short404Data struct {
- AssetsVersion int
- FullyQualifiedAssetsBaseURL string
- FullyQualifiedShortURL string
- FullyQualifiedSiteURL string
- FullyQualifiedTargetURL string
- RefreshDelay time.Duration
- SiteName string
- }
- data := Short404Data{}
- err := tmpl.Execute(w, data)
- if err != nil {
- fmt.Println(err)
- }
- return bytes(""), nil
- }
- func build451(w http.ResponseWriter, short string) (bytes, error) {
- return nil, nil
- }
- // handleGetShort handles path /<short>
- func handleGetShort(w http.ResponseWriter, r *http.Request) {
- short, ok := mux.Vars(r)["short"]
- if !ok {
- w.WriteHeader(http.StatusBadRequest)
- return
- }
- target, err := domain.GetTargetURL(short)
- // Happy path.
- if err == nil {
- w.Header().Set("Location", target)
- w.WriteHeader(http.StatusTemporaryRedirect)
- return
- }
- // Very sad path.
- domainErr, ok := err.(domain.Error)
- if !ok {
- // All errors return by the API should be domain-specific errors.
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
- // Normal sad paths.
- // TODO improve UX: build pages instead of just HTTP 4xx.
- var status int
- switch domainErr.Kind {
- case domain.ShortNotFound:
- status = http.StatusNotFound
- if page, err := build404(w, short); err != nil {
- status = http.StatusInternalServerError
- w.WriteHeader(status)
- } else {
- w.WriteHeader(status)
- w.Write(page)
- }
- case domain.TargetBlockedError:
- status = http.StatusForbidden
- if page, err := build403(w, short); err != nil {
- status = http.StatusInternalServerError
- w.WriteHeader(status)
- } else {
- w.WriteHeader(status)
- w.Write(page)
- }
- case domain.TargetCensoredError:
- status = http.StatusUnavailableForLegalReasons
- if page, err := build451(w, short); err != nil {
- status = http.StatusInternalServerError
- w.WriteHeader(status)
- } else {
- w.WriteHeader(status)
- w.Write(page)
- }
- default:
- // TargetInvalid is not supposed to happen in this case, so it is an internal error too.
- status = http.StatusInternalServerError
- w.WriteHeader(status)
- }
- }
|