go语言解析HTTP包生成代码发送HTTP数据包

输入是从fiddler捕获的HTTP数据包

GET https://bbs.kanxue.com/ HTTP/1.1
Host: bbs.kanxue.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9

运行程序以后,粘贴上面的内容,然后回车即可。

需要注意的是,有的请求没有body部分,所以需要多一个回车。

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"net/url"
	"os"
	"strings"
	"text/template"
)

type Request struct {
	Method string
	URL    string
	//Headers []struct {
	//	Key   string
	//	Value string
	//}
	Headers map[string]string
	Body    string
	Proxy   string
}

func main() {
	reader := bufio.NewReader(os.Stdin)

	// 读取并解析起始行
	startLine, _ := reader.ReadString('\n')
	method, reqURL, _ := parseStartLine(startLine)

	// 读取并解析Header部分
	headers := make(map[string]string)
	for {
		line, _ := reader.ReadString('\n')
		if line == "\r\n" {
			break
		}
		key, value := parseHeader(line)
		headers[key] = value
	}
	delete(headers, "Content-Length")

	// 读取Body部分
	body, _ := reader.ReadString('\n')
	//fmt.Println("Body: ", body)

	// 输出解析结果
	//fmt.Println("RequestMethod: ", method)
	//fmt.Println("RequestURL: ", reqURL)
	//fmt.Println("Headers: ", headers)
	//fmt.Println("Body: ", body)

	data := &Request{
		Method:  method,
		URL:     reqURL,
		Headers: headers,
		Body:    body,
		Proxy:   "http://127.0.0.1:7788",
	}
	generate(data)
}

func replace(input, from, to string) string {
	return strings.Replace(input, from, to, -1)
}

func generate(data *Request) {
	// 从内存中获取数据,构造结构体

	funcMap := template.FuncMap{"replace": replace}
	// 定义模板
	t := template.Must(template.New("codeTemplate").Funcs(funcMap).Parse(`
package main

import (
        "bytes"
        "fmt"
        "io/ioutil"
        "net/http"
        "net/url"
)

func main() {
        // 请求方法
        method := "{{.Method}}"
        urls := "{{.URL}}"
        
        // 请求头
        headers := map[string]string{
                {{range $key, $value :=.Headers}}"{{$key}}": "{{replace $value "\"" "\\\""}}",
                {{end}}
        }
        
        // 请求 body
        body := ` + "`{{.Body}}`" + `
        
        // 创建 HTTP 客户端
		client := &http.Client{}


		proxyStr := "{{.Proxy}}"
		_, err := url.Parse(proxyStr)
		{{if .Proxy}}
		// 设置代理

		proxyURL, err := url.Parse(proxyStr)
		if err != nil {
			fmt.Println("Error parsing proxy URL:", err)
			return
		}

		// 设置 HTTP 客户端的代理
		client.Transport = &http.Transport{Proxy: http.ProxyURL(proxyURL)}
		{{end}}

        // 创建 HTTP 请求
        req, err := http.NewRequest(method, urls, bytes.NewBuffer([]byte(body)))
        if err != nil {
                fmt.Println("Error creating HTTP request:", err)
                return
        }

        // 添加 HTTP 请求头
        for key, value := range headers {
                req.Header.Set(key, value)
        }

        // 发送 HTTP 请求
        resp, err := client.Do(req)
        if err != nil {
                fmt.Println("Error sending HTTP request:", err)
                return
        }
        defer resp.Body.Close()

        // 读取 HTTP 响应体
        respBody, err := ioutil.ReadAll(resp.Body)
        if err != nil {
                fmt.Println("Error reading HTTP response body:", err)
                return
        }

        // 输出 HTTP 响应体
        fmt.Println(string(respBody))
}
`))

	// 渲染模板
	var buf bytes.Buffer
	if err := t.Execute(&buf, data); err != nil {
		log.Fatalf("Failed to render template: %v", err)
	}

	// 将 Go 语言代码写入文件
	file, err := os.Create("http_request.go")
	if err != nil {
		log.Fatalf("Failed to create file: %v", err)
	}
	defer file.Close()
	if _, err := file.Write(buf.Bytes()); err != nil {
		log.Fatalf("Failed to write file: %v", err)
	}
	fmt.Println("Go 语言程序生成成功,请通过 go run 命令运行 http_request.go 程序。")
}

// 解析HTTP请求起始行
func parseStartLine(startLine string) (string, string, error) {
	// 移除行尾的回车换行符
	startLine = strings.TrimSpace(startLine)

	parts := strings.Split(startLine, " ")
	if len(parts) != 3 {
		return "", "", fmt.Errorf("Invalid Start Line: %s", startLine)
	}

	reqURL, err := url.Parse(parts[1])
	if err != nil {
		return "", "", err
	}

	return parts[0], reqURL.String(), nil
}

// 解析HTTP请求Header部分
func parseHeader(line string) (string, string) {
	parts := strings.SplitN(line, ":", 2)
	if len(parts) != 2 {
		return "", ""
	}

	key := strings.TrimSpace(parts[0])
	value := strings.TrimSpace(parts[1])

	return key, value
}

posted @ 2023-06-21 11:53  念秋  阅读(91)  评论(0编辑  收藏  举报