/
main.go
104 lines (83 loc) · 2.03 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package main
import (
"bytes"
"fmt"
"io"
"net"
"strconv"
"github.com/belljustin/jserver/request"
"github.com/belljustin/jserver/response"
)
const (
HOST = "localhost"
PORT = 9090
)
func main() {
listen := fmt.Sprintf("%s:%d", HOST, PORT)
ln, err := net.Listen("tcp", listen)
if err != nil {
// TODO: handle error
fmt.Println(err)
}
fmt.Printf("Accepting connections on %s\n", listen)
for {
conn, err := ln.Accept()
if err != nil {
// TODO: handle error
fmt.Println(err)
}
go handleConnection(conn, echoHandler)
}
}
func handleConnection(conn net.Conn, handle handler) {
defer conn.Close()
fmt.Println("Handling connection")
buf, bodyBuf := readHeader(conn)
req := request.ParseRequest(buf, bodyBuf)
fmt.Printf("%+v\n", req)
// If request is POST, use Content-Length header to read rest of request
if req.Method == "POST" {
n, found := req.Headers["Content-Length"]
if !found {
panic("No Content-Length for POST request")
}
m, _ := strconv.Atoi(n) // TODO: handle error
tmp := make([]byte, (m+1)-bodyBuf.Len())
conn.Read(tmp) // TODO: handle error
bodyBuf.Write(tmp)
}
res := handle(req)
conn.Write(res.Bytes())
}
func readHeader(r io.Reader) (headerBuf bytes.Buffer, bodyBuf bytes.Buffer) {
tmp := make([]byte, 256)
// delim CRLF CRLF marks end of request line and headers
delim := [...]byte{'\r', '\n', '\r', '\n'}
i := 0
for {
n, _ := r.Read(tmp)
for m, b := range tmp {
// increment the counter if the next delim is found
if b == delim[i] {
i += 1
} else {
i = 0
}
// if entire delim is found, write part before to headerBuf and
// the rest to the body buffer
if i == len(delim) {
headerBuf.Write(tmp[:m])
bodyBuf.Write(tmp[m:n])
return headerBuf, bodyBuf
}
}
headerBuf.Write(tmp[:n])
}
return headerBuf, bodyBuf
}
// Hanlders
type handler func(*request.Request) *response.Response
func echoHandler(req *request.Request) *response.Response {
headers := make(map[string]string)
return response.NewResponse(200, headers, req.Body)
}