Files
wails_tools/examples/wails3_init_updater/mockupdateserver/server.go
2026-03-12 22:16:34 +01:00

151 lines
3.7 KiB
Go

package mockupdateserver
import (
"archive/zip"
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"net/http"
"runtime"
"github.com/Eriyc/rules_wails/pkg/wails3kit/updates"
)
const BearerToken = "test-token"
func NewHandler() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/manifest.json", manifest)
mux.HandleFunc("/artifacts/updater-example_0.2.0.zip", artifact)
mux.HandleFunc("/artifacts/updater-example_0.2.0.zip.sha256", checksum)
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.Header.Get("Authorization") != "Bearer "+BearerToken {
http.Error(writer, "unauthorized", http.StatusUnauthorized)
return
}
mux.ServeHTTP(writer, request)
})
}
func manifest(writer http.ResponseWriter, request *http.Request) {
_, checksumValue, err := archiveWithChecksum()
if err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
document := map[string]any{
"schemaVersion": 1,
"productID": "com.eriyc.updater-example",
"releases": []any{
map[string]any{
"id": "0.2.0",
"version": "0.2.0",
"channel": "stable",
"publishedAt": "2026-03-01T03:10:56Z",
"notesMarkdown": "Adds a staged resource update and relaunch flow.",
"artifacts": []any{
map[string]any{
"os": runtime.GOOS,
"arch": runtime.GOARCH,
"kind": updates.ArtifactKindBundleArchive,
"format": updates.ArtifactFormatZip,
"url": baseURL(request) + "/artifacts/updater-example_0.2.0.zip",
"sha256": checksumValue,
},
},
},
},
}
writer.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(writer).Encode(document)
}
func artifact(writer http.ResponseWriter, _ *http.Request) {
archive, err := buildArchive()
if err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
writer.Header().Set("Content-Type", "application/zip")
_, _ = writer.Write(archive)
}
func checksum(writer http.ResponseWriter, _ *http.Request) {
_, checksumValue, err := archiveWithChecksum()
if err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
_, _ = writer.Write([]byte(checksumValue + " updater-example_0.2.0.zip"))
}
func buildArchive() ([]byte, error) {
buffer := bytes.NewBuffer(nil)
archive := zip.NewWriter(buffer)
bundleFile, err := archive.Create("bundle.json")
if err != nil {
return nil, err
}
bundle := updates.BundleManifest{
SchemaVersion: 1,
EntryPoint: entryPoint(),
Files: []updates.BundleFile{
{Path: resourcePath(), Mode: "0644"},
},
}
if err := json.NewEncoder(bundleFile).Encode(bundle); err != nil {
return nil, err
}
resourceFile, err := archive.Create(resourcePath())
if err != nil {
return nil, err
}
if _, err := resourceFile.Write([]byte(`{"version":"0.2.0","status":"downloaded"}`)); err != nil {
return nil, err
}
if err := archive.Close(); err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
func archiveWithChecksum() ([]byte, string, error) {
archive, err := buildArchive()
if err != nil {
return nil, "", err
}
sum := sha256.Sum256(archive)
return archive, hex.EncodeToString(sum[:]), nil
}
func entryPoint() string {
if runtime.GOOS == "darwin" {
return "Contents/MacOS/updater-example"
}
if runtime.GOOS == "windows" {
return "updater-example.exe"
}
return "updater-example"
}
func resourcePath() string {
if runtime.GOOS == "darwin" {
return "Contents/Resources/update.json"
}
return "resources/update.json"
}
func baseURL(request *http.Request) string {
scheme := "http"
if request.TLS != nil {
scheme = "https"
}
return scheme + "://" + request.Host
}