We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Server

Click to play video

Congratulations! You made an HTTP request parser and, honestly, that's the hardest part of this course. But of course, we're not done yet. Now let's build the actual server interface that handles the requests and sends responses.

I Like Bun's Approach

In Bun (JavaScript, I know, sorry), they have a very simple server implementation that looks like this in code:

const server = Bun.serve({
  port: 8080,
  async fetch(req) {
    return new Response("Bun!");
  },
});

It's fairly similar to Go's http.ListenAndServe:

server := &http.Server{
    Addr: ":8080",
    Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Go!")
    }),
}
server.ListenAndServe()

We're going to follow a similar pattern, with a few differences that I'll point out as we get to them.

Assignment

In this step we'll be upgrading from a tcplistener to an actual httpserver! It will accept valid requests and send valid responses. That said, for now, no matter what request is sent, the response will always be the same.

  1. const port = 42069
    
    func main() {
        server, err := server.Serve(port)
        if err != nil {
            log.Fatalf("Error starting server: %v", err)
        }
        defer server.Close()
        log.Println("Server started on port", port)
    
        sigChan := make(chan os.Signal, 1)
        signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
        <-sigChan
        log.Println("Server gracefully stopped")
    }
    

    As you can see, we've settled on a server.Serve function. This is where all the magic happens. It accepts a port and starts handling requests that come in. In a future step we'll allow it to accept a handler function, but for now, we're going to hardcode the response.

    Notice the sigChan code. This is a common pattern in Go for gracefully shutting down a server. Because server.Serve returns immediately (it handles requests in the background in goroutines) if we exit main immediately, the server will just stop. We want to wait for a signal (like Ctrl+C) before we stop the server.

    • HTTP/1.1 200 OK
      Content-Type: text/plain
      Content-Length: 13
      
      Hello World!
      

      The body includes the trailing newline after Hello World!, so it's 13 bytes.

Run and submit the CLI tests with your server running.