TRA-4140 Fix HTTP/1.0 is recognized as HTTP/1.1 (#666)

This commit is contained in:
M. Mert Yıldıran 2022-01-20 11:02:21 +03:00 committed by GitHub
parent d5fd2ff1da
commit b31af7214b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 40 additions and 22 deletions

View File

@ -24,7 +24,7 @@ Think TCPDump and Wireshark re-invented for Kubernetes.
- Simple and powerful CLI
- Monitoring network traffic in real-time. Supported protocols:
- [HTTP/1.1](https://datatracker.ietf.org/doc/html/rfc2616) (REST, etc.)
- [HTTP/1.x](https://datatracker.ietf.org/doc/html/rfc2616) (REST, GraphQL, SOAP, etc.)
- [HTTP/2](https://datatracker.ietf.org/doc/html/rfc7540) (gRPC)
- [AMQP](https://www.rabbitmq.com/amqp-0-9-1-reference.html) (RabbitMQ, Apache Qpid, etc.)
- [Apache Kafka](https://kafka.apache.org/protocol)

View File

@ -66,7 +66,7 @@ func handleHTTP2Stream(http2Assembler *Http2Assembler, tcpID *api.TcpID, superTi
streamID,
"HTTP2",
)
item = reqResMatcher.registerRequest(ident, &messageHTTP1, superTimer.CaptureTime)
item = reqResMatcher.registerRequest(ident, &messageHTTP1, superTimer.CaptureTime, messageHTTP1.ProtoMinor)
if item != nil {
item.ConnectionInfo = &api.ConnectionInfo{
ClientIP: tcpID.SrcIP,
@ -86,7 +86,7 @@ func handleHTTP2Stream(http2Assembler *Http2Assembler, tcpID *api.TcpID, superTi
streamID,
"HTTP2",
)
item = reqResMatcher.registerResponse(ident, &messageHTTP1, superTimer.CaptureTime)
item = reqResMatcher.registerResponse(ident, &messageHTTP1, superTimer.CaptureTime, messageHTTP1.ProtoMinor)
if item != nil {
item.ConnectionInfo = &api.ConnectionInfo{
ClientIP: tcpID.DstIP,
@ -135,7 +135,7 @@ func handleHTTP1ClientStream(b *bufio.Reader, tcpID *api.TcpID, counterPair *api
counterPair.Request,
"HTTP1",
)
item := reqResMatcher.registerRequest(ident, req, superTimer.CaptureTime)
item := reqResMatcher.registerRequest(ident, req, superTimer.CaptureTime, req.ProtoMinor)
if item != nil {
item.ConnectionInfo = &api.ConnectionInfo{
ClientIP: tcpID.SrcIP,
@ -175,7 +175,7 @@ func handleHTTP1ServerStream(b *bufio.Reader, tcpID *api.TcpID, counterPair *api
counterPair.Response,
"HTTP1",
)
item := reqResMatcher.registerResponse(ident, res, superTimer.CaptureTime)
item := reqResMatcher.registerResponse(ident, res, superTimer.CaptureTime, res.ProtoMinor)
if item != nil {
item.ConnectionInfo = &api.ConnectionInfo{
ClientIP: tcpID.DstIP,

View File

@ -235,8 +235,8 @@ func checkIsHTTP2ServerStream(b *bufio.Reader) (bool, error) {
return false, err
}
// If response starts with this text, it is HTTP/1.x
if bytes.Compare(buf, []byte("HTTP/1.0 ")) == 0 || bytes.Compare(buf, []byte("HTTP/1.1 ")) == 0 {
// If response starts with HTTP/1. then it's not HTTP/2
if bytes.HasPrefix(buf, []byte("HTTP/1.")) {
return false, nil
}

View File

@ -15,7 +15,21 @@ import (
"github.com/up9inc/mizu/tap/api"
)
var protocol api.Protocol = api.Protocol{
var http10protocol api.Protocol = api.Protocol{
Name: "http",
LongName: "Hypertext Transfer Protocol -- HTTP/1.0",
Abbreviation: "HTTP",
Macro: "http",
Version: "1.0",
BackgroundColor: "#205cf5",
ForegroundColor: "#ffffff",
FontSize: 12,
ReferenceLink: "https://datatracker.ietf.org/doc/html/rfc1945",
Ports: []string{"80", "443", "8080"},
Priority: 0,
}
var http11protocol api.Protocol = api.Protocol{
Name: "http",
LongName: "Hypertext Transfer Protocol -- HTTP/1.1",
Abbreviation: "HTTP",
@ -69,12 +83,12 @@ func init() {
type dissecting string
func (d dissecting) Register(extension *api.Extension) {
extension.Protocol = &protocol
extension.Protocol = &http11protocol
extension.MatcherMap = reqResMatcher.openMessagesMap
}
func (d dissecting) Ping() {
log.Printf("pong %s", protocol.Name)
log.Printf("pong %s", http11protocol.Name)
}
func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, counterPair *api.CounterPair, superTimer *api.SuperTimer, superIdentifier *api.SuperIdentifier, emitter api.Emitter, options *api.TrafficFilteringOptions) error {
@ -96,7 +110,7 @@ func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, co
http2Assembler = createHTTP2Assembler(b)
}
if superIdentifier.Protocol != nil && superIdentifier.Protocol != &protocol {
if superIdentifier.Protocol != nil && superIdentifier.Protocol != &http11protocol {
return errors.New("Identified by another protocol")
}
@ -128,7 +142,7 @@ func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, co
tcpID.DstPort,
"HTTP2",
)
item := reqResMatcher.registerRequest(ident, req, superTimer.CaptureTime)
item := reqResMatcher.registerRequest(ident, req, superTimer.CaptureTime, req.ProtoMinor)
if item != nil {
item.ConnectionInfo = &api.ConnectionInfo{
ClientIP: tcpID.SrcIP,
@ -154,7 +168,7 @@ func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, co
if !dissected {
return err
}
superIdentifier.Protocol = &protocol
superIdentifier.Protocol = &http11protocol
return nil
}
@ -442,9 +456,9 @@ func (d dissecting) Represent(request map[string]interface{}, response map[strin
func (d dissecting) Macros() map[string]string {
return map[string]string{
`http`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s"`, protocol.Name, protocol.Version),
`http2`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s"`, protocol.Name, http2Protocol.Version),
`grpc`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s" and proto.macro == "%s"`, protocol.Name, grpcProtocol.Version, grpcProtocol.Macro),
`http`: fmt.Sprintf(`proto.name == "%s" and proto.version.startsWith("%c")`, http11protocol.Name, http11protocol.Version[0]),
`http2`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s"`, http11protocol.Name, http2Protocol.Version),
`grpc`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s" and proto.macro == "%s"`, http11protocol.Name, grpcProtocol.Version, grpcProtocol.Macro),
}
}

View File

@ -22,7 +22,7 @@ func createResponseRequestMatcher() requestResponseMatcher {
return *newMatcher
}
func (matcher *requestResponseMatcher) registerRequest(ident string, request *http.Request, captureTime time.Time) *api.OutputChannelItem {
func (matcher *requestResponseMatcher) registerRequest(ident string, request *http.Request, captureTime time.Time, protoMinor int) *api.OutputChannelItem {
split := splitIdent(ident)
key := genKey(split)
@ -41,14 +41,14 @@ func (matcher *requestResponseMatcher) registerRequest(ident string, request *ht
if responseHTTPMessage.IsRequest {
return nil
}
return matcher.preparePair(&requestHTTPMessage, responseHTTPMessage)
return matcher.preparePair(&requestHTTPMessage, responseHTTPMessage, protoMinor)
}
matcher.openMessagesMap.Store(key, &requestHTTPMessage)
return nil
}
func (matcher *requestResponseMatcher) registerResponse(ident string, response *http.Response, captureTime time.Time) *api.OutputChannelItem {
func (matcher *requestResponseMatcher) registerResponse(ident string, response *http.Response, captureTime time.Time, protoMinor int) *api.OutputChannelItem {
split := splitIdent(ident)
key := genKey(split)
@ -67,14 +67,18 @@ func (matcher *requestResponseMatcher) registerResponse(ident string, response *
if !requestHTTPMessage.IsRequest {
return nil
}
return matcher.preparePair(requestHTTPMessage, &responseHTTPMessage)
return matcher.preparePair(requestHTTPMessage, &responseHTTPMessage, protoMinor)
}
matcher.openMessagesMap.Store(key, &responseHTTPMessage)
return nil
}
func (matcher *requestResponseMatcher) preparePair(requestHTTPMessage *api.GenericMessage, responseHTTPMessage *api.GenericMessage) *api.OutputChannelItem {
func (matcher *requestResponseMatcher) preparePair(requestHTTPMessage *api.GenericMessage, responseHTTPMessage *api.GenericMessage, protoMinor int) *api.OutputChannelItem {
protocol := http11protocol
if protoMinor == 0 {
protocol = http10protocol
}
return &api.OutputChannelItem{
Protocol: protocol,
Timestamp: requestHTTPMessage.CaptureTime.UnixNano() / int64(time.Millisecond),

View File

@ -35,7 +35,7 @@ export function getClassification(statusCode: number): string {
let classification = StatusCodeClassification.NEUTRAL;
// 1 - 16 HTTP/2 (gRPC) status codes
// 2xx - 5xx HTTP/1.1 status codes
// 2xx - 5xx HTTP/1.x status codes
if ((statusCode >= 200 && statusCode <= 399) || statusCode === 0) {
classification = StatusCodeClassification.SUCCESS;
} else if (statusCode >= 400 || (statusCode >= 1 && statusCode <= 16)) {