internal/worker: add delete module handler

A /delete endpoint is added to the worker, which is used to delete a
specified module version.

Change-Id: Id50bd9785e9d08c7d399f0fe8f757131767a0819
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/239742
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/internal/worker/server.go b/internal/worker/server.go
index ee19341..a7effce 100644
--- a/internal/worker/server.go
+++ b/internal/worker/server.go
@@ -155,6 +155,9 @@
 	// manual: clear-cache clears the redis cache.
 	handle("/clear-cache", rmw(s.errorHandler(s.clearCache)))
 
+	// manual: delete the specified module version.
+	handle("/delete/", http.StripPrefix("/delete", rmw(s.errorHandler(s.handleDelete))))
+
 	// returns the Worker homepage.
 	handle("/", http.HandlerFunc(s.handleStatusPage))
 }
@@ -494,6 +497,19 @@
 	return nil
 }
 
+// handleDelete deletes the specified module version.
+func (s *Server) handleDelete(w http.ResponseWriter, r *http.Request) error {
+	modulePath, version, err := parseModulePathAndVersion(r.URL.Path)
+	if err != nil {
+		return &serverError{http.StatusBadRequest, err}
+	}
+	if err := s.db.DeleteModule(r.Context(), modulePath, version); err != nil {
+		return &serverError{http.StatusInternalServerError, err}
+	}
+	fmt.Fprintf(w, "Deleted %s@%s", modulePath, version)
+	return nil
+}
+
 // Parse the template for the status page.
 func parseTemplate(staticPath string) (*template.Template, error) {
 	if staticPath == "" {