Search code examples
reactjsgomux

How to serve React


I have a simple React application I would like to serve from my Go server back end. I hear the process is similar to serving a static html file, but I just can't seem to get it to work.

When I try to view the app on the browser it says "This page isn't working" and that "localhost has redirected too many times"

Here is the code where I am running the server locally as well as trying to handle the react application

func main() {

r := mux.NewRouter()

// handle app
buildHandler := http.FileServer(http.Dir("./client/build/index.html"))
r.PathPrefix("/").Handler(buildHandler)

staticHandler := http.StripPrefix("/static/", http.FileServer(http.Dir("./client/build/static")))
r.PathPrefix("/static/").Handler(staticHandler)

r.HandleFunc("/", index).Methods("GET")

srv := &http.Server{
    Handler:      r,
    Addr:         "127.0.0.1:8080",
    WriteTimeout: 15 * time.Second,
    ReadTimeout:  15 * time.Second,
}

// serve
fmt.Println("Server started on PORT 8080")
log.Fatal(srv.ListenAndServe())


}

Here is the code for the index route

func index(w http.ResponseWriter, r *http.Request) {
    // not sure if this is necessary
    http.ServeFile(w, r, "index.html")
}

I believe the solution is simple and that I am most likely making a small error somewhere.


Solution

  • In your case only build handler is needed. It must point to directory not a file. Rest of the handlers are obsolete except the case of routing.

    package main
    
    import (
        "fmt"
        "github.com/gorilla/mux"
        "log"
        "net/http"
        "time"
    )
    
    func main() {
    
        r := mux.NewRouter()
    
        r.HandleFunc("/route1", index).Methods("GET")
        r.HandleFunc("/route2", index).Methods("GET")
        buildHandler := http.FileServer(http.Dir("client/build"))
        r.PathPrefix("/").Handler(buildHandler)
    
        srv := &http.Server{
            Handler:      r,
            Addr:         "127.0.0.1:8080",
            WriteTimeout: 15 * time.Second,
            ReadTimeout:  15 * time.Second,
        }
    
        fmt.Println("Server started on PORT 8080")
        log.Fatal(srv.ListenAndServe())
    
    }
    
    func index(w http.ResponseWriter, r *http.Request) {
        http.ServeFile(w, r, "client/build/index.html")
    }
    

    The same can be achieved with the standard library only.

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "time"
    )
    
    func main() {
    
        r := http.NewServeMux()
    
        r.HandleFunc("/route1", index)
        r.HandleFunc("/route2", index)
        buildHandler := http.FileServer(http.Dir("client/build"))
        r.Handle("/", buildHandler)
    
        srv := &http.Server{
            Handler:      r,
            Addr:         "127.0.0.1:8080",
            WriteTimeout: 15 * time.Second,
            ReadTimeout:  15 * time.Second,
        }
    
        fmt.Println("Server started on PORT 8080")
        log.Fatal(srv.ListenAndServe())
    
    }
    
    func index(w http.ResponseWriter, r *http.Request) {
        http.ServeFile(w, r, "client/build/index.html")
    }