如何在Go语言中解析HTTP头部

16

我在日志中记录了从其他地方传输的HTTP响应头。我的日志文件中有类似以下的内容:

Date: Fri, 21 Mar 2014 06:45:15 GMT\r\nContent-Encoding: gzip\r\nLast-Modified: Tue, 20 Aug 2013 15:45:41 GMT\r\nServer: nginx/0.8.54\r\nAge: 18884\r\nVary: Accept-Encoding\r\nContent-Type: text/html\r\nCache-Control: max-age=864000, public\r\nX-UA-Compatible: IE=Edge,chrome=1\r\nTiming-Allow-Origin: *\r\nContent-Length: 14888\r\nExpires: Mon, 31 Mar 2014 06:45:15 GMT\r\n

给定上述内容作为字符串,我该如何将其解析为 net/http 中描述的 Header 对象?一种方法是手动拆分字符串并映射键值对... 但我正在寻找避免手动操作并使用标准(或维护良好的第三方)库来解析它的方法... 有什么建议吗?


@dystroy,我觉得这不是重复的问题,请您详细说明一下。 - SirDarius
1
解析这个非常简单。它只是一串由换行符分隔的键值对字符串。你可能需要在这个问题上动动手脚。 - Ralph Caraveo
@ralph-caraveo 是的,这很琐碎,但我很懒。我喜欢尽可能拥有少量的代码... 另外,被接受的答案还免费提供了诸如规范化等方面的内容。 - sajal
1个回答

26

内置解析器在textproto中。您可以直接使用它,或者添加一个虚假的HTTP请求头并在http包中使用ReadRequest。无论哪种方式,您都需要将数据包装到bufio.Reader中。这里我只是假设我们从一个字符串开始。

使用textproto:

logEntry := "Content-Encoding: gzip\r\nLast-Modified: Tue, 20 Aug 2013 15:45:41 GMT\r\nServer: nginx/0.8.54\r\nAge: 18884\r\nVary: Accept-Encoding\r\nContent-Type: text/html\r\nCache-Control: max-age=864000, public\r\nX-UA-Compatible: IE=Edge,chrome=1\r\nTiming-Allow-Origin: *\r\nContent-Length: 14888\r\nExpires: Mon, 31 Mar 2014 06:45:15 GMT\r\n"

// don't forget to make certain the headers end with a second "\r\n"
reader := bufio.NewReader(strings.NewReader(logEntry + "\r\n"))
tp := textproto.NewReader(reader)

mimeHeader, err := tp.ReadMIMEHeader()
if err != nil {
   log.Fatal(err)
}

// http.Header and textproto.MIMEHeader are both just a map[string][]string
httpHeader := http.Header(mimeHeader)
log.Println(httpHeader)

使用 http.ReadRequest 方法:

logEntry := "Content-Encoding: gzip\r\nLast-Modified: Tue, 20 Aug 2013 15:45:41 GMT\r\nServer: nginx/0.8.54\r\nAge: 18884\r\nVary: Accept-Encoding\r\nContent-Type: text/html\r\nCache-Control: max-age=864000, public\r\nX-UA-Compatible: IE=Edge,chrome=1\r\nTiming-Allow-Origin: *\r\nContent-Length: 14888\r\nExpires: Mon, 31 Mar 2014 06:45:15 GMT\r\n"

// we need to make sure to add a fake HTTP header here to make a valid request.
reader := bufio.NewReader(strings.NewReader("GET / HTTP/1.1\r\n" + logEntry + "\r\n"))

logReq, err := http.ReadRequest(reader)
if err != nil {
   log.Fatal(err)
}

log.Println(logReq.Header)

https://golang.org/pkg/net/textproto


谢谢。运行得很好。 - sajal
这也适用于电子邮件,因为net/mail使用textproto进行mime解析。 - Xeoncross

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接