Files
picoclaw/web/backend/api/update.go
T
sky5454 49e61fa07f feat(updater): robust self-update selection & extraction (nightly default) (#2201)
* feat(updater): add web self-update endpoint and updater package

* feat(selfupgrade): when url empty, using GetTestReleaseAPIURL for test .

* feat(selfupgrade):  only GetTestReleaseAPIURL  .

* feat(upgrade): cli  $0 update work well!

* fix(ci): fix ci err

* fix(test): fix ci test

* fix(ci): fix ci  lint fmt err

* test(updater): add test for updater

* fix(ci): fix ci  lint var copy err

* fix(ci): retry ci

* updater: require checksum verification, prefer API digest, verify SHA256, fix zip extraction, update tests

* fix(lint): lint fixed

* fix(lint): lint fixed2

* updater: stream download and verify sha256; add http client timeout and progress

Avoid double-download by streaming asset into temp file while computing SHA256 and verifying against checksum; replace http.Get with shared httpClient (2m timeout) to prevent hangs; add simple stderr progress display; remove unused helpers.
2026-04-01 23:41:32 +08:00

53 lines
1.4 KiB
Go

package api
import (
"encoding/json"
"net/http"
"github.com/sipeed/picoclaw/pkg/updater"
)
// registerUpdateRoutes registers the self-update endpoint.
func (h *Handler) registerUpdateRoutes(mux *http.ServeMux) {
mux.HandleFunc("/api/update", h.handleUpdate)
}
type updateRequest struct {
URL string `json:"url,omitempty"`
Binary string `json:"binary,omitempty"`
}
type updateResponse struct {
Status string `json:"status"`
Message string `json:"message,omitempty"`
}
func (h *Handler) handleUpdate(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
_ = json.NewEncoder(w).Encode(updateResponse{Status: "error", Message: "method not allowed"})
return
}
dec := json.NewDecoder(http.MaxBytesReader(w, r.Body, 1<<20))
var req updateRequest
if err := dec.Decode(&req); err != nil {
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(updateResponse{Status: "error", Message: "invalid request body"})
return
}
binary := req.Binary
if binary == "" {
binary = "picoclaw-launcher"
}
if err := updater.UpdateSelfFromRelease(req.URL, "", "", binary); err != nil {
w.WriteHeader(http.StatusInternalServerError)
_ = json.NewEncoder(w).Encode(updateResponse{Status: "error", Message: err.Error()})
return
}
_ = json.NewEncoder(w).Encode(updateResponse{Status: "ok", Message: "update applied; restart to use new version"})
}