diff --git a/context.go b/context.go index 85a0a9a..8a9b53f 100644 --- a/context.go +++ b/context.go @@ -53,7 +53,7 @@ func (ctx *context) Next() error { // Redirects the client to a different location with the specified status code. func (ctx *context) Redirect(status int, location string) error { ctx.response.SetStatus(status) - ctx.response.SetHeader("Location", location) + ctx.response.SetHeader(HeaderLocation, location) return nil } diff --git a/header.go b/header.go index ae86680..4d73350 100644 --- a/header.go +++ b/header.go @@ -1,6 +1,63 @@ package web +// Header represents an HTTP header with key and value type Header struct { Key string Value string } + +// Common HTTP header keys +const ( + HeaderContentType = "Content-Type" + HeaderContentLength = "Content-Length" + HeaderHost = "Host" + HeaderAccept = "Accept" + HeaderUserAgent = "User-Agent" + HeaderAcceptEncoding = "Accept-Encoding" + HeaderAcceptLanguage = "Accept-Language" + HeaderConnection = "Connection" + HeaderCookie = "Cookie" + HeaderSetCookie = "Set-Cookie" + HeaderLocation = "Location" + HeaderAuthorization = "Authorization" + HeaderCacheControl = "Cache-Control" + HeaderOrigin = "Origin" + HeaderReferer = "Referer" + HeaderTransferEncoding = "Transfer-Encoding" +) + +// Pre-allocated common headers +var ( + // Content type headers + HeaderContentTypeJSON = Header{Key: HeaderContentType, Value: "application/json"} + HeaderContentTypeHTML = Header{Key: HeaderContentType, Value: "text/html"} + HeaderContentTypePlain = Header{Key: HeaderContentType, Value: "text/plain"} + HeaderContentTypeXML = Header{Key: HeaderContentType, Value: "application/xml"} + HeaderContentTypeForm = Header{Key: HeaderContentType, Value: "application/x-www-form-urlencoded"} + HeaderContentTypeMultipart = Header{Key: HeaderContentType, Value: "multipart/form-data"} + + // Connection headers + HeaderConnectionClose = Header{Key: HeaderConnection, Value: "close"} + HeaderConnectionKeepAlive = Header{Key: HeaderConnection, Value: "keep-alive"} +) + +// FindHeader looks for a header by key in a slice of headers +func FindHeader(headers []Header, key string) (string, bool) { + for _, h := range headers { + if h.Key == key { + return h.Value, true + } + } + return "", false +} + +// SetHeader sets a header value in a slice of headers +func SetHeader(headers *[]Header, key string, value string) { + for i, h := range *headers { + if h.Key == key { + (*headers)[i].Value = value + return + } + } + *headers = append(*headers, Header{Key: key, Value: value}) +} diff --git a/request.go b/request.go index a57272f..b0dcccb 100644 --- a/request.go +++ b/request.go @@ -32,13 +32,8 @@ type request struct { // Returns the header value for the given key. func (req *request) Header(key string) string { - for _, header := range req.headers { - if header.Key == key { - return header.Value - } - } - - return "" + value, _ := FindHeader(req.headers, key) + return value } // Returns the requested host. diff --git a/response.go b/response.go index c1ae09d..d15c1f0 100644 --- a/response.go +++ b/response.go @@ -28,25 +28,13 @@ func (res *response) Body() []byte { // Returns the header value for the given key. func (res *response) Header(key string) string { - for _, header := range res.headers { - if header.Key == key { - return header.Value - } - } - - return "" + value, _ := FindHeader(res.headers, key) + return value } // Sets the header value for the given key. func (res *response) SetHeader(key string, value string) { - for i, header := range res.headers { - if header.Key == key { - res.headers[i].Value = value - return - } - } - - res.headers = append(res.headers, Header{Key: key, Value: value}) + SetHeader(&res.headers, key, value) } // Replaces the response body with the new contents. diff --git a/server.go b/server.go index 1025c6a..fafe28e 100644 --- a/server.go +++ b/server.go @@ -210,7 +210,7 @@ func (s *server) handleConnection(conn net.Conn) { } // Read the body, if any - if contentLength := ctx.request.Header("Content-Length"); contentLength != "" { + if contentLength := ctx.request.Header(HeaderContentLength); contentLength != "" { length, _ := strconv.Atoi(contentLength) ctx.request.body = make([]byte, length) ctx.reader.Read(ctx.request.body) @@ -244,7 +244,7 @@ func (s *server) handleRequest(ctx *context, method string, url string, writer i tmp := bytes.Buffer{} tmp.WriteString("HTTP/1.1 ") tmp.WriteString(strconv.Itoa(int(ctx.status))) - tmp.WriteString("\r\nContent-Length: ") + tmp.WriteString("\r\n" + HeaderContentLength + ": ") tmp.WriteString(strconv.Itoa(len(ctx.response.body))) tmp.WriteString("\r\n")