Skip to content

Commit

Permalink
[patch] fixed inifinite recursion issue (reported in issue #48)
Browse files Browse the repository at this point in the history
[patch] use one time marshaled json payload for static response
  • Loading branch information
bnkamalesh committed Apr 21, 2024
1 parent 4ee9d0e commit 9882f0c
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 27 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![](https://godoc.org/github.com/nathany/looper?status.svg)](http://godoc.org/github.com/bnkamalesh/webgo)
[![](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go#web-frameworks)

# WebGo v7.0.1
# WebGo v7.0.4

WebGo is a minimalistic router for [Go](https://golang.org) to build web applications (server side) with no 3rd party dependencies. WebGo will always be Go standard library compliant; with the HTTP handlers having the same signature as [http.HandlerFunc](https://golang.org/pkg/net/http/#HandlerFunc).

Expand Down
2 changes: 1 addition & 1 deletion config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestConfig_LoadInvalid(t *testing.T) {
cfg := &Config{}
cfg.Load("")
str := tl.out.String()
want := "open : no such file or directoryunexpected end of JSON inputPort number not provided or is invalid (should be between 0 - 65535)"
want := "open : no such file or directoryunexpected end of JSON inputport number not provided or is invalid (should be between 0 - 65535)"
got := str
if got != want {
t.Errorf(
Expand Down
4 changes: 2 additions & 2 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

var (
// ErrInvalidPort is the error returned when the port number provided in the config file is invalid
ErrInvalidPort = errors.New("Port number not provided or is invalid (should be between 0 - 65535)")
ErrInvalidPort = errors.New("port number not provided or is invalid (should be between 0 - 65535)")

lh *logHandler
)
Expand Down Expand Up @@ -71,7 +71,7 @@ func (lh *logHandler) Warn(data ...interface{}) {
lh.warn.Println(data...)
}

// Error prints log of severity 2
// Error prints log of severity 2
func (lh *logHandler) Error(data ...interface{}) {
if lh.err == nil {
return
Expand Down
34 changes: 20 additions & 14 deletions responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import (
"net/http"
)

var (
jsonErrPayload = []byte{}
)

// ErrorData used to render the error page
type ErrorData struct {
ErrCode int
Expand Down Expand Up @@ -69,29 +73,31 @@ func SendResponse(w http.ResponseWriter, data interface{}, rCode int) {
w = crwAsserter(w, rCode)
w.Header().Add(HeaderContentType, JSONContentType)
err := json.NewEncoder(w).Encode(dOutput{Data: data, Status: rCode})
if err != nil {
/*
In case of encoding error, send "internal server error" and
log the actual error.
*/
R500(w, ErrInternalServer)
LOGHANDLER.Error(err)
if err == nil {
return
}

// assuming the error was related to JSON encoding, so reattempting to respond
// with a static payload. This could still fail in case of network write or other error(s)
w = crwAsserter(w, http.StatusInternalServerError)
_, _ = w.Write(jsonErrPayload)
LOGHANDLER.Error(err)
}

// SendError is used to respond to any request with an error
func SendError(w http.ResponseWriter, data interface{}, rCode int) {
w = crwAsserter(w, rCode)
w.Header().Add(HeaderContentType, JSONContentType)
err := json.NewEncoder(w).Encode(errOutput{data, rCode})
if err != nil {
/*
In case of encoding error, send "internal server error" and
log the actual error.
*/
R500(w, ErrInternalServer)
LOGHANDLER.Error(err)
if err == nil {
return
}

// assuming the error was related to JSON encoding, so reattempting to respond
// with a static payload. This could still fail in case of network write or other error(s)
w = crwAsserter(w, http.StatusInternalServerError)
_, _ = w.Write(jsonErrPayload)
LOGHANDLER.Error(err)
}

// Render is used for rendering templates (HTML)
Expand Down
19 changes: 10 additions & 9 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package webgo
import (
"bufio"
"context"
"encoding/json"
"errors"
"fmt"
"net"
Expand All @@ -14,13 +15,21 @@ import (
// responsewriter used
type httpResponseWriter interface {
http.ResponseWriter
http.CloseNotifier //nolint
http.Flusher
http.Hijacker
http.Pusher
}

func init() {
var err error
jsonErrPayload, err = json.Marshal(errOutput{
Errors: ErrInternalServer,
Status: http.StatusInternalServerError,
})
if err != nil {
panic(err)
}

// ensure the custom response writer implements all the required functions
crw := &customResponseWriter{}
_ = httpResponseWriter(crw)
Expand Down Expand Up @@ -93,14 +102,6 @@ func (crw *customResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
return nil, nil, errors.New("unable to create hijacker")
}

// CloseNotify implements the http.CloseNotifier interface
func (crw *customResponseWriter) CloseNotify() <-chan bool { //nolint
if n, ok := crw.ResponseWriter.(http.CloseNotifier); ok { //nolint
return n.CloseNotify()
}
return nil
}

func (crw *customResponseWriter) Push(target string, opts *http.PushOptions) error {
if n, ok := crw.ResponseWriter.(http.Pusher); ok {
return n.Push(target, opts)
Expand Down

0 comments on commit 9882f0c

Please sign in to comment.