Files
go2rtc/cmd/api/config.go
Sergey Krashevich b7016e798f Update config.go
2023-01-14 21:27:23 +03:00

113 lines
2.4 KiB
Go

package api
import (
"io"
"io/ioutil"
"net/http"
"os"
"github.com/AlexxIT/go2rtc/cmd/app"
"gopkg.in/yaml.v3"
)
func configHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
data, err := os.ReadFile(app.ConfigPath)
if err != nil {
http.NotFound(w, r)
return
}
if _, err = w.Write(data); err != nil {
log.Warn().Err(err).Caller().Send()
}
case "POST":
data, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// validate config
var tmp struct{}
if err = yaml.Unmarshal(data, &tmp); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err = os.WriteFile(app.ConfigPath, data, 0644); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
case "PATCH":
rawdata, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
data, err := mergeYAML(app.ConfigPath, rawdata)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// validate config
var tmp struct{}
if err = yaml.Unmarshal(data, &tmp); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err = os.WriteFile(app.ConfigPath, data, 0644); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}
func mergeYAML(file1 string, yaml2 []byte) ([]byte, error) {
// Read the contents of the first YAML file
data1, err := ioutil.ReadFile(file1)
if err != nil {
return nil, err
}
// Unmarshal the first YAML file into a map
var config1 map[string]interface{}
err = yaml.Unmarshal(data1, &config1)
if err != nil {
return nil, err
}
// Unmarshal the second YAML document into a map
var config2 map[string]interface{}
err = yaml.Unmarshal(yaml2, &config2)
if err != nil {
return nil, err
}
// Merge the two maps
config1 = merge(config1, config2)
// Marshal the merged map into YAML
return yaml.Marshal(&config1)
}
func merge(a, b map[string]interface{}) map[string]interface{} {
for k, v := range b {
if vv, ok := a[k]; ok {
switch vv := vv.(type) {
case map[string]interface{}:
v := v.(map[string]interface{})
a[k] = merge(vv, v)
case []interface{}:
v := v.([]interface{})
a[k] = v
default:
a[k] = v
}
} else {
a[k] = v
}
}
return a
}