comandy/main.go
源文雨 9cf8968a82 init
2024-04-15 02:39:28 +09:00

131 lines
2.9 KiB
Go

package main
import "C"
import (
"context"
"crypto/tls"
"encoding/base64"
"encoding/json"
"io"
"net"
"net/http"
"reflect"
"strings"
"time"
"github.com/fumiama/terasu"
)
func main() {}
var dialer = net.Dialer{
Timeout: time.Minute,
}
var cli = http.Client{
Transport: &http.Transport{
DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
conn, err := dialer.DialContext(ctx, "tcp", addr)
if err != nil {
return nil, err
}
host, _, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
return terasu.Use(tls.Client(conn, &tls.Config{
ServerName: host,
InsecureSkipVerify: true,
})), nil
},
},
}
type capsule struct {
C int `json:"code,omitempty"`
M string `json:"method,omitempty"`
U string `json:"url,omitempty"`
H map[string]any `json:"headers,omitempty"`
D string `json:"data,omitempty"`
}
func (r *capsule) printerr(err error) string {
buf := strings.Builder{}
r.C = http.StatusInternalServerError
r.D = base64.StdEncoding.EncodeToString(stringToBytes(err.Error()))
_ = json.NewEncoder(&buf).Encode(r)
return buf.String()
}
func (r *capsule) printstrerr(err string) string {
buf := strings.Builder{}
r.C = http.StatusInternalServerError
r.D = base64.StdEncoding.EncodeToString(stringToBytes(err))
_ = json.NewEncoder(&buf).Encode(r)
return buf.String()
}
//export request
func request(para *C.char) *C.char {
r := capsule{}
err := json.Unmarshal(stringToBytes(C.GoString(para)), &r)
if err != nil {
return C.CString(r.printerr(err))
}
if r.U == "" || !strings.HasPrefix(r.U, "http") {
return C.CString(r.printstrerr("invalid url '" + r.U + "'"))
}
if r.M != "GET" && r.M != "POST" && r.M != "DELETE" {
return C.CString(r.printstrerr("invalid method '" + r.U + "'"))
}
req, err := http.NewRequest(r.M, r.U, strings.NewReader(r.D))
if err != nil {
return C.CString(r.printerr(err))
}
for k, vs := range r.H {
lk := strings.ToLower(k)
if strings.HasPrefix(lk, "x-") {
continue
}
switch x := vs.(type) {
case string:
req.Header.Add(k, x)
case []string:
for _, v := range x {
req.Header.Add(k, v)
}
default:
return C.CString(r.printstrerr("unsupported H type " + reflect.ValueOf(x).Type().Name()))
}
}
resp, err := cli.Do(req)
if err != nil {
return C.CString(r.printerr(err))
}
defer resp.Body.Close()
sb := strings.Builder{}
enc := base64.NewEncoder(base64.StdEncoding, &sb)
_, err = io.CopyN(enc, resp.Body, resp.ContentLength)
_ = enc.Close()
if err != nil {
return C.CString(r.printerr(err))
}
r.C = resp.StatusCode
r.H = make(map[string]any, len(resp.Header)*2)
for k, vs := range resp.Header {
if len(vs) == 1 {
r.H[k] = vs[0]
continue
}
r.H[k] = vs
}
r.D = sb.String()
outbuf := strings.Builder{}
err = json.NewEncoder(&outbuf).Encode(&r)
if err != nil {
return C.CString(r.printerr(err))
}
return C.CString(outbuf.String())
}