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 }