rs / rest-layer

REST Layer, Go (golang) REST API framework

Home Page: http://rest-layer.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bogus error line, when returning empty response on 204

Dragomir-Ivanov opened this issue · comments

When Prefer: return=minimal is used, rest-layer will return empty body with HTTP code of 204,
however this results in a bogus log line with following text:

Can't send response: http: request method or response status code does not allow body

Mental trace of the issue:
func itemPatch executes this statements:

status = 200
	if isNoContent(r) {
		item.Payload = nil
		status = 204
	}

thus making item.Payload = nil
However later down the pipeline in func FormatItem(...)(ctx context, body interface{}) we have:

	if skipBody {
		return ctx, nil
	}
	return ctx, i.Payload
}

If skipBody is not flagged, we are returning map[string]interface{}{nil} which is not the same as interface{}{nil}.
Then later we have func (s DefaultResponseSender) Send(...)

	w.WriteHeader(status)

	if body != nil {
		j, err := json.Marshal(body)
		if err != nil {
			w.WriteHeader(500)
			logErrorf(ctx, "Can't build response: %v", err)
			msg := fmt.Sprintf("Can't build response: %q", err.Error())
			w.Write([]byte(fmt.Sprintf("{\"code\": 500, \"msg\": \"%s\"}", msg)))
			return
		}
		if _, err = w.Write(j); err != nil {
			logErrorf(ctx, "Can't send response: %v", err)
		}
	}

Which checks the body iterface{}, and it is not nil but map[string]interface{}{nil}, so it proceeds with marshaling it to null string. Then on the w.Write().
But since Go's http package doesn't like we just wrote w.WriteHeader(status) of 204, it fails on that w.Write call with the error string Can't send response: http: request method or response status code does not allow body.

Will make a PR shortly.