mirror of
https://github.com/cupcakearmy/codecrafters-http-server-go.git
synced 2024-12-22 08:06:27 +00:00
cleanup
This commit is contained in:
parent
899f7828a5
commit
de8a68ac05
@ -5,7 +5,7 @@ import (
|
|||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
)
|
)
|
||||||
|
|
||||||
func gzipCompress(data []byte) *bytes.Buffer {
|
func gzipCompress(data []byte) []byte {
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
gz := gzip.NewWriter(buf)
|
gz := gzip.NewWriter(buf)
|
||||||
if _, err := gz.Write(data); err != nil {
|
if _, err := gz.Write(data); err != nil {
|
||||||
@ -14,7 +14,5 @@ func gzipCompress(data []byte) *bytes.Buffer {
|
|||||||
if err := gz.Close(); err != nil {
|
if err := gz.Close(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
return buf.Bytes()
|
||||||
// fmt.Println("Hexadecimal Representation:", hex.EncodeToString(buf.Bytes()))
|
|
||||||
return buf
|
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@ import (
|
|||||||
var DIR string = ""
|
var DIR string = ""
|
||||||
|
|
||||||
func getFilepath(filename string) string {
|
func getFilepath(filename string) string {
|
||||||
|
// Set the DIR if not already set
|
||||||
if DIR == "" {
|
if DIR == "" {
|
||||||
|
|
||||||
if len(os.Args) != 3 {
|
if len(os.Args) != 3 {
|
||||||
log.Fatal("Not enough args")
|
log.Fatal("Not enough args")
|
||||||
}
|
}
|
||||||
|
34
app/http.go
34
app/http.go
@ -13,10 +13,6 @@ const (
|
|||||||
HTTPDelimiter = "\r\n"
|
HTTPDelimiter = "\r\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
// type Header struct {
|
|
||||||
// Name string
|
|
||||||
// Value string
|
|
||||||
// }
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Method string
|
Method string
|
||||||
Path string
|
Path string
|
||||||
@ -64,37 +60,44 @@ type Routes struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Respond(conn net.Conn, req Request, res Response) {
|
func Respond(conn net.Conn, req Request, res Response) {
|
||||||
|
// Create headers if not existent
|
||||||
if res.Headers == nil {
|
if res.Headers == nil {
|
||||||
res.Headers = make(map[string]string)
|
res.Headers = make(map[string]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isGzip := false
|
// Base response line
|
||||||
isGzip := strings.Contains(req.Headers["Accept-Encoding"], "gzip")
|
|
||||||
// if isGzip {
|
|
||||||
// res.Headers["Content-Encoding"] = "gzip"
|
|
||||||
// }
|
|
||||||
|
|
||||||
fmt.Fprintf(conn, "%s %d %s%s", res.Version, res.Code.Code, res.Code.Message, HTTPDelimiter)
|
fmt.Fprintf(conn, "%s %d %s%s", res.Version, res.Code.Code, res.Code.Message, HTTPDelimiter)
|
||||||
|
|
||||||
var body []byte
|
var body []byte
|
||||||
if res.Body != "" {
|
if res.Body != "" {
|
||||||
body = []byte(res.Body)
|
body = []byte(res.Body)
|
||||||
} else {
|
} else {
|
||||||
body = res.BodyRaw
|
body = res.BodyRaw
|
||||||
}
|
}
|
||||||
if isGzip && len(body) > 0 {
|
|
||||||
res.Headers["Content-Encoding"] = "gzip"
|
|
||||||
body = gzipCompress(body).Bytes()
|
|
||||||
}
|
|
||||||
bodySize := len(body)
|
bodySize := len(body)
|
||||||
|
|
||||||
|
// Check if gzip is accepted and encode the body
|
||||||
|
isGzip := strings.Contains(req.Headers["Accept-Encoding"], "gzip")
|
||||||
|
if isGzip && bodySize > 0 {
|
||||||
|
body = gzipCompress(body)
|
||||||
|
bodySize = len(body)
|
||||||
|
res.Headers["Content-Encoding"] = "gzip"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the size of the content
|
||||||
if bodySize > 0 {
|
if bodySize > 0 {
|
||||||
res.Headers["Content-Length"] = strconv.Itoa(bodySize)
|
res.Headers["Content-Length"] = strconv.Itoa(bodySize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write headers
|
||||||
for header, value := range res.Headers {
|
for header, value := range res.Headers {
|
||||||
fmt.Fprintf(conn, "%s: %s%s", header, value, HTTPDelimiter)
|
fmt.Fprintf(conn, "%s: %s%s", header, value, HTTPDelimiter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delimiter for the body, always present
|
||||||
fmt.Fprint(conn, HTTPDelimiter)
|
fmt.Fprint(conn, HTTPDelimiter)
|
||||||
|
|
||||||
|
// Write body if available
|
||||||
if bodySize > 0 {
|
if bodySize > 0 {
|
||||||
conn.Write(body)
|
conn.Write(body)
|
||||||
}
|
}
|
||||||
@ -112,6 +115,7 @@ func parseRequest(conn net.Conn) (Request, bool) {
|
|||||||
request := Request{Headers: map[string]string{}}
|
request := Request{Headers: map[string]string{}}
|
||||||
isBody := false
|
isBody := false
|
||||||
for i, part := range parts {
|
for i, part := range parts {
|
||||||
|
// The first part is always the basic information
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
head := strings.Split(part, " ")
|
head := strings.Split(part, " ")
|
||||||
if len(head) != 3 {
|
if len(head) != 3 {
|
||||||
@ -123,6 +127,7 @@ func parseRequest(conn net.Conn) (Request, bool) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Body
|
||||||
if isBody {
|
if isBody {
|
||||||
request.Body = part
|
request.Body = part
|
||||||
break
|
break
|
||||||
@ -130,6 +135,7 @@ func parseRequest(conn net.Conn) (Request, bool) {
|
|||||||
|
|
||||||
// Headers
|
// Headers
|
||||||
if part == "" {
|
if part == "" {
|
||||||
|
// If the header is "empty" it means that we have arrived at the body, and we'll skip to it
|
||||||
isBody = true
|
isBody = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ var routes = Routes{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Read file
|
||||||
{
|
{
|
||||||
regex: regexp.MustCompile(`^/files/([A-Za-z0-9_\-.]+)`),
|
regex: regexp.MustCompile(`^/files/([A-Za-z0-9_\-.]+)`),
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@ -60,6 +61,7 @@ var routes = Routes{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Write file
|
||||||
{
|
{
|
||||||
regex: regexp.MustCompile(`^/files/([A-Za-z0-9_\-.]+)`),
|
regex: regexp.MustCompile(`^/files/([A-Za-z0-9_\-.]+)`),
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -6,17 +6,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// type Handler = func(req Request, res Response)
|
|
||||||
// type Middleware = func(next Handler) Handler
|
|
||||||
|
|
||||||
// var m Middleware = func(next Handler) Handler {
|
|
||||||
// return func(req Request, res Response) {
|
|
||||||
// fmt.Println("Start")
|
|
||||||
// next(req, res)
|
|
||||||
// fmt.Println("End")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
func handleConnection(conn net.Conn, routes Routes) {
|
func handleConnection(conn net.Conn, routes Routes) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
@ -28,6 +17,7 @@ func handleConnection(conn net.Conn, routes Routes) {
|
|||||||
|
|
||||||
fmt.Println(req)
|
fmt.Println(req)
|
||||||
|
|
||||||
|
// Loop over the available routes. First string, then regexp
|
||||||
for _, route := range routes.stringRoutes {
|
for _, route := range routes.stringRoutes {
|
||||||
if req.Path == route.path && req.Method == route.method {
|
if req.Path == route.path && req.Method == route.method {
|
||||||
Respond(conn, req, route.handler(req))
|
Respond(conn, req, route.handler(req))
|
||||||
@ -45,12 +35,11 @@ func handleConnection(conn net.Conn, routes Routes) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Catch all 404
|
||||||
Respond(conn, req, Response{Version: req.Version, Code: NotFound})
|
Respond(conn, req, Response{Version: req.Version, Code: NotFound})
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("Logs from your program will appear here!")
|
|
||||||
|
|
||||||
l, err := net.Listen("tcp", "0.0.0.0:4221")
|
l, err := net.Listen("tcp", "0.0.0.0:4221")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Failed to bind to port 4221")
|
fmt.Println("Failed to bind to port 4221")
|
||||||
|
@ -38,8 +38,11 @@ func checkResponse(t *testing.T, res *http.Response, expected Expected) {
|
|||||||
t.Errorf(`Expected body to be "%s" but got "%s"`, expected.body, body)
|
t.Errorf(`Expected body to be "%s" but got "%s"`, expected.body, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Println("HEADERS", res.Header)
|
||||||
for header, value := range expected.headers {
|
for header, value := range expected.headers {
|
||||||
if actual := res.Header[header][0]; actual != value {
|
if res.Header[header] == nil {
|
||||||
|
t.Errorf(`Expected "%s" header to be present`, header)
|
||||||
|
} else if actual := res.Header[header][0]; actual != value {
|
||||||
t.Errorf(`Expected "%s" header to be "%s" but got "%s"`, header, value, actual)
|
t.Errorf(`Expected "%s" header to be "%s" but got "%s"`, header, value, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,23 +67,24 @@ func TestEcho(t *testing.T) {
|
|||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
|
||||||
// func TestEchoGzip(t *testing.T) {
|
func TestEchoGzip(t *testing.T) {
|
||||||
// input := "abc"
|
input := "abc"
|
||||||
// req, _ := http.NewRequest("GET", fmt.Sprintf("http://localhost:4221/echo/%s", input), nil)
|
req, _ := http.NewRequest("GET", fmt.Sprintf("http://localhost:4221/echo/%s", input), nil)
|
||||||
// req.Header.Set("Accept-Encoding", "gzip")
|
req.Header.Set("Accept-Encoding", "gzip")
|
||||||
// client := &http.Client{}
|
client := &http.Client{}
|
||||||
// res, _ := client.Do(req)
|
res, _ := client.Do(req)
|
||||||
|
|
||||||
// checkResponse(t, res, Expected{status: 200, body: input, headers: map[string]string{
|
checkResponse(t, res, Expected{status: 200, body: input, headers: map[string]string{
|
||||||
// "Content-Length": strconv.Itoa(len(input)),
|
"Content-Length": "27", // Size of gzip "abc"
|
||||||
// "Content-Type": "text/plain",
|
"Content-Type": "text/plain",
|
||||||
// "Content-Encoding": "gzip",
|
"Content-Encoding": "gzip",
|
||||||
// }})
|
}})
|
||||||
// }
|
}
|
||||||
|
|
||||||
func TestUserAgent(t *testing.T) {
|
func TestUserAgent(t *testing.T) {
|
||||||
input := "CodeCrafters/1.0"
|
input := "CodeCrafters/1.0"
|
||||||
req, _ := http.NewRequest("GET", "http://localhost:4221/user-agent", nil)
|
req, _ := http.NewRequest("GET", "http://localhost:4221/user-agent", nil)
|
||||||
|
req.Header.Del("")
|
||||||
req.Header.Set("User-Agent", input)
|
req.Header.Set("User-Agent", input)
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
res, _ := client.Do(req)
|
res, _ := client.Do(req)
|
||||||
|
Loading…
Reference in New Issue
Block a user