Skip to content

Instantly share code, notes, and snippets.

@josue
Last active August 4, 2023 21:23
Show Gist options
  • Select an option

  • Save josue/7c70d7b1f3d0e374a465a0718ac82aff to your computer and use it in GitHub Desktop.

Select an option

Save josue/7c70d7b1f3d0e374a465a0718ac82aff to your computer and use it in GitHub Desktop.

Revisions

  1. josue revised this gist May 12, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion server.go
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,7 @@ go build for linux:
    env GOOS=linux go build -o /tmp/server server.go

    run with docker:
    docker run -it --rm --name test -v /tmp/server:/tmp/server -p 3000:80 -p 3001:6060 alpine /server
    docker run -it --rm --name test -v /tmp/server:/server -p 3000:80 -p 3001:6060 alpine /server

    run pprof debugger:
    go get github.com/google/pprof
  2. josue revised this gist May 12, 2018. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -1,13 +1,13 @@
    /*
    go build for linux:
    env GOOS=linux go build -o /tmp/server-linux server.go
    env GOOS=linux go build -o /tmp/server server.go

    run with docker:
    docker run -it --rm --name test -v /tmp:/app -p 3000:80 -p 3001:6060 -e SERVER_PORT=80 alpine /app/server-linux
    docker run -it --rm --name test -v /tmp/server:/tmp/server -p 3000:80 -p 3001:6060 alpine /server

    run pprof debugger:
    go get github.com/google/pprof
    pprof --seconds 30 -http=:4444 /tmp/server-linux http://localhost:3001/debug/pprof/profile
    pprof --seconds 30 -http=:4444 /tmp/server http://localhost:3001/debug/pprof/profile

    benchmarking with wrk:
    brew install wrk
    @@ -159,7 +159,7 @@ func initApiServer() {
    http.HandleFunc(route, errorHandler(routeHandler))
    }

    port := "3000" // default port
    port := "80" // default port
    if os.Getenv("SERVER_PORT") != "" {
    port = os.Getenv("SERVER_PORT")
    }
  3. josue revised this gist May 12, 2018. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -56,15 +56,18 @@ func routeHandler(w http.ResponseWriter, r *http.Request) error {
    }

    // route methods
    // root/index path
    func apiRoot(w http.ResponseWriter, r *http.Request) error {
    data := map[string]string{"hello": "welcome"}
    return outputJSON(w, data)
    }

    // simple health check
    func apiHealthz(w http.ResponseWriter, r *http.Request) error {
    data := map[string]interface{}{"alive": time.Now().Unix()}
    return outputJSON(w, data)
    }
    // simulate error with 1 second delay
    func apiError(w http.ResponseWriter, r *http.Request) error {
    defer timeTrack(time.Now(), "/error endpoint bug taking too long")
    time.Sleep(1 * time.Second)
  4. josue revised this gist May 12, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion server.go
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ import (
    "syscall"
    "time"

    _ "net/http/pprof" // NOTE: temp debugger
    _ "net/http/pprof"
    )

    // http routes
  5. josue revised this gist May 12, 2018. No changes.
  6. josue revised this gist May 12, 2018. 1 changed file with 35 additions and 4 deletions.
    39 changes: 35 additions & 4 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,19 @@
    /*
    go build for linux:
    env GOOS=linux go build -o /tmp/server-linux server.go

    run with docker:
    docker run -it --rm --name test -v /tmp:/app -p 3000:80 -p 3001:6060 -e SERVER_PORT=80 alpine /app/server-linux

    run pprof debugger:
    go get github.com/google/pprof
    pprof --seconds 30 -http=:4444 /tmp/server-linux http://localhost:3001/debug/pprof/profile

    benchmarking with wrk:
    brew install wrk
    wrk -d 5s http://localhost:3000/
    */

    package main

    import (
    @@ -9,6 +25,8 @@ import (
    "os/signal"
    "syscall"
    "time"

    _ "net/http/pprof" // NOTE: temp debugger
    )

    // http routes
    @@ -121,25 +139,38 @@ func initSignals() {
    signalHandler(<-captureSignal)
    }

    // initialize PPROF debugger
    func initPprofDebugger() {
    port := "6060" // default port
    if os.Getenv("PPROF_PORT") != "" {
    port = os.Getenv("PPROF_PORT")
    }
    log.Println("Running pprof debugger on :" + port)
    log.Println(fmt.Sprint(http.ListenAndServe(":"+port, nil).Error()))
    }

    // initialize server listener
    func initApiServer() {
    // initialize routes
    for route, _ := range routes {
    http.HandleFunc(route, errorHandler(routeHandler))
    }

    serverPort := "3000" // default port
    port := "3000" // default port
    if os.Getenv("SERVER_PORT") != "" {
    serverPort = os.Getenv("SERVER_PORT")
    port = os.Getenv("SERVER_PORT")
    }
    fmt.Println("Running api server on port :" + serverPort)
    err := http.ListenAndServe(":"+serverPort, nil)
    log.Println("Running api server on port :" + port)
    err := http.ListenAndServe(":"+port, nil)
    if err != nil {
    log.Printf("[Error] ListenAndServe: %v", err)
    }
    }

    func main() {
    // start PPROF debugger
    go initPprofDebugger()

    // capture signals
    go initSignals()

  7. josue revised this gist May 12, 2018. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -48,6 +48,7 @@ func apiHealthz(w http.ResponseWriter, r *http.Request) error {
    return outputJSON(w, data)
    }
    func apiError(w http.ResponseWriter, r *http.Request) error {
    defer timeTrack(time.Now(), "/error endpoint bug taking too long")
    time.Sleep(1 * time.Second)
    return fmt.Errorf("some error")
    }
    @@ -61,10 +62,10 @@ func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.Handler
    if err != nil {
    errMsg := fmt.Sprintf("{ \"error:\": \"%s\" }", err.Error())
    http.Error(w, errMsg, http.StatusInternalServerError)
    timeTrack(startTime, fmt.Sprintf("%d [Error] Path: %q -- err: %v", http.StatusInternalServerError, r.RequestURI, err))
    log.Printf("[latency: %s] %d Error - Path: %s -- err: %v", time.Since(startTime), http.StatusInternalServerError, r.RequestURI, err)
    return
    }
    timeTrack(startTime, fmt.Sprintf("%d [OK] Path: %s", http.StatusOK, r.RequestURI))
    log.Printf("[latency: %s] %d OK - Path: %s", time.Since(startTime), http.StatusOK, r.RequestURI)
    }
    }

  8. josue revised this gist May 12, 2018. 1 changed file with 17 additions and 5 deletions.
    22 changes: 17 additions & 5 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,7 @@
    package main

    import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    @@ -38,13 +39,13 @@ func routeHandler(w http.ResponseWriter, r *http.Request) error {

    // route methods
    func apiRoot(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprint(w, "{ \"test\": 123123 }")
    return nil
    data := map[string]string{"hello": "welcome"}
    return outputJSON(w, data)
    }

    func apiHealthz(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprintf(w, "{ \"alive:\": %d }", time.Now().Unix())
    return nil
    data := map[string]interface{}{"alive": time.Now().Unix()}
    return outputJSON(w, data)
    }
    func apiError(w http.ResponseWriter, r *http.Request) error {
    time.Sleep(1 * time.Second)
    @@ -67,6 +68,17 @@ func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.Handler
    }
    }

    // map to json string
    func outputJSON(w http.ResponseWriter, data interface{}) error {
    jsonString, err := json.Marshal(data)
    if err != nil {
    log.Fatalf("[Internal Error] Unable to stringify map argument, err: %v", err)
    return fmt.Errorf("[Internal Error] JSON data")
    }
    fmt.Fprint(w, string(jsonString))
    return nil
    }

    // time track
    func timeTrack(start time.Time, name string) {
    elapsed := time.Since(start)
    @@ -132,4 +144,4 @@ func main() {

    // start HTTP server
    initApiServer()
    }
    }
  9. josue revised this gist May 12, 2018. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion server.go
    Original file line number Diff line number Diff line change
    @@ -20,7 +20,6 @@ var routes = map[string]string{
    // handle route paths with methods
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    route, ok := routes[r.RequestURI]

    if !ok {
    return fmt.Errorf("Route %s path does not exist", r.RequestURI)
    }
  10. josue revised this gist May 12, 2018. 1 changed file with 54 additions and 36 deletions.
    90 changes: 54 additions & 36 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -10,6 +10,33 @@ import (
    "time"
    )

    // http routes
    var routes = map[string]string{
    "/": "apiRoot",
    "/healthz": "apiHealthz",
    "/error": "apiError",
    }

    // handle route paths with methods
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    route, ok := routes[r.RequestURI]

    if !ok {
    return fmt.Errorf("Route %s path does not exist", r.RequestURI)
    }

    switch route {
    case "apiRoot":
    return apiRoot(w, r)
    case "apiHealthz":
    return apiHealthz(w, r)
    case "apiError":
    return apiError(w, r)
    default:
    return fmt.Errorf("Route %s method not exist", r.RequestURI)
    }
    }

    // route methods
    func apiRoot(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprint(w, "{ \"test\": 123123 }")
    @@ -25,43 +52,28 @@ func apiError(w http.ResponseWriter, r *http.Request) error {
    return fmt.Errorf("some error")
    }

    // handle route paths with methods
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    defer timeTrack(time.Now(), "Path: " + r.RequestURI)

    switch r.RequestURI {
    case "/":
    return apiRoot(w, r)
    case "/healthz":
    return apiHealthz(w, r)
    case "/error":
    return apiError(w, r)
    }

    return nil
    }

    // time track
    func timeTrack(start time.Time, name string) {
    elapsed := time.Since(start)
    log.Printf("TimeTrack (%s) -> %s", elapsed, name)
    }

    // capture errors
    func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
    startTime := time.Now()
    w.Header().Set("Content-Type", "application/json")
    err := f(w, r)
    if err != nil {
    log.Printf("[Error] %q: %v", r.RequestURI, err)
    errMsg := fmt.Sprintf("{ \"error:\": \"%s\" }", err.Error())
    http.Error(w, errMsg, http.StatusInternalServerError)
    timeTrack(startTime, fmt.Sprintf("%d [Error] Path: %q -- err: %v", http.StatusInternalServerError, r.RequestURI, err))
    return
    }
    log.Printf("[OK] %q", r.RequestURI)
    timeTrack(startTime, fmt.Sprintf("%d [OK] Path: %s", http.StatusOK, r.RequestURI))
    }
    }

    // time track
    func timeTrack(start time.Time, name string) {
    elapsed := time.Since(start)
    log.Printf("TimeTrack (%s) -> %s", elapsed, name)
    }

    // signal handler
    func signalHandler(signal os.Signal) {
    fmt.Printf("\nCaught signal: %+v", signal)
    @@ -90,22 +102,20 @@ func signalHandler(signal os.Signal) {
    os.Exit(0)
    }

    func main() {
    // capture signals
    go func() {
    var captureSignal = make(chan os.Signal, 1)
    signal.Notify(captureSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGABRT)
    signalHandler(<-captureSignal)
    }()

    // http routes
    routes := []string{"/", "/healthz", "/error"}
    // initialize signal handler
    func initSignals() {
    var captureSignal = make(chan os.Signal, 1)
    signal.Notify(captureSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGABRT)
    signalHandler(<-captureSignal)
    }

    for _, route := range routes {
    // initialize server listener
    func initApiServer() {
    // initialize routes
    for route, _ := range routes {
    http.HandleFunc(route, errorHandler(routeHandler))
    }

    // start HTTP server
    serverPort := "3000" // default port
    if os.Getenv("SERVER_PORT") != "" {
    serverPort = os.Getenv("SERVER_PORT")
    @@ -115,4 +125,12 @@ func main() {
    if err != nil {
    log.Printf("[Error] ListenAndServe: %v", err)
    }
    }

    func main() {
    // capture signals
    go initSignals()

    // start HTTP server
    initApiServer()
    }
  11. josue revised this gist May 12, 2018. 1 changed file with 67 additions and 67 deletions.
    134 changes: 67 additions & 67 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -10,30 +10,55 @@ import (
    "time"
    )

    func main() {
    // capture signals
    go func() {
    var captureSignal = make(chan os.Signal, 1)
    signal.Notify(captureSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGABRT)
    signalHandler(<-captureSignal)
    }()
    // route methods
    func apiRoot(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprint(w, "{ \"test\": 123123 }")
    return nil
    }

    // http routes
    routes := []string{"/", "/healthz", "/error"}
    func apiHealthz(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprintf(w, "{ \"alive:\": %d }", time.Now().Unix())
    return nil
    }
    func apiError(w http.ResponseWriter, r *http.Request) error {
    time.Sleep(1 * time.Second)
    return fmt.Errorf("some error")
    }

    for _, route := range routes {
    http.HandleFunc(route, errorHandler(routeHandler))
    // handle route paths with methods
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    defer timeTrack(time.Now(), "Path: " + r.RequestURI)

    switch r.RequestURI {
    case "/":
    return apiRoot(w, r)
    case "/healthz":
    return apiHealthz(w, r)
    case "/error":
    return apiError(w, r)
    }

    return nil
    }

    // start HTTP server
    serverPort := "3000" // default port
    if os.Getenv("SERVER_PORT") != "" {
    serverPort = os.Getenv("SERVER_PORT")
    }
    fmt.Println("Running api server on port :" + serverPort)
    err := http.ListenAndServe(":"+serverPort, nil)
    if err != nil {
    log.Printf("[Error] ListenAndServe: %v", err)
    // time track
    func timeTrack(start time.Time, name string) {
    elapsed := time.Since(start)
    log.Printf("TimeTrack (%s) -> %s", elapsed, name)
    }

    // capture errors
    func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    err := f(w, r)
    if err != nil {
    log.Printf("[Error] %q: %v", r.RequestURI, err)
    errMsg := fmt.Sprintf("{ \"error:\": \"%s\" }", err.Error())
    http.Error(w, errMsg, http.StatusInternalServerError)
    return
    }
    log.Printf("[OK] %q", r.RequestURI)
    }
    }

    @@ -65,54 +90,29 @@ func signalHandler(signal os.Signal) {
    os.Exit(0)
    }

    // capture errors
    func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    err := f(w, r)
    if err != nil {
    log.Printf("[Error] %q: %v", r.RequestURI, err)
    errMsg := fmt.Sprintf("{ \"error:\": \"%s\" }", err.Error())
    http.Error(w, errMsg, http.StatusInternalServerError)
    return
    }
    log.Printf("[OK] %q", r.RequestURI)
    }
    }
    func main() {
    // capture signals
    go func() {
    var captureSignal = make(chan os.Signal, 1)
    signal.Notify(captureSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGABRT)
    signalHandler(<-captureSignal)
    }()

    // time track
    func TimeTrack(start time.Time, name string) {
    elapsed := time.Since(start)
    log.Printf("TimeTrack (%s) -> %s", elapsed, name)
    }
    // http routes
    routes := []string{"/", "/healthz", "/error"}

    // handle routes
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    defer TimeTrack(time.Now(), "Path: " + r.RequestURI)

    switch r.RequestURI {
    case "/":
    return apiRoot(w, r)
    case "/healthz":
    return apiHealthz(w, r)
    case "/error":
    return apiError(w, r)
    for _, route := range routes {
    http.HandleFunc(route, errorHandler(routeHandler))
    }

    return nil
    }

    // routes methods
    func apiRoot(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprint(w, "{ \"test\": 123123 }")
    return nil
    }

    func apiHealthz(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprintf(w, "{ \"alive:\": %d }", time.Now().Unix())
    return nil
    }
    func apiError(w http.ResponseWriter, r *http.Request) error {
    time.Sleep(1 * time.Second)
    return fmt.Errorf("some error")
    }
    // start HTTP server
    serverPort := "3000" // default port
    if os.Getenv("SERVER_PORT") != "" {
    serverPort = os.Getenv("SERVER_PORT")
    }
    fmt.Println("Running api server on port :" + serverPort)
    err := http.ListenAndServe(":"+serverPort, nil)
    if err != nil {
    log.Printf("[Error] ListenAndServe: %v", err)
    }
    }
  12. josue revised this gist May 11, 2018. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -88,8 +88,7 @@ func TimeTrack(start time.Time, name string) {

    // handle routes
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    startTime := time.Now()
    defer TimeTrack(startTime, "Path: " + r.RequestURI)
    defer TimeTrack(time.Now(), "Path: " + r.RequestURI)

    switch r.RequestURI {
    case "/":
    @@ -99,6 +98,7 @@ func routeHandler(w http.ResponseWriter, r *http.Request) error {
    case "/error":
    return apiError(w, r)
    }

    return nil
    }

    @@ -113,5 +113,6 @@ func apiHealthz(w http.ResponseWriter, r *http.Request) error {
    return nil
    }
    func apiError(w http.ResponseWriter, r *http.Request) error {
    time.Sleep(1 * time.Second)
    return fmt.Errorf("some error")
    }
  13. josue revised this gist May 11, 2018. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion server.go
    Original file line number Diff line number Diff line change
    @@ -88,7 +88,8 @@ func TimeTrack(start time.Time, name string) {

    // handle routes
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    defer TimeTrack(time.Now(), "Path: " + r.RequestURI)
    startTime := time.Now()
    defer TimeTrack(startTime, "Path: " + r.RequestURI)

    switch r.RequestURI {
    case "/":
  14. josue revised this gist May 11, 2018. 1 changed file with 7 additions and 2 deletions.
    9 changes: 7 additions & 2 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -80,10 +80,15 @@ func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.Handler
    }
    }

    // time track
    func TimeTrack(start time.Time, name string) {
    elapsed := time.Since(start)
    log.Printf("TimeTrack (%s) -> %s", elapsed, name)
    }

    // handle routes
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    start := time.Now()
    defer log.Printf("TimeTrack (%s) -> %s", time.Since(start), r.RequestURI)
    defer TimeTrack(time.Now(), "Path: " + r.RequestURI)

    switch r.RequestURI {
    case "/":
  15. josue revised this gist May 11, 2018. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -82,6 +82,9 @@ func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.Handler

    // handle routes
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    start := time.Now()
    defer log.Printf("TimeTrack (%s) -> %s", time.Since(start), r.RequestURI)

    switch r.RequestURI {
    case "/":
    return apiRoot(w, r)
  16. josue revised this gist May 4, 2018. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion server.go
    Original file line number Diff line number Diff line change
    @@ -31,7 +31,10 @@ func main() {
    serverPort = os.Getenv("SERVER_PORT")
    }
    fmt.Println("Running api server on port :" + serverPort)
    http.ListenAndServe(":"+serverPort, nil)
    err := http.ListenAndServe(":"+serverPort, nil)
    if err != nil {
    log.Printf("[Error] ListenAndServe: %v", err)
    }
    }

    // signal handler
  17. josue revised this gist May 4, 2018. 1 changed file with 12 additions and 12 deletions.
    24 changes: 12 additions & 12 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -26,12 +26,12 @@ func main() {
    }

    // start HTTP server
    SERVER_PORT := "3000" // default port
    serverPort := "3000" // default port
    if os.Getenv("SERVER_PORT") != "" {
    SERVER_PORT = os.Getenv("SERVER_PORT")
    serverPort = os.Getenv("SERVER_PORT")
    }
    fmt.Println("Running api server on port :" + SERVER_PORT)
    http.ListenAndServe(":"+SERVER_PORT, nil)
    fmt.Println("Running api server on port :" + serverPort)
    http.ListenAndServe(":"+serverPort, nil)
    }

    // signal handler
    @@ -69,8 +69,8 @@ func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.Handler
    err := f(w, r)
    if err != nil {
    log.Printf("[Error] %q: %v", r.RequestURI, err)
    err_msg := fmt.Sprintf("{ \"error:\": \"%s\" }", err.Error())
    http.Error(w, err_msg, http.StatusInternalServerError)
    errMsg := fmt.Sprintf("{ \"error:\": \"%s\" }", err.Error())
    http.Error(w, errMsg, http.StatusInternalServerError)
    return
    }
    log.Printf("[OK] %q", r.RequestURI)
    @@ -81,25 +81,25 @@ func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.Handler
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    switch r.RequestURI {
    case "/":
    return ApiRoot(w, r)
    return apiRoot(w, r)
    case "/healthz":
    return ApiHealthz(w, r)
    return apiHealthz(w, r)
    case "/error":
    return ApiError(w, r)
    return apiError(w, r)
    }
    return nil
    }

    // routes methods
    func ApiRoot(w http.ResponseWriter, r *http.Request) error {
    func apiRoot(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprint(w, "{ \"test\": 123123 }")
    return nil
    }

    func ApiHealthz(w http.ResponseWriter, r *http.Request) error {
    func apiHealthz(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprintf(w, "{ \"alive:\": %d }", time.Now().Unix())
    return nil
    }
    func ApiError(w http.ResponseWriter, r *http.Request) error {
    func apiError(w http.ResponseWriter, r *http.Request) error {
    return fmt.Errorf("some error")
    }
  18. josue revised this gist May 4, 2018. 1 changed file with 5 additions and 3 deletions.
    8 changes: 5 additions & 3 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -19,9 +19,11 @@ func main() {
    }()

    // http routes
    http.HandleFunc("/", errorHandler(routeHandler))
    http.HandleFunc("/healthz", errorHandler(routeHandler))
    http.HandleFunc("/error", errorHandler(routeHandler))
    routes := []string{"/", "/healthz", "/error"}

    for _, route := range routes {
    http.HandleFunc(route, errorHandler(routeHandler))
    }

    // start HTTP server
    SERVER_PORT := "3000" // default port
  19. josue created this gist May 4, 2018.
    103 changes: 103 additions & 0 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,103 @@
    package main

    import (
    "fmt"
    "log"
    "net/http"
    "os"
    "os/signal"
    "syscall"
    "time"
    )

    func main() {
    // capture signals
    go func() {
    var captureSignal = make(chan os.Signal, 1)
    signal.Notify(captureSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGABRT)
    signalHandler(<-captureSignal)
    }()

    // http routes
    http.HandleFunc("/", errorHandler(routeHandler))
    http.HandleFunc("/healthz", errorHandler(routeHandler))
    http.HandleFunc("/error", errorHandler(routeHandler))

    // start HTTP server
    SERVER_PORT := "3000" // default port
    if os.Getenv("SERVER_PORT") != "" {
    SERVER_PORT = os.Getenv("SERVER_PORT")
    }
    fmt.Println("Running api server on port :" + SERVER_PORT)
    http.ListenAndServe(":"+SERVER_PORT, nil)
    }

    // signal handler
    func signalHandler(signal os.Signal) {
    fmt.Printf("\nCaught signal: %+v", signal)
    fmt.Println("\nWait for 1 second to finish processing")
    time.Sleep(1 * time.Second)

    switch signal {

    case syscall.SIGHUP: // kill -SIGHUP XXXX
    fmt.Println("- got hungup")

    case syscall.SIGINT: // kill -SIGINT XXXX or Ctrl+c
    fmt.Println("- got ctrl+c")

    case syscall.SIGTERM: // kill -SIGTERM XXXX
    fmt.Println("- got force stop")

    case syscall.SIGQUIT: // kill -SIGQUIT XXXX
    fmt.Println("- stop and core dump")

    default:
    fmt.Println("- unknown signal")
    }

    fmt.Println("\nFinished server cleanup")
    os.Exit(0)
    }

    // capture errors
    func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    err := f(w, r)
    if err != nil {
    log.Printf("[Error] %q: %v", r.RequestURI, err)
    err_msg := fmt.Sprintf("{ \"error:\": \"%s\" }", err.Error())
    http.Error(w, err_msg, http.StatusInternalServerError)
    return
    }
    log.Printf("[OK] %q", r.RequestURI)
    }
    }

    // handle routes
    func routeHandler(w http.ResponseWriter, r *http.Request) error {
    switch r.RequestURI {
    case "/":
    return ApiRoot(w, r)
    case "/healthz":
    return ApiHealthz(w, r)
    case "/error":
    return ApiError(w, r)
    }
    return nil
    }

    // routes methods
    func ApiRoot(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprint(w, "{ \"test\": 123123 }")
    return nil
    }

    func ApiHealthz(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprintf(w, "{ \"alive:\": %d }", time.Now().Unix())
    return nil
    }
    func ApiError(w http.ResponseWriter, r *http.Request) error {
    return fmt.Errorf("some error")
    }