Project Icon

CycleTLS

自定义TLS指纹模拟的高性能工具

CycleTLS是一款高性能TLS指纹模拟工具,支持自定义JA3指纹、HTTP头顺序和用户代理。它采用goroutine池处理异步请求,支持代理,并提供JavaScript和Go语言API。CycleTLS能够精确模拟不同浏览器的TLS行为,可用于网络测试和安全研究。作为一个开源项目,CycleTLS为开发者提供了灵活的网络通信模拟功能。

CycleTLS

CycleTLS

接受社区支持和PR

构建 GoDoc 许可证 Go 报告卡 npm 版本 在 Discord 上聊天

如果您有API更改或功能请求,请随时开启一个问题

🚀 特性

  • 高性能 内置的goroutine池用于处理异步请求
  • 通过fhttp实现自定义头部排序
  • 代理支持 | Socks4, Socks5, Socks5h
  • Ja3 Token配置

目录

依赖

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的namevalue

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();

})();

交叉编译适用于其他平台

原生支持的三种操作系统类型 linuxdarwinwindows 应该涵盖了大多数使用场景。

你可以使用内置的 Golang 交叉编译命令 go build 来为其他操作系统编译。

例如,对于 linux arm,你需要传入 GOOSGOARCH 参数

$ 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. 软件作者或许可方不对软件造成的任何损害承担责任。

有关许可证的更多信息可以在这里找到

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号