[WIP] New updater first working prototype
This commit is contained in:
@@ -1,161 +1,161 @@
|
||||
package updates
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
// "bytes"
|
||||
// "io"
|
||||
// "net/http"
|
||||
// "os"
|
||||
// "path/filepath"
|
||||
// "strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
// "github.com/ghodss/yaml"
|
||||
|
||||
"github.com/safing/portmaster/base/api"
|
||||
"github.com/safing/portmaster/base/log"
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
// "github.com/safing/portmaster/base/api"
|
||||
// "github.com/safing/portmaster/base/log"
|
||||
// "github.com/safing/portmaster/base/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
apiPathCheckForUpdates = "updates/check"
|
||||
)
|
||||
|
||||
func registerAPIEndpoints() error {
|
||||
if err := api.RegisterEndpoint(api.Endpoint{
|
||||
Name: "Check for Updates",
|
||||
Description: "Checks if new versions are available. If automatic updates are enabled, they are also downloaded and applied.",
|
||||
Parameters: []api.Parameter{{
|
||||
Method: http.MethodPost,
|
||||
Field: "download",
|
||||
Value: "",
|
||||
Description: "Force downloading and applying of all updates, regardless of auto-update settings.",
|
||||
}},
|
||||
Path: apiPathCheckForUpdates,
|
||||
Write: api.PermitUser,
|
||||
ActionFunc: func(r *api.Request) (msg string, err error) {
|
||||
// Check if we should also download regardless of settings.
|
||||
downloadAll := r.URL.Query().Has("download")
|
||||
// func registerAPIEndpoints() error {
|
||||
// if err := api.RegisterEndpoint(api.Endpoint{
|
||||
// Name: "Check for Updates",
|
||||
// Description: "Checks if new versions are available. If automatic updates are enabled, they are also downloaded and applied.",
|
||||
// Parameters: []api.Parameter{{
|
||||
// Method: http.MethodPost,
|
||||
// Field: "download",
|
||||
// Value: "",
|
||||
// Description: "Force downloading and applying of all updates, regardless of auto-update settings.",
|
||||
// }},
|
||||
// Path: apiPathCheckForUpdates,
|
||||
// Write: api.PermitUser,
|
||||
// ActionFunc: func(r *api.Request) (msg string, err error) {
|
||||
// // Check if we should also download regardless of settings.
|
||||
// downloadAll := r.URL.Query().Has("download")
|
||||
|
||||
// Trigger update task.
|
||||
err = TriggerUpdate(true, downloadAll)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// // Trigger update task.
|
||||
// err = TriggerUpdate(true, downloadAll)
|
||||
// if err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
|
||||
// Report how we triggered.
|
||||
if downloadAll {
|
||||
return "downloading all updates...", nil
|
||||
}
|
||||
return "checking for updates...", nil
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
// // Report how we triggered.
|
||||
// if downloadAll {
|
||||
// return "downloading all updates...", nil
|
||||
// }
|
||||
// return "checking for updates...", nil
|
||||
// },
|
||||
// }); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
if err := api.RegisterEndpoint(api.Endpoint{
|
||||
Name: "Get Resource",
|
||||
Description: "Returns the requested resource from the udpate system",
|
||||
Path: `updates/get/{identifier:[A-Za-z0-9/\.\-_]{1,255}}`,
|
||||
Read: api.PermitUser,
|
||||
ReadMethod: http.MethodGet,
|
||||
HandlerFunc: func(w http.ResponseWriter, r *http.Request) {
|
||||
// Get identifier from URL.
|
||||
var identifier string
|
||||
if ar := api.GetAPIRequest(r); ar != nil {
|
||||
identifier = ar.URLVars["identifier"]
|
||||
}
|
||||
if identifier == "" {
|
||||
http.Error(w, "no resource speicified", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// if err := api.RegisterEndpoint(api.Endpoint{
|
||||
// Name: "Get Resource",
|
||||
// Description: "Returns the requested resource from the udpate system",
|
||||
// Path: `updates/get/{identifier:[A-Za-z0-9/\.\-_]{1,255}}`,
|
||||
// Read: api.PermitUser,
|
||||
// ReadMethod: http.MethodGet,
|
||||
// HandlerFunc: func(w http.ResponseWriter, r *http.Request) {
|
||||
// // Get identifier from URL.
|
||||
// var identifier string
|
||||
// if ar := api.GetAPIRequest(r); ar != nil {
|
||||
// identifier = ar.URLVars["identifier"]
|
||||
// }
|
||||
// if identifier == "" {
|
||||
// http.Error(w, "no resource speicified", http.StatusBadRequest)
|
||||
// return
|
||||
// }
|
||||
|
||||
// Get resource.
|
||||
resource, err := registry.GetFile(identifier)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
// // Get resource.
|
||||
// resource, err := registry.GetFile(identifier)
|
||||
// if err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusNotFound)
|
||||
// return
|
||||
// }
|
||||
|
||||
// Open file for reading.
|
||||
file, err := os.Open(resource.Path())
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer file.Close() //nolint:errcheck,gosec
|
||||
// // Open file for reading.
|
||||
// file, err := os.Open(resource.Path())
|
||||
// if err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// defer file.Close() //nolint:errcheck,gosec
|
||||
|
||||
// Assign file to reader
|
||||
var reader io.Reader = file
|
||||
// // Assign file to reader
|
||||
// var reader io.Reader = file
|
||||
|
||||
// Add version to header.
|
||||
w.Header().Set("Resource-Version", resource.Version())
|
||||
// // Add version to header.
|
||||
// w.Header().Set("Resource-Version", resource.Version())
|
||||
|
||||
// Set Content-Type.
|
||||
contentType, _ := utils.MimeTypeByExtension(filepath.Ext(resource.Path()))
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
// // Set Content-Type.
|
||||
// contentType, _ := utils.MimeTypeByExtension(filepath.Ext(resource.Path()))
|
||||
// w.Header().Set("Content-Type", contentType)
|
||||
|
||||
// Check if the content type may be returned.
|
||||
accept := r.Header.Get("Accept")
|
||||
if accept != "" {
|
||||
mimeTypes := strings.Split(accept, ",")
|
||||
// First, clean mime types.
|
||||
for i, mimeType := range mimeTypes {
|
||||
mimeType = strings.TrimSpace(mimeType)
|
||||
mimeType, _, _ = strings.Cut(mimeType, ";")
|
||||
mimeTypes[i] = mimeType
|
||||
}
|
||||
// Second, check if we may return anything.
|
||||
var acceptsAny bool
|
||||
for _, mimeType := range mimeTypes {
|
||||
switch mimeType {
|
||||
case "*", "*/*":
|
||||
acceptsAny = true
|
||||
}
|
||||
}
|
||||
// Third, check if we can convert.
|
||||
if !acceptsAny {
|
||||
var converted bool
|
||||
sourceType, _, _ := strings.Cut(contentType, ";")
|
||||
findConvertiblePair:
|
||||
for _, mimeType := range mimeTypes {
|
||||
switch {
|
||||
case sourceType == "application/yaml" && mimeType == "application/json":
|
||||
yamlData, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
jsonData, err := yaml.YAMLToJSON(yamlData)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
reader = bytes.NewReader(jsonData)
|
||||
converted = true
|
||||
break findConvertiblePair
|
||||
}
|
||||
}
|
||||
// // Check if the content type may be returned.
|
||||
// accept := r.Header.Get("Accept")
|
||||
// if accept != "" {
|
||||
// mimeTypes := strings.Split(accept, ",")
|
||||
// // First, clean mime types.
|
||||
// for i, mimeType := range mimeTypes {
|
||||
// mimeType = strings.TrimSpace(mimeType)
|
||||
// mimeType, _, _ = strings.Cut(mimeType, ";")
|
||||
// mimeTypes[i] = mimeType
|
||||
// }
|
||||
// // Second, check if we may return anything.
|
||||
// var acceptsAny bool
|
||||
// for _, mimeType := range mimeTypes {
|
||||
// switch mimeType {
|
||||
// case "*", "*/*":
|
||||
// acceptsAny = true
|
||||
// }
|
||||
// }
|
||||
// // Third, check if we can convert.
|
||||
// if !acceptsAny {
|
||||
// var converted bool
|
||||
// sourceType, _, _ := strings.Cut(contentType, ";")
|
||||
// findConvertiblePair:
|
||||
// for _, mimeType := range mimeTypes {
|
||||
// switch {
|
||||
// case sourceType == "application/yaml" && mimeType == "application/json":
|
||||
// yamlData, err := io.ReadAll(reader)
|
||||
// if err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// jsonData, err := yaml.YAMLToJSON(yamlData)
|
||||
// if err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// reader = bytes.NewReader(jsonData)
|
||||
// converted = true
|
||||
// break findConvertiblePair
|
||||
// }
|
||||
// }
|
||||
|
||||
// If we could not convert to acceptable format, return an error.
|
||||
if !converted {
|
||||
http.Error(w, "conversion to requested format not supported", http.StatusNotAcceptable)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// // If we could not convert to acceptable format, return an error.
|
||||
// if !converted {
|
||||
// http.Error(w, "conversion to requested format not supported", http.StatusNotAcceptable)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Write file.
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if r.Method != http.MethodHead {
|
||||
_, err = io.Copy(w, reader)
|
||||
if err != nil {
|
||||
log.Errorf("updates: failed to serve resource file: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
// // Write file.
|
||||
// w.WriteHeader(http.StatusOK)
|
||||
// if r.Method != http.MethodHead {
|
||||
// _, err = io.Copy(w, reader)
|
||||
// if err != nil {
|
||||
// log.Errorf("updates: failed to serve resource file: %s", err)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// }); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
return nil
|
||||
}
|
||||
// return nil
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user