package shortener import ( "log" "net/http" "git.xdrm.io/go/aicra" "git.xdrm.io/go/aicra/api" "git.xdrm.io/go/tiny-url-ex/service/auth" ) // Service manages the url shortener type Service struct { authService *auth.Service } // New returns a bare service func New(auth *auth.Service) (*Service, error) { log.Printf("[shortener] creating service") log.Printf("[shortener] service created") return &Service{ authService: auth, }, nil } // Wire to the aicra server func (svc *Service) Wire(server *aicra.Server) { log.Printf("[shortener] service wired") server.HandleFunc(http.MethodGet, "/", svc.redirect) server.HandleFunc(http.MethodPost, "/", svc.authService.CheckToken(svc.register)) server.HandleFunc(http.MethodPut, "/", svc.authService.CheckToken(svc.update)) server.HandleFunc(http.MethodDelete, "/", svc.authService.CheckToken(svc.delete)) } // redirect from a tiny url to the long url func (svc *Service) redirect(req api.Request, res *api.Response) { // 1. extract input tinyURL, err := req.Param.GetString("url") if err != nil { res.SetError(api.ErrorInvalidParam(), "url", err.Error()) return } // 2. check in db if exists model := NewModel(tinyURL, "") if model.Search() != nil { res.SetError(api.ErrorNoMatchFound()) return } // 3. redirect res.Status = http.StatusPermanentRedirect res.Headers.Set("Location", model.long) res.SetError(api.ErrorSuccess()) } // register registers a new tiny url to a long one func (svc *Service) register(req api.Request, res *api.Response) { // 1. extract arguments longURL, err := req.Param.GetString("target") if err != nil { res.SetError(api.ErrorInvalidParam(), "target", err.Error()) return } tinyURL, err := req.Param.GetString("url") if err != nil { res.SetError(api.ErrorInvalidParam(), "url", err.Error()) return } // 2. fail if already used model := NewModel(tinyURL, "") if model.Search() == nil { res.SetError(api.ErrorAlreadyExists(), "url") return } // 3. store association model.long = longURL if model.Create() != nil { res.SetError(api.ErrorFailure()) return } log.Printf("[shortener] new %q -> %q", model.tiny, model.long) res.SetError(api.ErrorSuccess()) } // update updates an existing tiny url to a new long one func (svc *Service) update(req api.Request, res *api.Response) { // 1. extract arguments longURL, err := req.Param.GetString("target") if err != nil { res.SetError(api.ErrorInvalidParam(), "target", err.Error()) return } tinyURL, err := req.Param.GetString("url") if err != nil { res.SetError(api.ErrorInvalidParam(), "url", err.Error()) return } // 2. fail if not already existing model := NewModel(tinyURL, "") if model.Search() != nil { res.SetError(api.ErrorNoMatchFound()) return } // 3. update association model.long = longURL if model.Update() != nil { res.SetError(api.ErrorFailure()) return } log.Printf("[shortener] upd %q -> %q", model.tiny, model.long) res.SetError(api.ErrorSuccess()) } // delete removes a new tiny url func (svc *Service) delete(req api.Request, res *api.Response) { // 1. extract arguments tinyURL, err := req.Param.GetString("url") if err != nil { res.SetError(api.ErrorInvalidParam(), "url", err.Error()) return } // 2. fail if not already existing model := NewModel(tinyURL, "") if model.Search() != nil { res.SetError(api.ErrorNoMatchFound()) return } // 3. delete association if model.Delete() != nil { res.SetError(api.ErrorFailure()) return } log.Printf("[shortener] del %q", model.tiny) res.SetError(api.ErrorSuccess()) }