chi: Question: HTTP Status Code

How do you set the HTTP Status code to something other than 200? I have a simple test case below and I’m unable to change the HTTP Status code. It is always a 200 OK. I can render my own text(JSON) but this still does NOT set the HTTP Status code to 401!

package main
func routes() *chi.Mux {
	router := chi.NewRouter()
	router.Use(
		render.SetContentType(render.ContentTypeJSON),
		middleware.Logger,
		middleware.DefaultCompress,
		middleware.RedirectSlashes,
		middleware.Recoverer,
		middleware.RealIP,
	)
	router.Get("/test", test)
	return router
}

func test(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(401)
	http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
	render.Status(r, 401)
	render.Render(w, r, ErrInvalidRequest())
	return
}
type ErrResponse struct {
	Err            error `json:"-"` // low-level runtime error
	HTTPStatusCode int   `json:"-"` // http response status code

	StatusText string `json:"status"`          // user-level status message
	AppCode    int64  `json:"code,omitempty"`  // application-specific error code
	ErrorText  string `json:"error,omitempty"` // application-level error message, for debugging
}

func (e *ErrResponse) Render(w http.ResponseWriter, r *http.Request) error {
	render.Status(r, e.HTTPStatusCode)
	return nil
}

func ErrInvalidRequest() render.Renderer {
	return &ErrResponse{
		// Err:            err,
		HTTPStatusCode: 401,
		StatusText:     "Invalid request.",
		ErrorText:      "Invalid request.",
	}
}
func main() {
	router := routes()

	walkFunc := func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
		log.Printf("%s %s\n", method, route)
		return nil
	}
	if err := chi.Walk(router, walkFunc); err != nil {
		log.Panicf("Loggin err: %s\n", err.Error())
	}
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", cfg.SrvPort), router))
}

Results - The text is changed but NOT the HTTP status code

curl --request GET  --url http://localhost:8080/test -i
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Tue, 19 Feb 2019 16:56:46 GMT
Content-Length: 57

Unauthorized
{"status":401,"message":"Invalid request."}

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 18 (8 by maintainers)

Most upvoted comments

In chi (like many other Go stdlib compatible routers) you have to memorize the acronym of Header-Status-Payload (HSP) acronym (just like TopRightBottomLeft in CSS). To illustrate the problem take a look at following unit test: https://gist.github.com/piotrkubisa/4b99eab4257f729abce8db853966b155

@pkieltyka after some testing I have found that if I remove the middleware.DefaultCompress everything works as expected… it returns the 401 on all systems (Windows, Mac, & Linux). If I include the middleware.DefaultCompress than I get a 200 on Windows & Mac and 401 on Linux. I have not looked at the DefaultCompress middleware code to see what it is doing but it somehow appears to be the culprit.

@pkieltyka I would like to see your output as I installed GO on a completely separate laptop (MacBook Pro) and I’m still getting a 200 OK as the response.

 curl --request GET  --url http://localhost:3333/test -i
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Mon, 25 Feb 2019 21:22:50 GMT
Content-Length: 57

{"status":"Invalid request.","error":"Invalid request."}

The texting being rendered is correct but the actual status code is still 200 OK, unless I use a http.HandlerFunc to wrap the call to the test function.