Skip to content

Commit

Permalink
feat: ability to edit status messages (#1126)
Browse files Browse the repository at this point in the history
* SetStatusMessage

* Docstring

* statusLine in header

* Use statusLine as []byte + ResponseHeader parsing

* status line getter
  • Loading branch information
valchulen committed Oct 22, 2021
1 parent 4cfec1a commit 556aa81
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
26 changes: 25 additions & 1 deletion header.go
Expand Up @@ -33,6 +33,7 @@ type ResponseHeader struct {
noDefaultDate bool

statusCode int
statusLine []byte
contentLength int
contentLengthBytes []byte
secureErrorLogMessage bool
Expand Down Expand Up @@ -136,6 +137,19 @@ 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
}
return statusLine(h.StatusCode())
}

// SetStatusLine sets response status line bytes.
func (h *ResponseHeader) SetStatusLine(statusLine []byte) {
h.statusLine = append(h.statusLine[:0], statusLine...)
}

// SetLastModified sets 'Last-Modified' header to the given value.
func (h *ResponseHeader) SetLastModified(t time.Time) {
h.bufKV.value = AppendHTTPDate(h.bufKV.value[:0], t)
Expand Down Expand Up @@ -683,6 +697,7 @@ func (h *ResponseHeader) resetSkipNormalize() {
h.connectionClose = false

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

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

dst.statusCode = h.statusCode
dst.statusLine = append(dst.statusLine[:0], h.statusLine...)
dst.contentLength = h.contentLength
dst.contentLengthBytes = append(dst.contentLengthBytes, h.contentLengthBytes...)
dst.contentType = append(dst.contentType, h.contentType...)
Expand Down Expand Up @@ -1639,7 +1655,12 @@ func (h *ResponseHeader) AppendBytes(dst []byte) []byte {
if statusCode < 0 {
statusCode = StatusOK
}
dst = append(dst, statusLine(statusCode)...)

if len(h.statusLine) > 0 {
dst = append(dst, h.statusLine...)
} else {
dst = append(dst, statusLine(statusCode)...)
}

server := h.Server()
if len(server) != 0 {
Expand Down Expand Up @@ -1859,6 +1880,9 @@ 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:])
}

return len(buf) - len(bNext), nil
}
Expand Down
10 changes: 9 additions & 1 deletion header_test.go
Expand Up @@ -36,7 +36,7 @@ func TestResponseHeaderAddContentType(t *testing.T) {
func TestResponseHeaderMultiLineValue(t *testing.T) {
t.Parallel()

s := "HTTP/1.1 200 OK\r\n" +
s := "HTTP/1.1 200 SuperOK\r\n" +
"EmptyValue1:\r\n" +
"Content-Type: foo/bar;\r\n\tnewline;\r\n another/newline\r\n" +
"Foo: Bar\r\n" +
Expand All @@ -52,6 +52,10 @@ 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())
}

for name, vals := range response.Header {
got := string(header.Peek(name))
want := vals[0]
Expand All @@ -78,6 +82,10 @@ 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())
}
}

func TestResponseHeaderMultiLinePaniced(t *testing.T) {
Expand Down
18 changes: 18 additions & 0 deletions http_test.go
Expand Up @@ -837,6 +837,24 @@ func TestResponseSkipBody(t *testing.T) {
t.Fatalf("unexpected content-type in response %q", s)
}

// set StatusNoContent with statusLine
r.Header.SetStatusCode(StatusNoContent)
r.Header.SetStatusLine([]byte("HTTP/1.1 204 NC\r\n"))
r.SetBodyString("foobar")
s = r.String()
if strings.Contains(s, "\r\n\r\nfoobar") {
t.Fatalf("unexpected non-zero body in response %q", s)
}
if strings.Contains(s, "Content-Length: ") {
t.Fatalf("unexpected content-length in response %q", s)
}
if strings.Contains(s, "Content-Type: ") {
t.Fatalf("unexpected content-type in response %q", s)
}
if !strings.HasPrefix(s, "HTTP/1.1 204 NC\r\n") {
t.Fatalf("expecting non-default status line in response %q", s)
}

// explicitly skip body
r.Header.SetStatusCode(StatusOK)
r.SkipBody = true
Expand Down

0 comments on commit 556aa81

Please sign in to comment.