

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Still calibrating
click for more info
Not enough gems
Cost: 6 gems
1: Server
incomplete
2: Content Length
incomplete
3: Response
incomplete
4: Other Common Headers
incomplete
5: Handler
incomplete
6: Code Review
incomplete
7: Refactor
incomplete
This lesson's interactive features are locked, please to keep using them
I just want to point out a few of the ways I implemented some of this, and talk through some of the decisions. First the Serve and listen functions:
func Serve(port int, handler Handler) (*Server, error) {
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
return nil, err
}
s := &Server{
handler: handler,
listener: listener,
}
go s.listen()
return s, nil
}
func (s *Server) listen() {
for {
conn, err := s.listener.Accept()
if err != nil {
if s.closed.Load() {
return
}
log.Printf("Error accepting connection: %v", err)
continue
}
go s.handle(conn)
}
}
You'll notice they're very similar to our original TCP listener, with the added handler to actually handle and respond to the HTTP request. In fact, the interesting part is that handle method:
func (s *Server) handle(conn net.Conn) {
defer conn.Close()
req, err := request.RequestFromReader(conn)
if err != nil {
hErr := &HandlerError{
StatusCode: response.StatusCodeBadRequest,
Message: err.Error(),
}
hErr.Write(conn)
return
}
buf := bytes.NewBuffer([]byte{})
hErr := s.handler(buf, req)
if hErr != nil {
hErr.Write(conn)
return
}
b := buf.Bytes()
response.WriteStatusLine(conn, response.StatusCodeSuccess)
headers := response.GetDefaultHeaders(len(b))
response.WriteHeaders(conn, headers)
conn.Write(b)
return
}
Some interesting things to note:
net.Conn it implements both the io.Reader and io.Writer interfaces, so it works perfectly with our request.RequestFromReader and response.WriteX functions.*HandlerError and don't write to the io.Writer themselves, but in the event of success, they do write to the io.Writer themselves and don't return an error.