JS Headers and case-sensitivity

Currently JS Headers such as `Nats-Expected-Last-Sequence` are case-sensitive
in the server to have a fast path rather and avoid `ReadMIMEHeader`.

In this change, we try to keep the fast path but add another check for cases
when the header may have been sent in a different case than expected.

Signed-off-by: Waldemar Quevedo <wally@synadia.com>
This commit is contained in:
Waldemar Quevedo
2021-04-09 11:11:49 -07:00
parent 112257d09d
commit a9e4aa4d42
2 changed files with 32 additions and 1 deletions

View File

@@ -3653,9 +3653,16 @@ func getHeader(key string, hdr []byte) []byte {
if len(hdr) == 0 {
return nil
}
// Fast-path is for when headers use canonical case.
index := bytes.Index(hdr, []byte(key))
if index < 0 {
return nil
// To make JetStream headers case insensitive, do another lookup
// with headers in lowercase.
index = bytes.Index(hdr, bytes.ToLower([]byte(key)))
if index < 0 {
return nil
}
}
index += len(key)
if index >= len(hdr) {

View File

@@ -3427,6 +3427,30 @@ func TestJetStreamPublishExpect(t *testing.T) {
t.Fatalf("Expected an error, got %q", resp.Data)
}
// Check with JS Headers in different cases.
m = nats.NewMsg("foo.bar")
m.Data = []byte("HI")
m.Header[JSExpectedLastSeq] = []string{"5"}
resp, err = nc.RequestMsg(m, 100*time.Millisecond)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if pa := getPubAckResponse(resp.Data); pa == nil || pa.Error == nil {
t.Fatalf("Expected an error, got %q", resp.Data)
}
// Try with JS Header in lower case.
// nats-expected-last-sequence: 5
m = nats.NewMsg("foo.bar")
m.Header[strings.ToLower(JSExpectedLastSeq)] = []string{"5"}
resp, err = nc.RequestMsg(m, 100*time.Millisecond)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if pa := getPubAckResponse(resp.Data); pa == nil || pa.Error == nil {
t.Fatalf("Expected an error, got %q", resp.Data)
}
// Restart the server and make sure we remember/rebuild last seq and last msgId.
// Stop current
sd := s.JetStreamConfig().StoreDir