Files
Sillyv2/core/node_request.go
T
2023-07-15 07:15:49 +08:00

228 lines
5.7 KiB
Go

package core
import (
"bytes"
"fmt"
"net"
"net/http"
u "net/url"
"strconv"
"strings"
"time"
C "github.com/Dreamacro/clash/constant"
"github.com/cdle/sillyplus/utils"
"github.com/dop251/goja"
"github.com/goccy/go-json"
)
func fetch(vm *goja.Runtime, uuid string, wts ...interface{}) (interface{}, error) {
var method = "get"
var url = ""
var req *http.Request
var headers map[string]interface{}
var transport *http.Transport
var formData map[string]interface{}
// var isJson bool
var isJsonBody bool
var body []byte
var allow_redirects bool = true
var responseType = ""
// var err error
// var useproxy bool
var timeout time.Duration = 0
var login = false
var instance C.Conn
for _, wt := range wts {
switch wt := wt.(type) {
case string:
url = wt
case map[string]interface{}:
props := wt
for i := range props {
switch strings.ToLower(i) {
case "timeout":
timeout = time.Duration(utils.Int64(props[i])) * time.Millisecond
case "headers":
headers = props[i].(map[string]interface{})
case "method":
method = strings.ToLower(props[i].(string))
case "url":
if f, ok := props[i].(func(i goja.FunctionCall) goja.Value); ok {
url = f(goja.FunctionCall{}).ToString().String()
} else {
if props[i] == nil {
panic(Error(vm, "无效的url请求地址nil"))
}
url = fmt.Sprint(props[i])
}
case "json":
if props[i].(bool) {
responseType = "json"
}
case "responsetype":
responseType = props[i].(string)
case "datatype":
responseType = props[i].(string)
case "allowredirects":
allow_redirects = props[i].(bool)
case "body":
switch v := props[i].(type) {
case string:
body = []byte(v)
case []byte:
body = v
case *Buffer:
body = v.value
default:
d, _ := json.Marshal(props[i])
body = d
isJsonBody = true
}
case "login":
login = true
case "formdata":
formData = props[i].(map[string]interface{})
case "form":
formData = props[i].(map[string]interface{})
case "proxy":
var err error
var params = props[i].(map[string]interface{})
if _, ok := params["name"]; !ok {
params["name"] = "临时"
}
instance, err = GetProxyTransport(url, uuid, params)
if err != nil {
panic(Error(vm, err))
}
if instance != nil {
defer instance.Close()
}
// var url, user, password string
// for k, v := range props[i].(map[string]interface{}) {
// if k == "url" {
// url = fmt.Sprint(v)
// }
// if k == "user" {
// user = fmt.Sprint(v)
// }
// if k == "password" {
// password = fmt.Sprint(v)
// }
// }
// if url != "" {
// var err error
// transport, err = GetTransport(url, user, password)
// if err != nil {
// return nil, err
// }
// }
}
}
}
var err error
if instance == nil {
instance, err = GetProxyTransport(url, uuid, nil)
if err != nil {
panic(Error(vm, err))
}
if instance != nil {
defer instance.Close()
}
}
if instance != nil {
transport = &http.Transport{
Dial: func(string, string) (net.Conn, error) {
return instance, nil
},
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 10 * time.Second,
}
}
method = strings.ToUpper(method)
if len(formData) > 0 {
data := u.Values{}
for key, value := range formData {
switch v := value.(type) {
case string:
data.Set(key, v)
case bool:
data.Set(key, strconv.FormatBool(v))
case int:
data.Set(key, strconv.Itoa(v))
// 可以根据需要添加其他类型的处理
default:
data.Set(key, fmt.Sprintf("%v", v))
}
}
req, err = http.NewRequest(method, url, strings.NewReader(data.Encode()))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
} else {
req, err = http.NewRequest(method, url, bytes.NewBuffer(body))
if err != nil {
return nil, err
}
if isJsonBody {
req.Header.Set("Content-Type", "application/json")
}
}
if login {
req.Header.Set("Cookie", "uuid=40e67d5e-f6f3-11ed-8bc2-dca9049272e5; token="+getTempAuth())
}
for i := range headers {
req.Header.Set(i, fmt.Sprint(headers[i]))
}
}
var rspObj goja.Proxy
var rsp *http.Response
var err error
var client = &http.Client{
Timeout: timeout,
}
if transport != nil {
client.Transport = transport
}
if !allow_redirects {
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
}
rsp, err = client.Do(req)
if err != nil {
return nil, err
}
defer rsp.Body.Close()
obj, err := MakeResponseObject(vm, rsp, responseType)
rspObj = vm.NewProxy(obj, &goja.ProxyTrapConfig{
Get: func(target *goja.Object, property string, receiver goja.Value) (value goja.Value) {
obj := target.Get(property)
if obj != nil {
return obj
}
switch property {
case "statusText", "statusMessage":
return vm.ToValue("")
case "statusCode":
return target.Get("status")
// case "body":
// return vm.ToValue(target.Get("getBody").Export().(func() interface{})())
case "then":
return goja.Undefined()
}
console.Error("response has no property " + property)
return goja.Undefined()
},
})
return rspObj, err
}