CycleTLS
如果您有API更改或功能请求,请随时开启一个问题
🚀 特性
目录
依赖
node ^v16.0
golang ^v1.21x
安装
Node Js
$ npm install cycletls
Golang
$ go get github.com/Danny-Dasilva/CycleTLS/cycletls
用法
TypeScript和JavaScript的CycleTLS请求示例
您可以在tests/simple.test.ts
中运行此测试
const initCycleTLS = require('cycletls');
// TypeScript: import initCycleTLS from 'cycletls';
(async () => {
// 初始化CycleTLS
const cycleTLS = await initCycleTLS();
// 发送请求
const response = await cycleTLS('https://ja3er.com/json', {
body: '',
ja3: '771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0',
userAgent: 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0',
proxy: 'http://username:password@hostname.com:443',
}, 'get');
console.log(response);
// 清理退出CycleTLS
cycleTLS.exit();
})();
Golang的CycleTLS请求示例
package main
import (
"log"
"github.com/Danny-Dasilva/CycleTLS/cycletls"
)
func main() {
client := cycletls.Init()
response, err := client.Do("https://ja3er.com/json", cycletls.Options{
Body : "",
Ja3: "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0",
UserAgent: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0",
}, "GET");
if err != nil {
log.Print("请求失败: " + err.Error())
}
log.Println(response)
}
使用自定义http.Client的示例
import (
"github.com/Danny-Dasilva/CycleTLS/cycletls"
http "github.com/Danny-Dasilva/fhttp" // 注意这是net/http的替代品
)
func main() {
ja3 := "771,52393-52392-52244-52243-49195-49199-49196-49200-49171-49172-156-157-47-53-10,65281-0-23-35-13-5-18-16-30032-11-10,29-23-24,0"
ua := "Chrome Version 57.0.2987.110 (64-bit) Linux"
cycleClient := &http.Client{
Transport: cycletls.NewTransport(ja3, ua),
}
resp, err := cycleClient.Get("https://tls.peet.ws/")
...
}
创建实例
要创建cycleTLS
实例,您可以运行以下代码:
JavaScript
// initCycleTLS函数会生成一个Golang进程,通过goroutine循环并发处理所有请求。
const initCycleTLS = require('cycletls');
// import initCycleTLS from 'cycletls';
// 异步/等待方法
const cycleTLS = await initCycleTLS();
// .then方法
initCycleTLS().then((cycleTLS) => {});
Golang
import (
"github.com/Danny-Dasilva/CycleTLS/cycletls"
)
//`Init`函数初始化golang通道以处理请求。
client := cycletls.Init()
CycleTLS 别名方法
CycleTLS 中存在以下方法:
cycleTLS(url, [config])
cycleTLS.get(url, [config])
cycleTLS.delete(url, [config])
cycleTLS.head(url, [config])
cycleTLS.options(url, [config])
cycleTLS.post(url, [config])
cycleTLS.put(url, config)
cycleTLS.patch(url, [config])
url 是必需的,config 是可选的
CycleTLS 请求配置
{
// 请求的 URL(如果未作为参数指定,则为必需)
url: "https://example.com"
// 请求的方法("head" | "get" | "post" | "put" | "delete" | "trace" | "options" | "connect" | "patch")
method: "get" // 默认方法
// 要发送的自定义头部
headers: { "Authorization": "Bearer someexampletoken" }
// 要发送的自定义 Cookie
Cookies: [{
"name": "key",
"value": "val",
"path": "/docs",
"domain": "google.com",
"expires": "Mon, 02-Jan-2022 15:04:05 EST"
"maxAge": 90,
"secure": false,
"httpOnly": true,
"sameSite": "Lax"
}],
// 要随请求发送的正文(必须是字符串 - 不能传递对象)
body: '',
// 要随请求发送的 JA3 令牌
ja3: '771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0',
// 请求的用户代理
userAgent: 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0',
// 发送请求时使用的代理(必须是相同的格式)
proxy: 'http://username:password@hostname.com:443',
// 请求超时前的秒数(默认:7)
timeout: 2,
// 切换 CycleTLS 是否应该跟随重定向
disableRedirect: true,
// 要随请求发送的自定义头部顺序(此值将覆盖默认头部顺序)
headerOrder: ["cache-control", "connection", "host"],
// 切换 CycleTLS 是否应该跳过证书验证(如果 InsecureSkipVerify 为 true,TLS 接受服务器提供的任何证书和该证书中的任何主机名)
insecureSkipVerify: false
// 强制 CycleTLS 执行 HTTP1 握手
forceHTTP1: false
}
CycleTLS 响应模式
{
// 服务器返回的状态码(数字)
status: 200,
// 服务器返回的正文(字符串)
body: "",
// 服务器返回的头部(对象)
headers: {
"some": "header",
...
},
// 服务器返回的最终 URL(字符串)。当重定向激活时,此字段很有用。
finalUrl: "https://final.url/"
}
TypeScript 和 JavaScript 的多个请求示例
如果 CycleTLS 在 JavaScript 环境中使用,CycleTLS 将生成一个 Golang 进程来处理请求。这个 Golang 进程在工作池中并发处理请求。因此,CycleTLS 在响应对象可用时立即返回它们(换句话说,CycleTLS 按接收顺序处理请求,但响应异步返回,所以它们不会按请求顺序返回)
如果你在 JavaScript 中使用 CycleTLS,有必要退出实例以防止僵尸进程。下面的示例展示了一种在需要处理多个请求时清理退出 CycleTLS 的方法(注意:请记住,调用 exit()
函数将终止所有正在进行的请求)。如果你的工作流程需要在整个进程运行期间保持请求运行,像 exit-hook 这样的模块可以作为清理退出 CycleTLS 的替代解决方案。
const initCycleTLS = require("cycletls");
// TypeScript: import initCycleTLS from 'cycletls';
// 在多个请求上定义自定义 JA3 令牌和用户代理
const ja3 = "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0";
const userAgent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0";
// 请求字典
const requestDict = {
"https://httpbin.org/get": {},
"https://httpbin.org/user-agent": {
ja3: ja3,
userAgent: userAgent,
},
"http://httpbin.org/post": {
body: '{"field":"POST-VAL"}',
method: "POST",
},
"http://httpbin.org/cookies": {
cookies: [
{
name: "example1",
value: "aaaaaaa",
expires: "Mon, 02-Jan-2022 15:04:05 EST",
},
],
},
};
// 请求的 Promise 数组
const promises = [];
// 匿名异步函数
(async () => {
// 初始化 CycleTLS
const cycleTLS = await initCycleTLS();
// 遍历上面定义的 requestDict(对象)
for (const url in requestDict) {
// 从 requestDict(对象)获取配置
const params = requestDict[url];
// 发送请求(注意:不等待)
const response = cycleTLS(
url, {
body: params.body ?? "", // ?? 在这里只是设置默认值
ja3: params.ja3 ?? ja3,
userAgent: params.userAgent ?? userAgent,
headers: params.headers,
cookies: params.cookies,
}, params.method ?? "GET");
// 打印响应对象
response.then((out) => {
console.log(url, out);
});
// 将请求推送到 Promise 数组
promises.push(response);
}
// 等待所有请求成功执行
Promise.all(promises).then(() => {
// 在收到所有请求后清理退出 CycleTLS
cycleTLS.exit();
});
})();
Golang 的多个请求示例
对于 golang 包,通常期望用户实现工作池或任何其他形式的 goroutine/异步处理。这个包包含一个内置的 Queue 方法,它利用工作池/通道来处理针对一组 URL 的长时间运行的异步请求。
package main
import (
"log"
cycletls "github.com/Danny-Dasilva/CycleTLS/cycletls"
)
// 静态变量
var (
ja3 = "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0"
userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36"
)
// RequestConfig 保存每个请求的配置。
type RequestConfig struct {
URL string
Method string
Options cycletls.Options
}
func main() {
client := cycletls.Init(true) // 初始化工作池
// 定义请求
requests := []RequestConfig{
{
URL: "http://httpbin.org/delay/4",
Method: "GET",
Options: cycletls.Options{
Ja3: ja3,
UserAgent: userAgent,
},
},
{
URL: "http://httpbin.org/post",
Method: "POST",
Options: cycletls.Options{
Body: {"field":"POST-VAL"}
,
Ja3: ja3,
UserAgent: userAgent,
},
},
{
URL: "http://httpbin.org/cookies",
Method: "GET",
Options: cycletls.Options{
Ja3: ja3,
UserAgent: userAgent,
Cookies: []cycletls.Cookie{
{
Name: "example1",
Value: "aaaaaaa",
},
},
},
},
}
// 将请求加入队列
for _, req := range requests {
client.Queue(req.URL, req.Options, req.Method)
}
// 异步读取响应,一旦可用就立即返回
// 它们会在处理完成后立即返回
// 例如,延迟3秒的请求将最后返回
for i := 0; i < len(requests); i++ {
response := <-client.RespChan
log.Println("响应:", response)
}
// 关闭客户端
client.Close()
}
# 开发设置
如果您想自己编译CycleTLS,请使用以下命令:
设置模块感知模式
`go env -w GO111MODULE=off`
安装Golang依赖
`go get github.com/Danny-Dasilva/CycleTLS/cycletls`
安装npm包(此命令会处理上述步骤)
`npm install`
### 重新编译src文件夹中的index.ts
`npm run build`
### 重新编译golang文件夹中的Golang文件
全部
`npm run build:go`
Windows
`npm run build:go:windows:amd64`
Linux
`npm run build:go:linux:amd64`
Mac
`npm run build:go:mac:arm64`
您可以在`package.json`中查看可用的编译选项
## 问题
### 如何设置Cookies
<details>
有两种简单的方法来操作cookies
### JavaScript简单Cookie配置
```js
const initCycleTLS = require("cycletls");
(async () => {
// 初始化cycleTLS
const cycleTLS = await initCycleTLS();
const response = await cycleTLS("https://httpbin.org/cookies", {
cookies: {
cookie1: "value1",
cookie2: "value2",
},
});
console.log(response.body);
/* 预期输出
{
"cookies": {
"cookie1": "value1",
"cookie2": "value2"
}
}
*/
cycleTLS.exit();
})();
在这个简单的例子中,您可以在一个对象中设置cookie的name
和value
JavaScript复杂Cookie配置
如果您希望对cookie参数有更精细的控制,您可以访问完整的底层Go结构
以下是您可以设置的值:
export interface Cookie {
name: string;
value: string;
path?: string;
domain?: string;
expires?: string;
rawExpires?: string;
maxAge?: number;
secure?: boolean;
httpOnly?: boolean;
sameSite?: string;
unparsed?: string;
}
您可以在请求中如下使用它们:
const initCycleTLS = require("cycletls");
(async () => {
// 初始化cycleTLS
const cycleTLS = await initCycleTLS();
const complexCookies = [
{
name: "cookie1",
value: "value1",
domain: "httpbin.org",
},
{
name: "cookie2",
value: "value2",
domain: "httpbin.org",
},
];
const response = await cycleTLS("https://httpbin.org/cookies", {
cookies: complexCookies,
});
console.log(response.body);
/* 预期输出
{
"cookies": {
"cookie1": "value1",
"cookie2": "value2"
}
}
*/
cycleTLS.exit();
})();
Golang配置Cookies
package main
import (
"github.com/Danny-Dasilva/CycleTLS/cycletls"
)
func main() {
resp, err := client.Do("https://httpbin.org/cookies", cycletls.Options{
Body: "",
Ja3: "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0",
UserAgent: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0",
Cookies: []cycletls.Cookie{{Name: "cookie1", Value: "value1"},
{Name: "cookie2", Value: "value2"}},
}, "GET")
if err != nil {
log.Print("请求失败: " + err.Error())
}
log.Println(resp.Body)
/* 预期输出
{
"cookies": {
"cookie1": "value1",
"cookie2": "value2"
}
}
*/
//或者,如果您想访问映射中的值
log.Println(resp.JSONBody())
/* 预期输出
map[cookies:map[cookie1:value1 cookie2:value2]]
*/
}
如果您需要特定文件类型支持的功能请求,请随时在Issue中提出。
如何在CycleTLS中使用CookieJar?
JS中的CookieJar
const initCycleTLS = require("cycletls");
const tough = require("tough-cookie");
const Cookie = tough.Cookie;
(async () => {
// 初始化cycleTLS和CookieJar
const cycleTLS = await initCycleTLS();
const cookieJar = new tough.CookieJar();
// 捕获设置的cookie
const firstResponse = await cycleTLS.get(
"https://httpbin.org/cookies/set?freeform=test",
{
disableRedirect: true,
}
);
// 现在使用processCookies函数将响应头中的cookies添加到cookie jar中
await processCookies(
firstResponse,
"https://httpbin.org/cookies/set?freeform=test",
cookieJar
);
// 现在发送第二个请求以验证我们是否有cookies
const secondResponse = await cycleTLS.get("https://httpbin.org/cookies", {
headers: {
cookie: await cookieJar.getCookieString("https://httpbin.org/cookies"),
},
});
//验证cookies是否已设置
console.log(secondResponse.body)
/* 预期输出
{
"cookies": {
"freeform": "test"
}
}
*/
cycleTLS.exit();
})();
异步函数 processCookies(response, url, cookieJar) {
如果 response.headers["Set-Cookie"] 是一个数组 {
response.headers["Set-Cookie"].map(
异步 (cookieString) => 等待 cookieJar.setCookie(cookieString, url)
);
} 否则 {
等待 cookieJar.setCookie(response.headers["Set-Cookie"], url);
}
}
### Golang中的CookieJar
```go
package main
import (
"github.com/Danny-Dasilva/CycleTLS/cycletls"
"log"
"net/http/cookiejar"
"net/url"
"strings"
)
func main() {
client := cycletls.Init()
jar, err := cookiejar.New(nil)
if err != nil {
log.Fatal(err)
}
// 第一个请求设置cookie
firstResponse, err := client.Do("https://httpbin.org/cookies/set?a=1&b=2&c=3", cycletls.Options{
Body: "",
Ja3: "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0",
UserAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
DisableRedirect: true,
},
"GET")
if err != nil {
log.Fatal(err)
}
firstURL, _ := url.Parse(firstResponse.FinalUrl)
jar.SetCookies( firstURL, firstResponse.Cookies)
// 第二个请求验证cookies,包含第一个响应中的cookies
secondResponse, err := client.Do("https://httpbin.org/cookies", cycletls.Options{
Body: "",
Ja3: "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0",
UserAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
Headers: map[string]string{
"Cookie": getHeadersFromJar(jar, firstURL),
},
}, "GET")
if err != nil {
log.Fatal(err)
}
log.Println("第二个响应体:", secondResponse.Body)
}
func getHeadersFromJar(jar *cookiejar.Jar, url *url.URL) string {
cookies := jar.Cookies(url)
var cookieStrs []string
for _, cookie := range cookies {
cookieStrs = append(cookieStrs, cookie.Name+"="+cookie.Value)
}
return strings.Join(cookieStrs, "; ")
}
如何在CycleTLS中发送multipart/form-data
Javascript文本form-data
const initCycleTLS = require("cycletls");
const FormData = require('form-data');
(async () => {
const cycleTLS = await initCycleTLS();
const formData = new FormData();
formData.append("key1", "value1");
formData.append("key2", "value2");
const response = await cycleTLS('http://httpbin.org/post', {
body: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
}, 'post');
console.log(response);
cycleTLS.exit();
})();
Javascript文件form-data
const initCycleTLS = require("cycletls");
const FormData = require('form-data');
const fs = require('fs');
(async () => {
const cycleTLS = await initCycleTLS();
const formData = new FormData();
const fileStream = fs.createReadStream("../go.mod");
formData.append('file', fileStream);
const response = await cycleTLS('http://httpbin.org/post', {
body: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
}, 'post');
console.log(response);
cycleTLS.exit();
})();
Golang文本form-data
package main
import (
"bytes"
"github.com/Danny-Dasilva/CycleTLS/cycletls"
"log"
"mime/multipart"
)
func main() {
client := cycletls.Init()
// 准备一个buffer来写入我们的multipart表单
var requestBody bytes.Buffer
multipartWriter := multipart.NewWriter(&requestBody)
// 添加表单字段
multipartWriter.WriteField("key1", "value1")
multipartWriter.WriteField("key2", "value2")
contentType := multipartWriter.FormDataContentType()
// 在发出请求之前关闭writer
multipartWriter.Close()
response, err := client.Do("http://httpbin.org/post", cycletls.Options{
Body: requestBody.String(),
Headers: map[string]string{
"Content-Type": contentType,
},
}, "POST")
if err != nil {
log.Print("请求失败: " + err.Error())
}
log.Println(response.Body)
}
Golang文件上传form-data
package main
import (
"github.com/Danny-Dasilva/CycleTLS/cycletls"
"bytes"
"io"
"log"
"mime/multipart"
"os"
)
func main() {
client := cycletls.Init()
// 准备一个buffer来写入我们的multipart表单
var requestBody bytes.Buffer
multipartWriter := multipart.NewWriter(&requestBody)
// 添加一个文件
fileWriter, err := multipartWriter.CreateFormFile("fieldname", "filename")
if err != nil {
log.Fatal("CreateFormFile错误: ", err)
}
// 打开你想上传的文件
file, err := os.Open("path/to/your/file")
if err != nil {
log.Fatal("文件打开错误: ", err)
}
defer file.Close()
// 将文件复制到multipart writer
_, err = io.Copy(fileWriter, file)
if err != nil {
log.Fatal("文件复制错误: ", err)
}
// 在发出请求之前关闭writer
contentType := multipartWriter.FormDataContentType()
multipartWriter.Close()
response, err := client.Do("http://httpbin.org/post", cycletls.Options{
Body: requestBody.String(),
Headers: map[string]string{
"Content-Type": contentType,
},
}, "POST")
if err != nil {
log.Print("请求失败: " + err.Error())
}
log.Println(response.Body)
}
如果需要,可以为golang添加编码辅助函数到仓库中
如何发送application/x-www-form-urlencoded POST请求
Javascript application/x-www-form-urlencoded 表单
const initCycleTLS = require("cycletls");
(async () => {
const cycleTLS = await initCycleTLS();
const urlEncodedData = new URLSearchParams();
urlEncodedData.append('key1', 'value1');
urlEncodedData.append('key2', 'value2');
const response = await cycleTLS('http://httpbin.org/post', {
body: urlEncodedData,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
}, 'post');
console.log(response);
cycleTLS.exit();
})();
Golang application/x-www-form-urlencoded 表单
package main
import (
"log"
"net/url"
"github.com/Danny-Dasilva/CycleTLS/cycletls"
)
func main() {
client := cycletls.Init()
// 准备表单数据
form := url.Values{}
form.Add("key1", "value1")
form.Add("key2", "value2")
response, err := client.Do("http://httpbin.org/post", cycletls.Options{
Body: form.Encode(),
Headers: map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
},
}, "POST")
if err != nil {
log.Print("请求失败: " + err.Error())
}
log.Println(response.Body)
}
如何下载图片?
具有以下类型的 Content-Type
头的图片会被 base64 编码。
支持的图片类型
image/svg+xml
image/webp
image/jpeg
image/png
application/pdf
要将它们写入文件,你可以使用以下方法
Javascript 将图片写入文件
const initCycleTLS = require("cycletls");
var fs = require("fs");
// 将图片写入文件的函数
const writeImage = (filename, data) => {
let writeStream = fs.createWriteStream(filename);
// 以 base64 编码写入一些数据
writeStream.write(data, "base64");
writeStream.on("finish", () => {
console.log(`写入文件 ${filename}`);
});
// 关闭流
writeStream.end();
};
(async () => {
const cycleTLS = await initCycleTLS();
// try {
const jpegImage = await cycleTLS("http://httpbin.org/image/jpeg", {
ja3: "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0",
userAgent:
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0",
});
// 写入图片
writeImage("test.jpeg", jpegImage.body);
cycleTLS.exit();
})();
Golang 将图片写入文件
package main
import (
"encoding/base64"
"os"
"github.com/Danny-Dasilva/CycleTLS/cycletls"
)
func main() {
client := cycletls.Init()
response, err := client.Do("http://httpbin.org/image/jpeg", cycletls.Options{
Body: "",
Ja3: "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-21,29-23-24,0",
UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36",
}, "GET")
// 解码 Base64
dec, err := base64.StdEncoding.DecodeString(response.Body)
if err != nil {
panic(err)
}
// 创建文件以写入
f, err := os.Create("test.jpeg")
if err != nil {
panic(err)
}
defer f.Close()
// 将 b64 写入文件
if _, err := f.Write(dec); err != nil {
panic(err)
}
if err := f.Sync(); err != nil {
panic(err)
}
}
计划增加对其他文件类型的支持。
欢迎通过提交Issue来请求支持特定文件类型。
如何设置/强制使用 HTTP1
在 golang 中,在 Options 中设置 ForceHTTP1
package main
import (
"github.com/Danny-Dasilva/CycleTLS/cycletls"
"log"
)
func main() {
client := cycletls.Init()
response, err := client.Do("https://tls.peet.ws/api/all", cycletls.Options{
ForceHTTP1: true,
}, "GET")
if err != nil {
log.Print("请求失败: " + err.Error())
}
log.Println(response.Body,) //你可以在响应中验证 HTTP_Version
}
在 JS/TS 中,在 Options 中设置 forceHTTP1
const initCycleTLS = require('cycletls');
// Typescript: import initCycleTLS from 'cycletls';
(async () => {
const cycleTLS = await initCycleTLS();
const response = await cycleTLS('https://ja3er.com/json', {
body: '',
ja3: '771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0',
userAgent:
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0',
forceHTTP1: false, //设置此字段
});
console.log(response);
//你可以在响应中验证 HTTP_Version
cycleTLS.exit();
})();
交叉编译适用于其他平台
原生支持的三种操作系统类型 linux
、darwin
和 windows
应该涵盖了大多数使用场景。
你可以使用内置的 Golang 交叉编译命令 go build
来为其他操作系统编译。
例如,对于 linux arm,你需要传入 GOOS
和 GOARCH
参数
$ GOOS=linux GOARCH=arm go build -o ./dist/index ./golang && chmod +x ./dist/index
使用上述命令,你只需运行 ./index
,CycleTLS 就应该按预期运行。
使用这个 gist 查看支持交叉编译的不同操作系统,如果你有特定操作系统的使用需求,欢迎通过提交 Issue 来请求新功能。
许可证
GPL3 许可证概要
总结 GPL3许可证的主要内容如下:
1. 任何人都可以复制、修改和分发此软件。
2. 每次分发时必须包含许可证和版权声明。
3. 您可以私下使用此软件。
4. 您可以将此软件用于商业目的。
5. 分发软件时必须提供源代码。
6. 对此代码库的任何修改必须以相同的许可证(GPLv3)分发。
7. 此软件不提供任何保证。
8. 软件作者或许可方不对软件造成的任何损害承担责任。