1package fasthttp
2
3import (
4	"fmt"
5	"sync/atomic"
6)
7
8// HTTP status codes were stolen from net/http.
9const (
10	StatusContinue           = 100 // RFC 7231, 6.2.1
11	StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
12	StatusProcessing         = 102 // RFC 2518, 10.1
13
14	StatusOK                   = 200 // RFC 7231, 6.3.1
15	StatusCreated              = 201 // RFC 7231, 6.3.2
16	StatusAccepted             = 202 // RFC 7231, 6.3.3
17	StatusNonAuthoritativeInfo = 203 // RFC 7231, 6.3.4
18	StatusNoContent            = 204 // RFC 7231, 6.3.5
19	StatusResetContent         = 205 // RFC 7231, 6.3.6
20	StatusPartialContent       = 206 // RFC 7233, 4.1
21	StatusMultiStatus          = 207 // RFC 4918, 11.1
22	StatusAlreadyReported      = 208 // RFC 5842, 7.1
23	StatusIMUsed               = 226 // RFC 3229, 10.4.1
24
25	StatusMultipleChoices   = 300 // RFC 7231, 6.4.1
26	StatusMovedPermanently  = 301 // RFC 7231, 6.4.2
27	StatusFound             = 302 // RFC 7231, 6.4.3
28	StatusSeeOther          = 303 // RFC 7231, 6.4.4
29	StatusNotModified       = 304 // RFC 7232, 4.1
30	StatusUseProxy          = 305 // RFC 7231, 6.4.5
31	_                       = 306 // RFC 7231, 6.4.6 (Unused)
32	StatusTemporaryRedirect = 307 // RFC 7231, 6.4.7
33	StatusPermanentRedirect = 308 // RFC 7538, 3
34
35	StatusBadRequest                   = 400 // RFC 7231, 6.5.1
36	StatusUnauthorized                 = 401 // RFC 7235, 3.1
37	StatusPaymentRequired              = 402 // RFC 7231, 6.5.2
38	StatusForbidden                    = 403 // RFC 7231, 6.5.3
39	StatusNotFound                     = 404 // RFC 7231, 6.5.4
40	StatusMethodNotAllowed             = 405 // RFC 7231, 6.5.5
41	StatusNotAcceptable                = 406 // RFC 7231, 6.5.6
42	StatusProxyAuthRequired            = 407 // RFC 7235, 3.2
43	StatusRequestTimeout               = 408 // RFC 7231, 6.5.7
44	StatusConflict                     = 409 // RFC 7231, 6.5.8
45	StatusGone                         = 410 // RFC 7231, 6.5.9
46	StatusLengthRequired               = 411 // RFC 7231, 6.5.10
47	StatusPreconditionFailed           = 412 // RFC 7232, 4.2
48	StatusRequestEntityTooLarge        = 413 // RFC 7231, 6.5.11
49	StatusRequestURITooLong            = 414 // RFC 7231, 6.5.12
50	StatusUnsupportedMediaType         = 415 // RFC 7231, 6.5.13
51	StatusRequestedRangeNotSatisfiable = 416 // RFC 7233, 4.4
52	StatusExpectationFailed            = 417 // RFC 7231, 6.5.14
53	StatusTeapot                       = 418 // RFC 7168, 2.3.3
54	StatusUnprocessableEntity          = 422 // RFC 4918, 11.2
55	StatusLocked                       = 423 // RFC 4918, 11.3
56	StatusFailedDependency             = 424 // RFC 4918, 11.4
57	StatusUpgradeRequired              = 426 // RFC 7231, 6.5.15
58	StatusPreconditionRequired         = 428 // RFC 6585, 3
59	StatusTooManyRequests              = 429 // RFC 6585, 4
60	StatusRequestHeaderFieldsTooLarge  = 431 // RFC 6585, 5
61	StatusUnavailableForLegalReasons   = 451 // RFC 7725, 3
62
63	StatusInternalServerError           = 500 // RFC 7231, 6.6.1
64	StatusNotImplemented                = 501 // RFC 7231, 6.6.2
65	StatusBadGateway                    = 502 // RFC 7231, 6.6.3
66	StatusServiceUnavailable            = 503 // RFC 7231, 6.6.4
67	StatusGatewayTimeout                = 504 // RFC 7231, 6.6.5
68	StatusHTTPVersionNotSupported       = 505 // RFC 7231, 6.6.6
69	StatusVariantAlsoNegotiates         = 506 // RFC 2295, 8.1
70	StatusInsufficientStorage           = 507 // RFC 4918, 11.5
71	StatusLoopDetected                  = 508 // RFC 5842, 7.2
72	StatusNotExtended                   = 510 // RFC 2774, 7
73	StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6
74)
75
76var (
77	statusLines atomic.Value
78
79	statusMessages = map[int]string{
80		StatusContinue:           "Continue",
81		StatusSwitchingProtocols: "Switching Protocols",
82		StatusProcessing:         "Processing",
83
84		StatusOK:                   "OK",
85		StatusCreated:              "Created",
86		StatusAccepted:             "Accepted",
87		StatusNonAuthoritativeInfo: "Non-Authoritative Information",
88		StatusNoContent:            "No Content",
89		StatusResetContent:         "Reset Content",
90		StatusPartialContent:       "Partial Content",
91		StatusMultiStatus:          "Multi-Status",
92		StatusAlreadyReported:      "Already Reported",
93		StatusIMUsed:               "IM Used",
94
95		StatusMultipleChoices:   "Multiple Choices",
96		StatusMovedPermanently:  "Moved Permanently",
97		StatusFound:             "Found",
98		StatusSeeOther:          "See Other",
99		StatusNotModified:       "Not Modified",
100		StatusUseProxy:          "Use Proxy",
101		StatusTemporaryRedirect: "Temporary Redirect",
102		StatusPermanentRedirect: "Permanent Redirect",
103
104		StatusBadRequest:                   "Bad Request",
105		StatusUnauthorized:                 "Unauthorized",
106		StatusPaymentRequired:              "Payment Required",
107		StatusForbidden:                    "Forbidden",
108		StatusNotFound:                     "Not Found",
109		StatusMethodNotAllowed:             "Method Not Allowed",
110		StatusNotAcceptable:                "Not Acceptable",
111		StatusProxyAuthRequired:            "Proxy Authentication Required",
112		StatusRequestTimeout:               "Request Timeout",
113		StatusConflict:                     "Conflict",
114		StatusGone:                         "Gone",
115		StatusLengthRequired:               "Length Required",
116		StatusPreconditionFailed:           "Precondition Failed",
117		StatusRequestEntityTooLarge:        "Request Entity Too Large",
118		StatusRequestURITooLong:            "Request URI Too Long",
119		StatusUnsupportedMediaType:         "Unsupported Media Type",
120		StatusRequestedRangeNotSatisfiable: "Requested Range Not Satisfiable",
121		StatusExpectationFailed:            "Expectation Failed",
122		StatusTeapot:                       "I'm a teapot",
123		StatusUnprocessableEntity:          "Unprocessable Entity",
124		StatusLocked:                       "Locked",
125		StatusFailedDependency:             "Failed Dependency",
126		StatusUpgradeRequired:              "Upgrade Required",
127		StatusPreconditionRequired:         "Precondition Required",
128		StatusTooManyRequests:              "Too Many Requests",
129		StatusRequestHeaderFieldsTooLarge:  "Request Header Fields Too Large",
130		StatusUnavailableForLegalReasons:   "Unavailable For Legal Reasons",
131
132		StatusInternalServerError:           "Internal Server Error",
133		StatusNotImplemented:                "Not Implemented",
134		StatusBadGateway:                    "Bad Gateway",
135		StatusServiceUnavailable:            "Service Unavailable",
136		StatusGatewayTimeout:                "Gateway Timeout",
137		StatusHTTPVersionNotSupported:       "HTTP Version Not Supported",
138		StatusVariantAlsoNegotiates:         "Variant Also Negotiates",
139		StatusInsufficientStorage:           "Insufficient Storage",
140		StatusLoopDetected:                  "Loop Detected",
141		StatusNotExtended:                   "Not Extended",
142		StatusNetworkAuthenticationRequired: "Network Authentication Required",
143	}
144)
145
146// StatusMessage returns HTTP status message for the given status code.
147func StatusMessage(statusCode int) string {
148	s := statusMessages[statusCode]
149	if s == "" {
150		s = "Unknown Status Code"
151	}
152	return s
153}
154
155func init() {
156	statusLines.Store(make(map[int][]byte))
157}
158
159func statusLine(statusCode int) []byte {
160	m := statusLines.Load().(map[int][]byte)
161	h := m[statusCode]
162	if h != nil {
163		return h
164	}
165
166	statusText := StatusMessage(statusCode)
167
168	h = []byte(fmt.Sprintf("HTTP/1.1 %d %s\r\n", statusCode, statusText))
169	newM := make(map[int][]byte, len(m)+1)
170	for k, v := range m {
171		newM[k] = v
172	}
173	newM[statusCode] = h
174	statusLines.Store(newM)
175	return h
176}
177