]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: optimize StatusText implementation
authorJoão Penteado <4219131+joaopenteado@users.noreply.github.com>
Tue, 30 Nov 2021 18:59:41 +0000 (18:59 +0000)
committerDamien Neil <dneil@google.com>
Fri, 15 Apr 2022 17:03:50 +0000 (17:03 +0000)
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>
src/net/http/response.go
src/net/http/server.go
src/net/http/status.go

index eb4cd9b0adbf0b4078014b30ec0f839d8b416699..755c6965575fd22323187ab38112b885b0e99a6d 100644 (file)
@@ -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 {
index 62bdf1695974e28f2683bb689b08e1bbf6c288f9..d44b0fb256577be0ec49ddc757803225c95a8b1e 100644 (file)
@@ -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)
        }
 }
index 286315f6395a8e5c89f6b2d835beea5543d80219..75fea0ca35ac81485f01c6a571922eb7b28e119a 100644 (file)
@@ -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 ""
+       }
 }