package api import ( "encoding/json" "io" "net/http" "github.com/annybs/ezdb" "github.com/annybs/go/rest" "github.com/annybs/go/validate" "github.com/annybs/shorty/internal/types" "github.com/rs/zerolog" ) type API struct { DB ezdb.Collection[*types.Redirect] Log zerolog.Logger AllPath string Token string } func (api *API) Delete(w http.ResponseWriter, req *http.Request) { if !rest.IsAuthenticated(req, api.Token) { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte{}) return } if req.URL.Path == api.AllPath { w.WriteHeader(http.StatusBadRequest) return } path := req.URL.Path if exist, _ := api.DB.Has(path); !exist { w.Write([]byte{}) return } if err := api.DB.Delete(path); err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) } else { w.Write([]byte{}) } } func (api *API) Get(w http.ResponseWriter, req *http.Request) { if req.URL.Path == api.AllPath { api.GetAll(w, req) return } path := req.URL.Path redirect, err := api.DB.Get(path) if err != nil { w.WriteHeader(http.StatusNotFound) w.Write([]byte(err.Error())) return } if len(redirect.Destination) == 0 || redirect.StatusCode == 0 { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("invalid redirect")) } w.Header().Set("Location", string(redirect.Destination)) w.WriteHeader(redirect.StatusCode) w.Write([]byte{}) } func (api *API) GetAll(w http.ResponseWriter, req *http.Request) { if !rest.IsAuthenticated(req, api.Token) { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte{}) return } all, err := api.DB.Iter().GetAll() if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } data, err := json.Marshal(all) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } w.Write(data) } func (api *API) Put(w http.ResponseWriter, req *http.Request) { if !rest.IsAuthenticated(req, api.Token) { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte{}) return } if req.URL.Path == api.AllPath { w.WriteHeader(http.StatusBadRequest) return } path := req.URL.Path dest, err := io.ReadAll(req.Body) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } if err := validate.URL(string(dest)); err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } redirect := &types.Redirect{ Destination: string(dest), StatusCode: http.StatusPermanentRedirect, } if err := api.DB.Put(path, redirect); err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) } else { w.Write([]byte{}) } } func (api *API) ServeHTTP(w http.ResponseWriter, req *http.Request) { api.Log.Info().Msgf("%s %s", req.Method, req.URL.Path) switch req.Method { case http.MethodGet: api.Get(w, req) case http.MethodPut: api.Put(w, req) case http.MethodDelete: api.Delete(w, req) default: w.WriteHeader(http.StatusBadRequest) w.Write([]byte("unsupported method")) } }