Files
EdgeCommon/pkg/serverconfigs/http_auth_sub_request_method.go
2021-06-19 21:50:15 +08:00

109 lines
2.3 KiB
Go

// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package serverconfigs
import (
"crypto/tls"
"encoding/json"
"net/http"
"regexp"
"time"
)
var httpAuthSubRequestHTTPClient = &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
// HTTPAuthSubRequestMethod 使用URL认证
type HTTPAuthSubRequestMethod struct {
URL string `json:"url"`
Method string `json:"method"`
// TODO 增加自定义Header、超时、证书等
isFullURL bool
}
func NewHTTPAuthSubRequestMethod() *HTTPAuthSubRequestMethod {
return &HTTPAuthSubRequestMethod{}
}
// Init 初始化
func (this *HTTPAuthSubRequestMethod) Init(params map[string]interface{}) error {
paramsJSON, err := json.Marshal(params)
if err != nil {
return err
}
err = json.Unmarshal(paramsJSON, this)
if err != nil {
return err
}
// 是否是完整的URL
this.isFullURL = false
if regexp.MustCompile(`^(?i)(http|https)://`).MatchString(this.URL) {
this.isFullURL = true
} else {
if len(this.URL) == 0 || this.URL[0] != '/' {
this.URL = "/" + this.URL
}
}
return nil
}
// Filter 过滤
func (this *HTTPAuthSubRequestMethod) Filter(req *http.Request, doSubReq func(subReq *http.Request) (status int, err error), formatter func(string) string) (bool, error) {
var method = this.Method
if len(method) == 0 {
method = req.Method
}
var url = formatter(this.URL)
var scheme = "http"
if req.TLS != nil {
scheme = "https"
}
var host = req.URL.Host
if len(host) == 0 {
host = req.Host
}
if !this.isFullURL {
url = scheme + "://" + host + url
}
newReq, err := http.NewRequest(method, url, nil)
if err != nil {
return false, err
}
for k, v := range req.Header {
if k != "Connection" {
newReq.Header[k] = v
}
}
if !this.isFullURL {
status, err := doSubReq(newReq)
if err != nil {
return false, err
}
return status >= 200 && status < 300, nil
}
// TODO 需要将Header和StatusCode、ResponseBody输出到客户端
newReq.Header.Set("Referer", scheme+"://"+host+req.URL.RequestURI())
resp, err := httpAuthSubRequestHTTPClient.Do(newReq)
if err != nil {
return false, err
}
defer func() {
_ = resp.Body.Close()
}()
return resp.StatusCode >= 200 && resp.StatusCode < 300, nil
}