Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix StatusLine issue #1134

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 29 additions & 14 deletions header.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
"strconv"
"sync"
"sync/atomic"
"time"
Expand Down Expand Up @@ -33,7 +34,7 @@ type ResponseHeader struct {
noDefaultDate bool

statusCode int
statusLine []byte
statusText []byte
contentLength int
contentLengthBytes []byte
secureErrorLogMessage bool
Expand Down Expand Up @@ -137,17 +138,27 @@ func (h *ResponseHeader) SetStatusCode(statusCode int) {
h.statusCode = statusCode
}

// StatusLine returns response status line.
func (h *ResponseHeader) StatusLine() []byte {
if len(h.statusLine) > 0 {
return h.statusLine
// StatusLine returns response status text.
//
// Return value looks something like "OK"
//
// The returned value is valid until the response is released,
// either though ReleaseResponse or your request handler returning.
// Do not store references to returned value. Make copies instead.
func (h *ResponseHeader) StatusText() []byte {
if len(h.statusText) > 0 {
return h.statusText
}
return statusLine(h.StatusCode())
return s2b(StatusMessage(h.StatusCode()))
}

// SetStatusLine sets response status line bytes.
func (h *ResponseHeader) SetStatusLine(statusLine []byte) {
h.statusLine = append(h.statusLine[:0], statusLine...)
// SetStatusText sets response status text bytes.
//
// statusLine should be something like "OK".
//
// statusLine is safe to reuse after this method has returned.
func (h *ResponseHeader) SetStatusText(statusLine []byte) {
h.statusText = append(h.statusText[:0], statusLine...)
}

// SetLastModified sets 'Last-Modified' header to the given value.
Expand Down Expand Up @@ -697,7 +708,7 @@ func (h *ResponseHeader) resetSkipNormalize() {
h.connectionClose = false

h.statusCode = 0
h.statusLine = h.statusLine[:0]
h.statusText = h.statusText[:0]
h.contentLength = 0
h.contentLengthBytes = h.contentLengthBytes[:0]

Expand Down Expand Up @@ -746,7 +757,7 @@ func (h *ResponseHeader) CopyTo(dst *ResponseHeader) {
dst.noDefaultDate = h.noDefaultDate

dst.statusCode = h.statusCode
dst.statusLine = append(dst.statusLine[:0], h.statusLine...)
dst.statusText = append(dst.statusText[:0], h.statusText...)
dst.contentLength = h.contentLength
dst.contentLengthBytes = append(dst.contentLengthBytes, h.contentLengthBytes...)
dst.contentType = append(dst.contentType, h.contentType...)
Expand Down Expand Up @@ -1656,8 +1667,12 @@ func (h *ResponseHeader) AppendBytes(dst []byte) []byte {
statusCode = StatusOK
}

if len(h.statusLine) > 0 {
dst = append(dst, h.statusLine...)
if len(h.statusText) > 0 {
dst = append(dst, "HTTP/1.1 "...)
dst = strconv.AppendInt(dst, int64(statusCode), 10)
dst = append(dst, ' ')
dst = append(dst, h.statusText...)
dst = append(dst, "\r\n"...)
} else {
dst = append(dst, statusLine(statusCode)...)
}
Expand Down Expand Up @@ -1881,7 +1896,7 @@ func (h *ResponseHeader) parseFirstLine(buf []byte) (int, error) {
return 0, fmt.Errorf("unexpected char at the end of status code. Response %q", buf)
}
if len(b) > n+1 && !bytes.Equal(b[n+1:], statusLine(h.statusCode)) {
h.SetStatusLine(b[n+1:])
h.SetStatusText(b[n+1:])
}

return len(buf) - len(bNext), nil
Expand Down
8 changes: 4 additions & 4 deletions header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ func TestResponseHeaderMultiLineValue(t *testing.T) {
t.Fatalf("parse response using net/http failed, %s", err)
}

if !bytes.Equal(header.StatusLine(), []byte("SuperOK")) {
t.Errorf("parse status line with non-default value failed, got: %s want: SuperOK", header.StatusLine())
if !bytes.Equal(header.StatusText(), []byte("SuperOK")) {
t.Errorf("parse status line with non-default value failed, got: %s want: SuperOK", header.StatusText())
}

for name, vals := range response.Header {
Expand Down Expand Up @@ -83,8 +83,8 @@ func TestResponseHeaderMultiLineName(t *testing.T) {
t.Errorf("expected error, got %q (%v)", m, err)
}

if !bytes.Equal(header.StatusLine(), []byte("OK")) {
t.Errorf("expected default status line, got: %s", header.StatusLine())
if !bytes.Equal(header.StatusText(), []byte("OK")) {
t.Errorf("expected default status line, got: %s", header.StatusText())
}
}

Expand Down
2 changes: 1 addition & 1 deletion http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ func TestResponseSkipBody(t *testing.T) {

// set StatusNoContent with statusLine
r.Header.SetStatusCode(StatusNoContent)
r.Header.SetStatusLine([]byte("HTTP/1.1 204 NC\r\n"))
r.Header.SetStatusText([]byte("NC"))
r.SetBodyString("foobar")
s = r.String()
if strings.Contains(s, "\r\n\r\nfoobar") {
Expand Down