aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoão Penteado <4219131+joaopenteado@users.noreply.github.com>2021-11-30 18:59:41 +0000
committerDamien Neil <dneil@google.com>2022-04-15 17:03:50 +0000
commitac01de5446ec92544768dabee3b0d1faf5f596d9 (patch)
tree8d74a1fbaf07cf4ad3bb91b13e46c6e3c205ec5d /src
parent082cfabf126d63e952e1ac29d47c2a47f1c64bee (diff)
downloadgo-ac01de5446ec92544768dabee3b0d1faf5f596d9.tar.xz
net/http: optimize StatusText implementation
The current implementation, although more succinct, relies on a runtime lookup to a "constant" unexported map (which also needs to be initialized at runtime). The proposed implementation is able to be optimized by the compiler at build-time, resulting in *much* more efficient instructions. Additionally, unused string literals may even be removed altogether from the generated binary in some cases. This change is fully backwards-compatible behavior-wise with the existing implementation. Change-Id: I36450320aacff5b322195820552f2831d4fecd52 GitHub-Last-Rev: e2058f132ef7a193529d4b0e84329ac93e5d1dcb GitHub-Pull-Request: golang/go#49811 Reviewed-on: https://go-review.googlesource.com/c/go/+/367201 Run-TryBot: Damien Neil <dneil@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Reviewed-by: Damien Neil <dneil@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/net/http/response.go5
-rw-r--r--src/net/http/server.go4
-rw-r--r--src/net/http/status.go198
3 files changed, 132 insertions, 75 deletions
diff --git a/src/net/http/response.go b/src/net/http/response.go
index eb4cd9b0ad..755c696557 100644
--- a/src/net/http/response.go
+++ b/src/net/http/response.go
@@ -246,9 +246,8 @@ func (r *Response) Write(w io.Writer) error {
// Status line
text := r.Status
if text == "" {
- var ok bool
- text, ok = statusText[r.StatusCode]
- if !ok {
+ text = StatusText(r.StatusCode)
+ if text == "" {
text = "status code " + strconv.Itoa(r.StatusCode)
}
} else {
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 62bdf16959..d44b0fb256 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -1516,7 +1516,7 @@ func writeStatusLine(bw *bufio.Writer, is11 bool, code int, scratch []byte) {
} else {
bw.WriteString("HTTP/1.0 ")
}
- if text, ok := statusText[code]; ok {
+ if text := StatusText(code); text != "" {
bw.Write(strconv.AppendInt(scratch[:0], int64(code), 10))
bw.WriteByte(' ')
bw.WriteString(text)
@@ -2192,7 +2192,7 @@ func Redirect(w ResponseWriter, r *Request, url string, code int) {
// Shouldn't send the body for POST or HEAD; that leaves GET.
if !hadCT && r.Method == "GET" {
- body := "<a href=\"" + htmlEscape(url) + "\">" + statusText[code] + "</a>.\n"
+ body := "<a href=\"" + htmlEscape(url) + "\">" + StatusText(code) + "</a>.\n"
fmt.Fprintln(w, body)
}
}
diff --git a/src/net/http/status.go b/src/net/http/status.go
index 286315f639..75fea0ca35 100644
--- a/src/net/http/status.go
+++ b/src/net/http/status.go
@@ -76,77 +76,135 @@ const (
StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6
)
-var statusText = map[int]string{
- StatusContinue: "Continue",
- StatusSwitchingProtocols: "Switching Protocols",
- StatusProcessing: "Processing",
- StatusEarlyHints: "Early Hints",
-
- StatusOK: "OK",
- StatusCreated: "Created",
- StatusAccepted: "Accepted",
- StatusNonAuthoritativeInfo: "Non-Authoritative Information",
- StatusNoContent: "No Content",
- StatusResetContent: "Reset Content",
- StatusPartialContent: "Partial Content",
- StatusMultiStatus: "Multi-Status",
- StatusAlreadyReported: "Already Reported",
- StatusIMUsed: "IM Used",
-
- StatusMultipleChoices: "Multiple Choices",
- StatusMovedPermanently: "Moved Permanently",
- StatusFound: "Found",
- StatusSeeOther: "See Other",
- StatusNotModified: "Not Modified",
- StatusUseProxy: "Use Proxy",
- StatusTemporaryRedirect: "Temporary Redirect",
- StatusPermanentRedirect: "Permanent Redirect",
-
- StatusBadRequest: "Bad Request",
- StatusUnauthorized: "Unauthorized",
- StatusPaymentRequired: "Payment Required",
- StatusForbidden: "Forbidden",
- StatusNotFound: "Not Found",
- StatusMethodNotAllowed: "Method Not Allowed",
- StatusNotAcceptable: "Not Acceptable",
- StatusProxyAuthRequired: "Proxy Authentication Required",
- StatusRequestTimeout: "Request Timeout",
- StatusConflict: "Conflict",
- StatusGone: "Gone",
- StatusLengthRequired: "Length Required",
- StatusPreconditionFailed: "Precondition Failed",
- StatusRequestEntityTooLarge: "Request Entity Too Large",
- StatusRequestURITooLong: "Request URI Too Long",
- StatusUnsupportedMediaType: "Unsupported Media Type",
- StatusRequestedRangeNotSatisfiable: "Requested Range Not Satisfiable",
- StatusExpectationFailed: "Expectation Failed",
- StatusTeapot: "I'm a teapot",
- StatusMisdirectedRequest: "Misdirected Request",
- StatusUnprocessableEntity: "Unprocessable Entity",
- StatusLocked: "Locked",
- StatusFailedDependency: "Failed Dependency",
- StatusTooEarly: "Too Early",
- StatusUpgradeRequired: "Upgrade Required",
- StatusPreconditionRequired: "Precondition Required",
- StatusTooManyRequests: "Too Many Requests",
- StatusRequestHeaderFieldsTooLarge: "Request Header Fields Too Large",
- StatusUnavailableForLegalReasons: "Unavailable For Legal Reasons",
-
- StatusInternalServerError: "Internal Server Error",
- StatusNotImplemented: "Not Implemented",
- StatusBadGateway: "Bad Gateway",
- StatusServiceUnavailable: "Service Unavailable",
- StatusGatewayTimeout: "Gateway Timeout",
- StatusHTTPVersionNotSupported: "HTTP Version Not Supported",
- StatusVariantAlsoNegotiates: "Variant Also Negotiates",
- StatusInsufficientStorage: "Insufficient Storage",
- StatusLoopDetected: "Loop Detected",
- StatusNotExtended: "Not Extended",
- StatusNetworkAuthenticationRequired: "Network Authentication Required",
-}
-
// StatusText returns a text for the HTTP status code. It returns the empty
// string if the code is unknown.
func StatusText(code int) string {
- return statusText[code]
+ switch code {
+ case StatusContinue:
+ return "Continue"
+ case StatusSwitchingProtocols:
+ return "Switching Protocols"
+ case StatusProcessing:
+ return "Processing"
+ case StatusEarlyHints:
+ return "Early Hints"
+ case StatusOK:
+ return "OK"
+ case StatusCreated:
+ return "Created"
+ case StatusAccepted:
+ return "Accepted"
+ case StatusNonAuthoritativeInfo:
+ return "Non-Authoritative Information"
+ case StatusNoContent:
+ return "No Content"
+ case StatusResetContent:
+ return "Reset Content"
+ case StatusPartialContent:
+ return "Partial Content"
+ case StatusMultiStatus:
+ return "Multi-Status"
+ case StatusAlreadyReported:
+ return "Already Reported"
+ case StatusIMUsed:
+ return "IM Used"
+ case StatusMultipleChoices:
+ return "Multiple Choices"
+ case StatusMovedPermanently:
+ return "Moved Permanently"
+ case StatusFound:
+ return "Found"
+ case StatusSeeOther:
+ return "See Other"
+ case StatusNotModified:
+ return "Not Modified"
+ case StatusUseProxy:
+ return "Use Proxy"
+ case StatusTemporaryRedirect:
+ return "Temporary Redirect"
+ case StatusPermanentRedirect:
+ return "Permanent Redirect"
+ case StatusBadRequest:
+ return "Bad Request"
+ case StatusUnauthorized:
+ return "Unauthorized"
+ case StatusPaymentRequired:
+ return "Payment Required"
+ case StatusForbidden:
+ return "Forbidden"
+ case StatusNotFound:
+ return "Not Found"
+ case StatusMethodNotAllowed:
+ return "Method Not Allowed"
+ case StatusNotAcceptable:
+ return "Not Acceptable"
+ case StatusProxyAuthRequired:
+ return "Proxy Authentication Required"
+ case StatusRequestTimeout:
+ return "Request Timeout"
+ case StatusConflict:
+ return "Conflict"
+ case StatusGone:
+ return "Gone"
+ case StatusLengthRequired:
+ return "Length Required"
+ case StatusPreconditionFailed:
+ return "Precondition Failed"
+ case StatusRequestEntityTooLarge:
+ return "Request Entity Too Large"
+ case StatusRequestURITooLong:
+ return "Request URI Too Long"
+ case StatusUnsupportedMediaType:
+ return "Unsupported Media Type"
+ case StatusRequestedRangeNotSatisfiable:
+ return "Requested Range Not Satisfiable"
+ case StatusExpectationFailed:
+ return "Expectation Failed"
+ case StatusTeapot:
+ return "I'm a teapot"
+ case StatusMisdirectedRequest:
+ return "Misdirected Request"
+ case StatusUnprocessableEntity:
+ return "Unprocessable Entity"
+ case StatusLocked:
+ return "Locked"
+ case StatusFailedDependency:
+ return "Failed Dependency"
+ case StatusTooEarly:
+ return "Too Early"
+ case StatusUpgradeRequired:
+ return "Upgrade Required"
+ case StatusPreconditionRequired:
+ return "Precondition Required"
+ case StatusTooManyRequests:
+ return "Too Many Requests"
+ case StatusRequestHeaderFieldsTooLarge:
+ return "Request Header Fields Too Large"
+ case StatusUnavailableForLegalReasons:
+ return "Unavailable For Legal Reasons"
+ case StatusInternalServerError:
+ return "Internal Server Error"
+ case StatusNotImplemented:
+ return "Not Implemented"
+ case StatusBadGateway:
+ return "Bad Gateway"
+ case StatusServiceUnavailable:
+ return "Service Unavailable"
+ case StatusGatewayTimeout:
+ return "Gateway Timeout"
+ case StatusHTTPVersionNotSupported:
+ return "HTTP Version Not Supported"
+ case StatusVariantAlsoNegotiates:
+ return "Variant Also Negotiates"
+ case StatusInsufficientStorage:
+ return "Insufficient Storage"
+ case StatusLoopDetected:
+ return "Loop Detected"
+ case StatusNotExtended:
+ return "Not Extended"
+ case StatusNetworkAuthenticationRequired:
+ return "Network Authentication Required"
+ default:
+ return ""
+ }
}