diff --git a/db/querier.go b/db/querier.go index f62f346..bc706b7 100644 --- a/db/querier.go +++ b/db/querier.go @@ -17,6 +17,7 @@ type Querier interface { GetUserByName(ctx context.Context, username string) (*User, error) ListUrlByUser(ctx context.Context, userID string) ([]*UserRelateUrl, error) ListUsers(ctx context.Context, arg *ListUsersParams) ([]*User, error) + UpdateStatus(ctx context.Context, arg *UpdateStatusParams) (*UserRelateUrl, error) UpdateUser(ctx context.Context, arg *UpdateUserParams) (*User, error) } diff --git a/db/query/user_relate_url.sql b/db/query/user_relate_url.sql index 1cacb3b..af93cf0 100644 --- a/db/query/user_relate_url.sql +++ b/db/query/user_relate_url.sql @@ -6,6 +6,12 @@ INSERT INTO user_relate_url ( ) RETURNING *; +-- name: UpdateStatus :one +UPDATE user_relate_url +SET status = $2 +WHERE short_url = $1 +RETURNING *; + -- name: ListUrlByUser :many SELECT * FROM user_relate_url diff --git a/db/user_relate_url.sql.go b/db/user_relate_url.sql.go index 933b685..9650d4a 100644 --- a/db/user_relate_url.sql.go +++ b/db/user_relate_url.sql.go @@ -83,3 +83,30 @@ func (q *Queries) ListUrlByUser(ctx context.Context, userID string) ([]*UserRela } return items, nil } + +const updateStatus = `-- name: UpdateStatus :one +UPDATE user_relate_url +SET status = $2 +WHERE short_url = $1 +RETURNING id, user_id, short_url, origin_url, status, expire_at, created_at +` + +type UpdateStatusParams struct { + ShortUrl string `json:"short_url"` + Status int32 `json:"status"` +} + +func (q *Queries) UpdateStatus(ctx context.Context, arg *UpdateStatusParams) (*UserRelateUrl, error) { + row := q.db.QueryRowContext(ctx, updateStatus, arg.ShortUrl, arg.Status) + var i UserRelateUrl + err := row.Scan( + &i.ID, + &i.UserID, + &i.ShortUrl, + &i.OriginUrl, + &i.Status, + &i.ExpireAt, + &i.CreatedAt, + ) + return &i, err +} diff --git a/handler/home.go b/handler/home.go index 277e518..b354354 100644 --- a/handler/home.go +++ b/handler/home.go @@ -15,14 +15,6 @@ func HomeView(templates fs.FS, store db.Store) http.HandlerFunc { if err != nil { renderLayout(w, r, templates, nil, "home.html.tmpl") } - - scheme := "http://" - if r.TLS != nil { - scheme = "https://" - } - for _, item := range result { - item.ShortUrl = scheme + r.Host + "/" + item.ShortUrl - } renderLayout(w, r, templates, result, "home.html.tmpl") } } diff --git a/handler/render.go b/handler/render.go index dc0c437..9cb5b07 100644 --- a/handler/render.go +++ b/handler/render.go @@ -20,6 +20,13 @@ func renderLayout(w http.ResponseWriter, r *http.Request, templates fs.FS, data "currentUser": func() *Authorize { return withUser(r.Context()) }, + "genShortUrl": func(url string) string { + scheme := "http://" + if r.TLS != nil { + scheme = "https://" + } + return scheme + r.Host + "/" + url + }, }) tpl := template.Must(t.Clone()) diff --git a/handler/resp.go b/handler/resp.go new file mode 100644 index 0000000..a470710 --- /dev/null +++ b/handler/resp.go @@ -0,0 +1,35 @@ +package handler + +import ( + "context" + "encoding/json" + "errors" + "log" + "net/http" +) + +type response struct { + Success bool `json:"success"` + Message string `json:"message"` + Data any `json:"data"` +} + +func respond(w http.ResponseWriter, message string, v any, statusCode int) { + rsp := response{ + Success: true, + Message: message, + Data: v, + } + b, err := json.Marshal(rsp) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.WriteHeader(statusCode) + _, err = w.Write(b) + if err != nil && !errors.Is(err, context.Canceled) { + log.Printf("could not write http response: %v\n", err) + } +} diff --git a/handler/short_url.go b/handler/short_url.go index c5363c5..f6b8be7 100644 --- a/handler/short_url.go +++ b/handler/short_url.go @@ -59,6 +59,28 @@ func CreateShortUrl(templates fs.FS, store db.Store) http.HandlerFunc { } } +func DeleteShortUrl(store db.Store) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + shorUrl := vars["shortUrl"] + _, err := store.UpdateStatus(r.Context(), &db.UpdateStatusParams{ + ShortUrl: shorUrl, + Status: -1, + }) + if err != nil { + respond(w, "删除错误", nil, http.StatusOK) + return + } + err = service.DeleteShortUrl(shorUrl) + if err != nil { + respond(w, "删除错误", nil, http.StatusOK) + return + } + + respond(w, "删除成功", nil, http.StatusOK) + } +} + func HandleShortUrlRedirect(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) shorUrl := vars["shortUrl"] diff --git a/main.go b/main.go index 1633905..4133536 100644 --- a/main.go +++ b/main.go @@ -99,13 +99,12 @@ func main() { subRouter := router.PathPrefix("/").Subrouter() subRouter.Use(handler.MyAuthorize) - subRouter.Handle("/", handler.HomeView(templates, store)).Methods(http.MethodGet) - subRouter.Handle("/create-short-url", hds.MethodHandler{ http.MethodGet: http.Handler(handler.CreateShortUrlView(templates)), http.MethodPost: http.Handler(handler.CreateShortUrl(templates, store)), }) + subRouter.Handle("/delete-short-url/{shortUrl}", handler.DeleteShortUrl(store)).Methods(http.MethodPost) router.HandleFunc("/{shortUrl}", handler.HandleShortUrlRedirect).Methods(http.MethodGet) diff --git a/service/redis_service.go b/service/redis_service.go index addc8cf..de9b817 100644 --- a/service/redis_service.go +++ b/service/redis_service.go @@ -52,3 +52,7 @@ func RetrieveInitialUrl(shortUrl string) (string, error) { return result, nil } + +func DeleteShortUrl(shortUrl string) error { + return storeService.redisClient.Set(ctx, shortUrl, "", time.Second).Err() +} diff --git a/web/template/home.html.tmpl b/web/template/home.html.tmpl index 14fbc97..6bb98b2 100644 --- a/web/template/home.html.tmpl +++ b/web/template/home.html.tmpl @@ -13,7 +13,7 @@ {{range .}} {{.OriginUrl}} - {{.ShortUrl}} + {{genShortUrl .ShortUrl}} {{if eq .Status 0}} YES @@ -21,10 +21,15 @@ NO {{end}} - delete + + {{if eq .Status 0}} + + {{end}} + {{end}} + {{ csrfField }} @@ -51,6 +56,28 @@ {{end}} {{define "js"}} {{end}} {{template "footer" .}} \ No newline at end of file