为了账号安全,请及时绑定邮箱和手机立即绑定

在 Go 中解析来自文本文件的 HTTP 请求和响应

在 Go 中解析来自文本文件的 HTTP 请求和响应

Go
Smart猫小萌 2021-11-22 20:02:26
给定以下文件,其中包含 HTTP 请求和 HTTP 响应的 HTTP 流水线流。如何将此文件解析为我的stream变量?type Connection struct{   Request *http.Request   Response *http.Response}stream := make([]Connection, 0)原始文件:GET /ubuntu/dists/trusty/InRelease HTTP/1.1Host: archive.ubuntu.comCache-Control: max-age=0Accept: text/*User-Agent: Debian APT-HTTP/1.3 (1.0.1ubuntu2)HTTP/1.1 404 Not FoundDate: Thu, 26 Nov 2015 18:26:36 GMTServer: Apache/2.2.22 (Ubuntu)Vary: Accept-EncodingContent-Length: 311Content-Type: text/html; charset=iso-8859-1<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL /ubuntu/dists/trusty/InRelease was not found on this server.</p><hr><address>Apache/2.2.22 (Ubuntu) Server at archive.ubuntu.com Port 80</address></body></html>GET /ubuntu/dists/trusty-updates/InRelease HTTP/1.1Host: archive.ubuntu.comCache-Control: max-age=0Accept: text/*User-Agent: Debian APT-HTTP/1.3 (1.0.1ubuntu2)HTTP/1.1 200 OKDate: Thu, 26 Nov 2015 18:26:37 GMTServer: Apache/2.2.22 (Ubuntu)Last-Modified: Thu, 26 Nov 2015 18:03:00 GMTETag: "fbb7-5257562a5fd00"Accept-Ranges: bytesContent-Length: 64439Cache-Control: max-age=382, proxy-revalidateExpires: Thu, 26 Nov 2015 18:33:00 GMT-----BEGIN PGP SIGNED MESSAGE-----Hash: SHA512Origin: UbuntuLabel: UbuntuSuite: trusty-updatesVersion: 14.04Codename: trusty[... truncated by author]我知道有http.ReadRequest。响应呢?任何想法/反馈/想法表示赞赏。
查看完整描述

1 回答

?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

其实很简单:


package main


import (

    "bufio"

    "bytes"

    "fmt"

    "io"

    "io/ioutil"

    "log"

    "net/http"

    "net/http/httputil"

    "os"

)


type Connection struct {

    Request  *http.Request

    Response *http.Response

}


func ReadHTTPFromFile(r io.Reader) ([]Connection, error) {

    buf := bufio.NewReader(r)

    stream := make([]Connection, 0)


    for {

        req, err := http.ReadRequest(buf)

        if err == io.EOF {

            break

        }

        if err != nil {

            return stream, err

        }


        resp, err := http.ReadResponse(buf, req)

        if err != nil {

            return stream, err

        }


        //save response body

        b := new(bytes.Buffer)

        io.Copy(b, resp.Body)

        resp.Body.Close()

        resp.Body = ioutil.NopCloser(b)


        stream = append(stream, Connection{Request: req, Response: resp})

    }

    return stream, nil


}

func main() {

    f, err := os.Open("/tmp/test.http")

    if err != nil {

        log.Fatal(err)

    }

    defer f.Close()

    stream, err := ReadHTTPFromFile(f)

    if err != nil {

        log.Fatalln(err)

    }

    for _, c := range stream {

        b, err := httputil.DumpRequest(c.Request, true)

        if err != nil {

            log.Fatal(err)

        }

        fmt.Println(string(b))

        b, err = httputil.DumpResponse(c.Response, true)

        if err != nil {

            log.Fatal(err)

        }

        fmt.Println(string(b))

    }

}

一些注意事项:

  • http.ReadRequesthttp.ReadResponse

  • http.ReadRequest并且http.ReadResponse可以在同一时间一遍又一遍地调用,bufio.Reader直到EOF它“正常工作”

    • “正常工作”取决于 Content-Length 标头是否存在且正确,因此读取正文会将 Reader 置于下一个请求/响应的开头

    • 阅读代码以准确了解哪些有效,哪些无效

  • resp.Body必须根据Close文档进行编辑,因此我们必须将其复制到另一个缓冲区以保留它

  • 使用您的示例数据(修改 Content-Length 以匹配您的截断),此代码将输出与给定相同的请求和响应

  • httputil.DumpRequest并且httputil.DumpResponse不一定以与输入文件相同的顺序转储 HTTP 标头,所以不要期望 adiff是完美的


查看完整回答
反对 回复 2021-11-22
  • 1 回答
  • 0 关注
  • 258 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信