Skip to content

Commit 89f39ea

Browse files
committed
client: retain order of headers in requests as specified
1 parent 7846101 commit 89f39ea

File tree

1 file changed

+108
-65
lines changed

1 file changed

+108
-65
lines changed

header.go

Lines changed: 108 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ type RequestHeader struct {
8282
userAgent []byte
8383
mulHeader [][]byte
8484

85+
explicitHost bool
86+
explicitUserAgent bool
87+
explicitContentType bool
88+
explicitContentLength bool
89+
explicitCookies bool
90+
explicitTrailer bool
91+
explicitConnection bool
92+
8593
h []argsKV
8694
trailer []argsKV
8795
bufKV argsKV
@@ -1134,33 +1142,47 @@ func (h *RequestHeader) VisitAllCookie(f func(key, value []byte)) {
11341142
//
11351143
// To get the headers in order they were received use VisitAllInOrder.
11361144
func (h *RequestHeader) VisitAll(f func(key, value []byte)) {
1137-
host := h.Host()
1138-
if len(host) > 0 {
1139-
f(strHost, host)
1145+
if !h.explicitHost {
1146+
host := h.Host()
1147+
if len(host) > 0 {
1148+
f(strHost, host)
1149+
}
11401150
}
1141-
if len(h.contentLengthBytes) > 0 {
1142-
f(strContentLength, h.contentLengthBytes)
1151+
if !h.explicitContentLength {
1152+
if len(h.contentLengthBytes) > 0 {
1153+
f(strContentLength, h.contentLengthBytes)
1154+
}
11431155
}
1144-
contentType := h.ContentType()
1145-
if len(contentType) > 0 {
1146-
f(strContentType, contentType)
1156+
if !h.explicitContentType {
1157+
contentType := h.ContentType()
1158+
if len(contentType) > 0 {
1159+
f(strContentType, contentType)
1160+
}
11471161
}
1148-
userAgent := h.UserAgent()
1149-
if len(userAgent) > 0 {
1150-
f(strUserAgent, userAgent)
1162+
if !h.explicitUserAgent {
1163+
userAgent := h.UserAgent()
1164+
if len(userAgent) > 0 {
1165+
f(strUserAgent, userAgent)
1166+
}
11511167
}
1152-
if len(h.trailer) > 0 {
1153-
f(strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
1168+
if !h.explicitTrailer {
1169+
if len(h.trailer) > 0 {
1170+
f(strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
1171+
}
11541172
}
11551173

1156-
h.collectCookies()
1157-
if len(h.cookies) > 0 {
1158-
h.bufKV.value = appendRequestCookieBytes(h.bufKV.value[:0], h.cookies)
1159-
f(strCookie, h.bufKV.value)
1174+
if !h.explicitCookies {
1175+
h.collectCookies()
1176+
if len(h.cookies) > 0 {
1177+
h.bufKV.value = appendRequestCookieBytes(h.bufKV.value[:0], h.cookies)
1178+
f(strCookie, h.bufKV.value)
1179+
}
11601180
}
11611181
visitArgs(h.h, f)
1162-
if h.ConnectionClose() {
1163-
f(strConnection, strClose)
1182+
if !h.explicitConnection {
1183+
if h.ConnectionClose() {
1184+
f(strConnection, strClose)
1185+
}
11641186
}
11651187
}
11661188

@@ -1233,24 +1255,31 @@ func (h *RequestHeader) del(key []byte) {
12331255
switch string(key) {
12341256
case HeaderHost:
12351257
h.host = h.host[:0]
1258+
h.explicitHost = false
12361259
case HeaderContentType:
12371260
h.contentType = h.contentType[:0]
1261+
h.explicitContentType = false
12381262
case HeaderUserAgent:
12391263
h.userAgent = h.userAgent[:0]
1264+
h.explicitUserAgent = false
12401265
case HeaderCookie:
12411266
h.cookies = h.cookies[:0]
1267+
h.explicitCookies = false
12421268
case HeaderContentLength:
12431269
h.contentLength = 0
12441270
h.contentLengthBytes = h.contentLengthBytes[:0]
1271+
h.explicitContentLength = false
12451272
case HeaderConnection:
12461273
h.connectionClose = false
1274+
h.explicitConnection = false
12471275
case HeaderTrailer:
12481276
h.trailer = h.trailer[:0]
1277+
h.explicitTrailer = false
12491278
}
12501279
h.h = delAllArgsBytes(h.h, key)
12511280
}
12521281

1253-
// setSpecialHeader handles special headers and return true when a header is processed.
1282+
// setSpecialHeader handles special headers.
12541283
func (h *ResponseHeader) setSpecialHeader(key, value []byte) bool {
12551284
if len(key) == 0 {
12561285
return false
@@ -1314,56 +1343,61 @@ func (h *ResponseHeader) setNonSpecial(key []byte, value []byte) {
13141343
}
13151344

13161345
// setSpecialHeader handles special headers and return true when a header is processed.
1317-
func (h *RequestHeader) setSpecialHeader(key, value []byte) bool {
1346+
func (h *RequestHeader) setSpecialHeader(key, value []byte) {
13181347
if len(key) == 0 {
1319-
return false
1348+
return
13201349
}
13211350

13221351
switch key[0] | 0x20 {
13231352
case 'c':
13241353
if caseInsensitiveCompare(strContentType, key) {
13251354
h.SetContentTypeBytes(value)
1326-
return true
1355+
h.explicitContentType = true
1356+
return
13271357
} else if caseInsensitiveCompare(strContentLength, key) {
13281358
if contentLength, err := parseContentLength(value); err == nil {
13291359
h.contentLength = contentLength
13301360
h.contentLengthBytes = append(h.contentLengthBytes[:0], value...)
1361+
h.explicitContentLength = true
13311362
}
1332-
return true
1363+
return
13331364
} else if caseInsensitiveCompare(strConnection, key) {
13341365
if bytes.Equal(strClose, value) {
13351366
h.SetConnectionClose()
13361367
} else {
13371368
h.ResetConnectionClose()
13381369
h.setNonSpecial(key, value)
13391370
}
1340-
return true
1371+
h.explicitConnection = true
1372+
return
13411373
} else if caseInsensitiveCompare(strCookie, key) {
13421374
h.collectCookies()
13431375
h.cookies = parseRequestCookies(h.cookies, value)
1344-
return true
1376+
h.explicitCookies = true
1377+
return
13451378
}
13461379
case 't':
13471380
if caseInsensitiveCompare(strTransferEncoding, key) {
13481381
// Transfer-Encoding is managed automatically.
1349-
return true
1382+
return
13501383
} else if caseInsensitiveCompare(strTrailer, key) {
13511384
_ = h.SetTrailerBytes(value)
1352-
return true
1385+
h.explicitTrailer = true
1386+
return
13531387
}
13541388
case 'h':
13551389
if caseInsensitiveCompare(strHost, key) {
13561390
h.SetHostBytes(value)
1357-
return true
1391+
h.explicitHost = true
1392+
return
13581393
}
13591394
case 'u':
13601395
if caseInsensitiveCompare(strUserAgent, key) {
13611396
h.SetUserAgentBytes(value)
1362-
return true
1397+
h.explicitUserAgent = true
1398+
return
13631399
}
13641400
}
1365-
1366-
return false
13671401
}
13681402

13691403
// setNonSpecial directly put into map i.e. not a basic header
@@ -1639,10 +1673,7 @@ func (h *RequestHeader) AddBytesV(key string, value []byte) {
16391673
// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
16401674
// it will be sent after the chunked request body.
16411675
func (h *RequestHeader) AddBytesKV(key, value []byte) {
1642-
if h.setSpecialHeader(key, value) {
1643-
return
1644-
}
1645-
1676+
h.setSpecialHeader(key, value)
16461677
k := getHeaderKeyBytes(&h.bufKV, b2s(key), h.disableNormalizing)
16471678
h.h = appendArgBytes(h.h, k, value, argsHasValue)
16481679
}
@@ -1698,9 +1729,7 @@ func (h *RequestHeader) SetBytesKV(key, value []byte) {
16981729
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
16991730
// it will be sent after the chunked request body.
17001731
func (h *RequestHeader) SetCanonical(key, value []byte) {
1701-
if h.setSpecialHeader(key, value) {
1702-
return
1703-
}
1732+
h.setSpecialHeader(key, value)
17041733
h.setNonSpecial(key, value)
17051734
}
17061735

@@ -2469,25 +2498,33 @@ func (h *RequestHeader) AppendBytes(dst []byte) []byte {
24692498
dst = append(dst, h.Protocol()...)
24702499
dst = append(dst, strCRLF...)
24712500

2472-
userAgent := h.UserAgent()
2473-
if len(userAgent) > 0 {
2474-
dst = appendHeaderLine(dst, strUserAgent, userAgent)
2501+
if !h.explicitUserAgent {
2502+
userAgent := h.UserAgent()
2503+
if len(userAgent) > 0 {
2504+
dst = appendHeaderLine(dst, strUserAgent, userAgent)
2505+
}
24752506
}
24762507

2477-
host := h.Host()
2478-
if len(host) > 0 {
2479-
dst = appendHeaderLine(dst, strHost, host)
2508+
if !h.explicitHost {
2509+
host := h.Host()
2510+
if len(host) > 0 {
2511+
dst = appendHeaderLine(dst, strHost, host)
2512+
}
24802513
}
24812514

2482-
contentType := h.ContentType()
2483-
if !h.noDefaultContentType && len(contentType) == 0 && !h.ignoreBody() {
2484-
contentType = strDefaultContentType
2485-
}
2486-
if len(contentType) > 0 {
2487-
dst = appendHeaderLine(dst, strContentType, contentType)
2515+
if !h.explicitContentType {
2516+
contentType := h.ContentType()
2517+
if !h.noDefaultContentType && len(contentType) == 0 && !h.ignoreBody() {
2518+
contentType = strDefaultContentType
2519+
}
2520+
if len(contentType) > 0 {
2521+
dst = appendHeaderLine(dst, strContentType, contentType)
2522+
}
24882523
}
2489-
if len(h.contentLengthBytes) > 0 {
2490-
dst = appendHeaderLine(dst, strContentLength, h.contentLengthBytes)
2524+
if !h.explicitContentLength {
2525+
if len(h.contentLengthBytes) > 0 {
2526+
dst = appendHeaderLine(dst, strContentLength, h.contentLengthBytes)
2527+
}
24912528
}
24922529

24932530
for i, n := 0, len(h.h); i < n; i++ {
@@ -2505,22 +2542,28 @@ func (h *RequestHeader) AppendBytes(dst []byte) []byte {
25052542
}
25062543
}
25072544

2508-
if len(h.trailer) > 0 {
2509-
dst = appendHeaderLine(dst, strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
2545+
if !h.explicitTrailer {
2546+
if len(h.trailer) > 0 {
2547+
dst = appendHeaderLine(dst, strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
2548+
}
25102549
}
25112550

2512-
// there is no need in h.collectCookies() here, since if cookies aren't collected yet,
2513-
// they all are located in h.h.
2514-
n := len(h.cookies)
2515-
if n > 0 {
2516-
dst = append(dst, strCookie...)
2517-
dst = append(dst, strColonSpace...)
2518-
dst = appendRequestCookieBytes(dst, h.cookies)
2519-
dst = append(dst, strCRLF...)
2551+
if !h.explicitCookies {
2552+
// there is no need in h.collectCookies() here, since if cookies aren't collected yet,
2553+
// they all are located in h.h.
2554+
n := len(h.cookies)
2555+
if n > 0 {
2556+
dst = append(dst, strCookie...)
2557+
dst = append(dst, strColonSpace...)
2558+
dst = appendRequestCookieBytes(dst, h.cookies)
2559+
dst = append(dst, strCRLF...)
2560+
}
25202561
}
25212562

2522-
if h.ConnectionClose() {
2523-
dst = appendHeaderLine(dst, strConnection, strClose)
2563+
if !h.explicitConnection {
2564+
if h.ConnectionClose() {
2565+
dst = appendHeaderLine(dst, strConnection, strClose)
2566+
}
25242567
}
25252568

25262569
return append(dst, strCRLF...)

0 commit comments

Comments
 (0)