AnkurS
AnkurS

Reputation: 243

How to write a simple custom HTTP server in Go?

I am new to Go and trying to write a custom HTTP server. I'm getting a compilation error. How can I implement the ServeHTTP method in my code?

My Code:

package main

import (
    "net/http"
    "fmt"
    "io"
    "time"
)


func myHandler(w http.ResponseWriter, req *http.Request) {
    io.WriteString(w, "hello, world!\n")
}


func main() {
    // Custom http server
    s := &http.Server{
        Addr:           ":8080",
        Handler:        myHandler,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    err := s.ListenAndServe()
    if err != nil {
        fmt.Printf("Server failed: ", err.Error())
    }
}

Error while compiling:

.\hello.go:21: cannot use myHandler (type func(http.ResponseWriter, *http.Request)) as type http.Handler in field value:
    func(http.ResponseWriter, *http.Request) does not implement http.Handler (missing ServeHTTP method)

Upvotes: 24

Views: 14498

Answers (3)

Zuko
Zuko

Reputation: 2914

You could also define a mux and add handlers to it before assigning it to the server like below.

func myHandler(w http.ResponseWriter, req *http.Request) {
   io.WriteString(w, "hello, world!\n")
}

func main(){

   // define a serveMux to handle routes
   mux := http.NewServeMux()
   // assign a route/todo to a handler myHandler
   mux.HandleFunc("/todo", myHandler)

   // assign a route/todo/notes to an anonymous func
   mux.HandleFunc("/todo/notes", func(w http.ResponseWriter, req *http.Request) {
       w.Write([]byte("Hello again."))
   })

   s := &http.Server{
      Addr:           ":8080",
      Handler:        mux,
      ReadTimeout:    10 * time.Second,
      WriteTimeout:   10 * time.Second,
      MaxHeaderBytes: 1 << 20,
   }

   if err := s.ListenAndServe(); err != nil {
      log.Fatalf("server failed to start with error %v", err.Error())
   }
}

Upvotes: 5

OneOfOne
OneOfOne

Reputation: 99361

You either use a struct and define ServeHTTP on it or simply wrap your function in a HandlerFunc

s := &http.Server{
    Addr:           ":8080",
    Handler:        http.HandlerFunc(myHandler),
    ReadTimeout:    10 * time.Second,
    WriteTimeout:   10 * time.Second,
    MaxHeaderBytes: 1 << 20,
}

Upvotes: 24

pyk
pyk

Reputation: 203

in order to work properly, myHandler should be an object that satisfy the Handler Interface, in other words myHandler should have method called ServeHTTP.

For example, let's say that myHandler is custom handler for showing the current time. The code should be like this

package main

import (
    "fmt"
    "net/http"
    "time"
)

type timeHandler struct {
    zone *time.Location
}

func (th *timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    tm := time.Now().In(th.zone).Format(time.RFC1123)
    w.Write([]byte("The time is: " + tm))
}

func newTimeHandler(name string) *timeHandler {
    return &timeHandler{zone: time.FixedZone(name, 0)}
}

func main() {

    myHandler := newTimeHandler("EST")
    //Custom http server
    s := &http.Server{
        Addr:           ":8080",
        Handler:        myHandler,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    err := s.ListenAndServe()
    if err != nil {
        fmt.Printf("Server failed: ", err.Error())
    }
}

run this code and access http://localhost:8080/ in your browser. you should see formatted text like this

The time is: Sat, 30 Aug 2014 18:19:46 EST

(you should see different time.)

hope this help,

Further more reading

A Recap of Request Handling in Go

Upvotes: 6

Related Questions