feat: add DoT
This commit is contained in:
		
							parent
							
								
									9cf8968a82
								
							
						
					
					
						commit
						43281f26fe
					
				
							
								
								
									
										16
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Makefile
									
									
									
									
									
								
							@ -1,3 +1,6 @@
 | 
			
		||||
# Tested under Apple M1.
 | 
			
		||||
# Edit it if you use different platform.
 | 
			
		||||
 | 
			
		||||
PROJECT_NAME := comandy
 | 
			
		||||
BUILD_PATH := build
 | 
			
		||||
GOOS := android
 | 
			
		||||
@ -11,12 +14,12 @@ CGO_ENABLED := 1
 | 
			
		||||
GO_SRC := $(shell find . -name '*.go')
 | 
			
		||||
NDK_TOOLCHAIN := ~/Library/Android/sdk/ndk/$(NDK_VERSION)/toolchains/llvm/prebuilt/$(BUILD_MACHINE)-$(BUILD_ARCH)
 | 
			
		||||
CC := $(NDK_TOOLCHAIN)/bin/aarch64-linux-$(TARGET_SDK)-clang
 | 
			
		||||
TEST_OUTPUT = '$(shell cd $(BUILD_PATH) && ./test)'
 | 
			
		||||
TEST_EXPECTED = '{"code":500,"data":"aW52YWxpZCB1cmwgJyc="}'
 | 
			
		||||
TEST_OUTPUT = '$(shell cd $(BUILD_PATH) && ./test | head -c 12)'
 | 
			
		||||
TEST_EXPECTED = '{"code":200,'
 | 
			
		||||
 | 
			
		||||
all: shared
 | 
			
		||||
 | 
			
		||||
shared: $(GO_SRC) dir
 | 
			
		||||
shared: $(GO_SRC) dir tidy
 | 
			
		||||
	GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=$(CGO_ENABLED) NDK_TOOLCHAIN=$(NDK_TOOLCHAIN) CC=$(CC) go build -buildmode=c-shared -o $(BUILD_PATH)/lib$(PROJECT_NAME).so $(GO_SRC)
 | 
			
		||||
test: dir
 | 
			
		||||
	@GOOS=$(BUILD_MACHINE) CC=cc NDK_TOOLCHAIN="" $(MAKE) -e shared
 | 
			
		||||
@ -27,7 +30,12 @@ runtest: test
 | 
			
		||||
	else \
 | 
			
		||||
		echo "test failed, expected:" $(TEST_EXPECTED) "but got:" $(TEST_OUTPUT); \
 | 
			
		||||
	fi
 | 
			
		||||
tidy:
 | 
			
		||||
	go mod tidy
 | 
			
		||||
dir:
 | 
			
		||||
	@if [ ! -d "$(BUILD_PATH)" ]; then mkdir $(BUILD_PATH); fi
 | 
			
		||||
clean:
 | 
			
		||||
	@if [ -d "$(BUILD_PATH)" ]; then rm -rf $(BUILD_PATH)/lib$(PROJECT_NAME).*; fi
 | 
			
		||||
	@if [ -d "$(BUILD_PATH)" ]; then \
 | 
			
		||||
		rm -rf $(BUILD_PATH)/lib$(PROJECT_NAME).*; \
 | 
			
		||||
		rm -rf $(BUILD_PATH)/test; \
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,11 @@
 | 
			
		||||
#include "libcomandy.h"
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
    char* msg = request("{}");
 | 
			
		||||
    puts(msg);
 | 
			
		||||
    puts(request("{\"method\":\"GET\","
 | 
			
		||||
        "\"url\":\"https://i.pximg.net/img-master/img/2012/04/04/21/24/46/26339586_p0_master1200.jpg\","
 | 
			
		||||
        "\"headers\":{"
 | 
			
		||||
            "\"Referer\":\"https://www.pixiv.net/\","
 | 
			
		||||
            "\"User-Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0\""
 | 
			
		||||
        "}"
 | 
			
		||||
    "}"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										138
									
								
								dns.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								dns.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,138 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/fumiama/terasu"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type dnsstat struct {
 | 
			
		||||
	A string
 | 
			
		||||
	E bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type dnsservers struct {
 | 
			
		||||
	sync.RWMutex
 | 
			
		||||
	m map[string][]*dnsstat
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// hasrecord no lock, use under lock
 | 
			
		||||
func hasrecord(lst []*dnsstat, a string) bool {
 | 
			
		||||
	for _, addr := range lst {
 | 
			
		||||
		if addr.A == a {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ds *dnsservers) add(m map[string][]string) {
 | 
			
		||||
	ds.Lock()
 | 
			
		||||
	defer ds.Unlock()
 | 
			
		||||
	addList := map[string][]*dnsstat{}
 | 
			
		||||
	for host, addrs := range m {
 | 
			
		||||
		for _, addr := range addrs {
 | 
			
		||||
			if !hasrecord(ds.m[host], addr) && !hasrecord(addList[host], addr) {
 | 
			
		||||
				addList[host] = append(addList[host], &dnsstat{addr, true})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for host, addrs := range addList {
 | 
			
		||||
		ds.m[host] = append(ds.m[host], addrs...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ds *dnsservers) dial(ctx context.Context) (tlsConn *tls.Conn, err error) {
 | 
			
		||||
	ds.RLock()
 | 
			
		||||
	defer ds.RUnlock()
 | 
			
		||||
	var conn net.Conn
 | 
			
		||||
	for host, addrs := range ds.m {
 | 
			
		||||
		for _, addr := range addrs {
 | 
			
		||||
			if !addr.E {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			conn, err = net.Dial("tcp", addr.A)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			tlsConn = terasu.Use(tls.Client(conn, &tls.Config{ServerName: host}))
 | 
			
		||||
			err = tlsConn.HandshakeContext(ctx)
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			addr.E = false // no need to acquire write lock
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var dotv6servers = dnsservers{
 | 
			
		||||
	m: map[string][]*dnsstat{
 | 
			
		||||
		"dns.alidns.com": {
 | 
			
		||||
			{"[2400:3200::1]:853", true},
 | 
			
		||||
			{"[2400:3200:baba::1]:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"dot.sb": {
 | 
			
		||||
			{"[2a09::]:853", true},
 | 
			
		||||
			{"[2a11::]:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"dns.google": {
 | 
			
		||||
			{"[2001:4860:4860::8888]:853", true},
 | 
			
		||||
			{"[2001:4860:4860::8844]:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"cloudflare-dns.com": {
 | 
			
		||||
			{"[2606:4700:4700::1111]:853", true},
 | 
			
		||||
			{"[2606:4700:4700::1001]:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"dns.umbrella.com": {
 | 
			
		||||
			{"[2620:0:ccc::2]:853", true},
 | 
			
		||||
			{"[2620:0:ccd::2]:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"dns10.quad9.net": {
 | 
			
		||||
			{"[2620:fe::10]:853", true},
 | 
			
		||||
			{"[2620:fe::fe:10]:853", true},
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var dotv4servers = dnsservers{
 | 
			
		||||
	m: map[string][]*dnsstat{
 | 
			
		||||
		"dns.alidns.com": {
 | 
			
		||||
			{"223.5.5.5:853", true},
 | 
			
		||||
			{"223.6.6.6:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"dot.sb": {
 | 
			
		||||
			{"185.222.222.222:853", true},
 | 
			
		||||
			{"45.11.45.11:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"dns.google": {
 | 
			
		||||
			{"8.8.8.8:853", true},
 | 
			
		||||
			{"8.8.4.4:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"cloudflare-dns.com": {
 | 
			
		||||
			{"1.1.1.1:853", true},
 | 
			
		||||
			{"1.0.0.1:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"dns.umbrella.com": {
 | 
			
		||||
			{"208.67.222.222:853", true},
 | 
			
		||||
			{"208.67.220.220:853", true},
 | 
			
		||||
		},
 | 
			
		||||
		"dns10.quad9.net": {
 | 
			
		||||
			{"9.9.9.10:853", true},
 | 
			
		||||
			{"149.112.112.10:853", true},
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var resolver = &net.Resolver{
 | 
			
		||||
	PreferGo: true,
 | 
			
		||||
	Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
 | 
			
		||||
		if canUseIPv6.Get() {
 | 
			
		||||
			return dotv6servers.dial(ctx)
 | 
			
		||||
		}
 | 
			
		||||
		return dotv4servers.dial(ctx)
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								dns_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								dns_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"net"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/fumiama/terasu"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestResolver(t *testing.T) {
 | 
			
		||||
	t.Log("canUseIPv6:", canUseIPv6.Get())
 | 
			
		||||
	addrs, err := resolver.LookupHost(context.TODO(), "dns.google")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	t.Log(addrs)
 | 
			
		||||
	t.Fail()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDNS(t *testing.T) {
 | 
			
		||||
	if canUseIPv6.Get() {
 | 
			
		||||
		dotv6servers.test(t)
 | 
			
		||||
	}
 | 
			
		||||
	dotv4servers.test(t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ds *dnsservers) test(t *testing.T) {
 | 
			
		||||
	ds.RLock()
 | 
			
		||||
	defer ds.RUnlock()
 | 
			
		||||
	for host, addrs := range ds.m {
 | 
			
		||||
		for _, addr := range addrs {
 | 
			
		||||
			if !addr.E {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			conn, err := net.Dial("tcp", addr.A)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			tlsConn := terasu.Use(tls.Client(conn, &tls.Config{ServerName: host}))
 | 
			
		||||
			err = tlsConn.Handshake()
 | 
			
		||||
			_ = tlsConn.Close()
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				t.Log("succ:", host, addr.A)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			t.Fatal("fail:", host, addr.A)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								go.mod
									
									
									
									
									
								
							@ -2,4 +2,7 @@ module comandy
 | 
			
		||||
 | 
			
		||||
go 1.22.1
 | 
			
		||||
 | 
			
		||||
require github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905
 | 
			
		||||
require (
 | 
			
		||||
	github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
 | 
			
		||||
	github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@ -1,2 +1,4 @@
 | 
			
		||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA=
 | 
			
		||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
 | 
			
		||||
github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905 h1:PHf84+ujLpFGJbfytrwZT6/D7KojmjFm5Itv6te6WUA=
 | 
			
		||||
github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905/go.mod h1:BFl0X1+rGJf8bLHl/kO+v05ryHrj/R4kyCrK89NvegA=
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								http.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								http.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/fumiama/terasu"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								ipv6.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								ipv6.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/RomiChan/syncx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var canUseIPv6 = syncx.Lazy[bool]{Init: func() bool {
 | 
			
		||||
	resp, err := http.Get("http://v6.ipv6-test.com/json/widgetdata.php?callback=?")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	_ = resp.Body.Close()
 | 
			
		||||
	return true
 | 
			
		||||
}}
 | 
			
		||||
							
								
								
									
										87
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								main.go
									
									
									
									
									
								
							@ -3,69 +3,46 @@ 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()
 | 
			
		||||
// para: json of map[host string][]addr:port string
 | 
			
		||||
//
 | 
			
		||||
//export add_dns
 | 
			
		||||
func add_dns(para *C.char, is_ipv6 C.int) *C.char {
 | 
			
		||||
	m := map[string][]string{}
 | 
			
		||||
	err := json.Unmarshal(stringToBytes(C.GoString(para)), &m)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return C.CString(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	if is_ipv6 != 0 {
 | 
			
		||||
		if !canUseIPv6.Get() {
 | 
			
		||||
			return C.CString("cannot use ipv6")
 | 
			
		||||
		}
 | 
			
		||||
		dotv6servers.add(m)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	dotv4servers.add(m)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// para:
 | 
			
		||||
//
 | 
			
		||||
//	request("{\"method\":\"GET\","
 | 
			
		||||
//		"\"url\":\"https://i.pximg.net/img-master/img/2012/04/04/21/24/46/26339586_p0_master1200.jpg\","
 | 
			
		||||
//		"\"headers\":{"
 | 
			
		||||
//			"\"Referer\":\"https://www.pixiv.net/\","
 | 
			
		||||
//			"\"User-Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0\""
 | 
			
		||||
//		"}"
 | 
			
		||||
//	"}");
 | 
			
		||||
//
 | 
			
		||||
//export request
 | 
			
		||||
func request(para *C.char) *C.char {
 | 
			
		||||
	r := capsule{}
 | 
			
		||||
@ -73,13 +50,17 @@ func request(para *C.char) *C.char {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return C.CString(r.printerr(err))
 | 
			
		||||
	}
 | 
			
		||||
	if r.U == "" || !strings.HasPrefix(r.U, "http") {
 | 
			
		||||
	if r.U == "" || !strings.HasPrefix(r.U, "https://") {
 | 
			
		||||
		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))
 | 
			
		||||
	var body io.Reader
 | 
			
		||||
	if len(r.D) > 0 {
 | 
			
		||||
		body = strings.NewReader(r.D)
 | 
			
		||||
	}
 | 
			
		||||
	req, err := http.NewRequest(r.M, r.U, body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return C.CString(r.printerr(err))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user