evcc-io/detect/http.go

117 lines
2.1 KiB
Go

package detect
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"
"github.com/andig/evcc/util"
"github.com/andig/evcc/util/jq"
"github.com/itchyny/gojq"
)
func init() {
registry.Add("http", HttpHandlerFactory)
}
type HttpResult struct {
Jq interface{}
}
func HttpHandlerFactory(conf map[string]interface{}) (TaskHandler, error) {
handler := HttpHandler{
Schema: "http",
Port: 80,
Method: "GET",
Codes: []int{200},
Header: map[string]string{
"Content-type": "application/json",
},
Timeout: 3 * timeout,
}
err := util.DecodeOther(conf, &handler)
if !(handler.Schema == "http" && handler.Port == 80 ||
handler.Schema == "https" && handler.Port == 443) {
handler.optionalPort = fmt.Sprintf(":%d", handler.Port)
}
if handler.Jq != "" {
query, err := gojq.Parse(handler.Jq)
if err != nil {
return nil, fmt.Errorf("invalid jq query: %s (%s)", handler.Jq, err)
}
handler.query = query
}
return &handler, err
}
type HttpHandler struct {
query *gojq.Query
Port int
optionalPort string
Schema, Method, Path string
Codes []int
Header map[string]string
Jq string
Timeout time.Duration
}
func (h *HttpHandler) Test(log *util.Logger, ip string) []interface{} {
uri := fmt.Sprintf("%s://%s%s/%s", h.Schema, ip, h.optionalPort, strings.TrimLeft(h.Path, "/"))
req, err := http.NewRequest(strings.ToUpper(h.Method), uri, nil)
if err != nil {
return nil
}
client := http.Client{
Timeout: h.Timeout,
}
resp, err := client.Do(req)
if err != nil {
return nil
}
defer resp.Body.Close()
if len(h.Codes) > 0 {
var status bool
for _, code := range h.Codes {
if resp.StatusCode == code {
status = true
break
}
}
if !status {
return nil
}
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil
}
var res HttpResult
if h.query != nil {
val, err := jq.Query(h.query, body)
res.Jq = val
if val == nil || err != nil {
return nil
}
}
if err == nil {
return []interface{}{res}
}
return nil
}