| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- package l7
- import (
- "bytes"
- "strconv"
- "strings"
- )
- func ParseHttp(payload []byte) (string, string) {
- method, rest, ok := bytes.Cut(payload, space)
- if !ok {
- return "", ""
- }
- if !isHttpMethod(string(method)) {
- return "", ""
- }
- uri, _, ok := bytes.Cut(rest, space)
- if !ok {
- uri = append(uri, []byte("...")...)
- }
- return string(method), string(uri)
- }
- // parseHttpHeader 解析 HTTP 头部字段的值
- func parseHttpHeader(payload []byte, headerName string) string {
- headerBytes := []byte(headerName)
- headerIdx := bytes.Index(payload, headerBytes)
- if headerIdx == -1 {
- return ""
- }
- headerStart := headerIdx + len(headerBytes)
- if headerStart >= len(payload) {
- return ""
- }
- // 查找头部值的结束位置(\r\n)
- headerEnd := bytes.Index(payload[headerStart:], []byte("\r\n"))
- if headerEnd == -1 {
- // 如果没有找到 \r\n,使用剩余数据的长度
- headerEnd = len(payload) - headerStart
- }
- if headerEnd <= 0 {
- return ""
- }
- headerValue := payload[headerStart : headerStart+headerEnd]
- return string(bytes.TrimSpace(headerValue))
- }
- // parseHttpHostCommon 解析 HTTP 请求的公共逻辑,返回 method, requestURI, host, port, rest
- // rest 是解析完 method 和 uri 后剩余的 payload 部分,用于后续解析其他头部
- func parseHttpHostCommon(payload []byte, isTls bool) (string, string, string, uint16, []byte) {
- method, rest, ok := bytes.Cut(payload, space)
- if !ok {
- return "", "", "", 0, nil
- }
- if !isHttpMethod(string(method)) {
- return "", "", "", 0, nil
- }
- uri, rest, ok := bytes.Cut(rest, space)
- if !ok {
- uri = append(uri, []byte("...")...)
- }
- // 解析 Host 头部
- hostPort := parseHttpHeader(rest, "Host:")
- if hostPort == "" {
- return string(method), string(uri), "", 0, rest
- }
- hostParts := strings.Split(hostPort, ":")
- host := hostParts[0]
- // 根据 TLS 标识设置默认端口
- var port uint16
- if isTls {
- port = 443 // HTTPS 默认端口
- } else {
- port = 80 // HTTP 默认端口
- }
- // 如果 Host 头部明确指定了端口,使用指定的端口
- if len(hostParts) > 1 {
- port64, err := strconv.ParseUint(hostParts[1], 10, 16)
- if err == nil {
- port = uint16(port64)
- }
- }
- return string(method), string(uri), host, port, rest
- }
- // ParseHttpHost 解析 HTTP 请求,返回 method, requestURI, host, port
- // 不解析 User-Agent,性能更优
- func ParseHttpHost(payload []byte, isTls bool) (string, string, string, uint16) {
- method, uri, host, port, _ := parseHttpHostCommon(payload, isTls)
- return method, uri, host, port
- }
- // ParseHttpHostWithUserAgent 解析 HTTP 请求,返回 method, requestURI, host, port, userAgent
- // 包含 User-Agent 解析,适用于需要 User-Agent 信息的场景
- func ParseHttpHostWithUserAgent(payload []byte, isTls bool) (string, string, string, uint16, string) {
- method, uri, host, port, rest := parseHttpHostCommon(payload, isTls)
- // 解析 User-Agent 头部
- userAgent := parseHttpHeader(rest, "User-Agent:")
- return method, uri, host, port, userAgent
- }
- // ParseElasticsearch 解析 Elasticsearch HTTP 请求体
- // 只返回请求体(Query)部分
- func ParseElasticsearch(payload []byte) string {
- _, _, _, _, rest := parseHttpHostCommon(payload, false)
- // 查找请求体的开始位置(\r\n\r\n 之后)
- bodyStart := bytes.Index(rest, []byte("\r\n\r\n"))
- if bodyStart == -1 {
- // 如果没有找到完整的头部结束标记,返回空字符串
- return ""
- }
- bodyStart += 4
- // 提取请求体(限制长度,避免过长)
- body := rest[bodyStart:]
- maxBodyLen := 200
- if len(body) > maxBodyLen {
- body = body[:maxBodyLen]
- }
- // 只返回请求体内容
- bodyStr := strings.TrimSpace(string(body))
- return bodyStr
- }
|