Skip to content

Commit

Permalink
add response headers to all http responses (0xPolygonHermez#2829)
Browse files Browse the repository at this point in the history
  • Loading branch information
tclemos authored Nov 23, 2023
1 parent 6d8cd1e commit a66e1a8
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 24 deletions.
9 changes: 5 additions & 4 deletions jsonrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ func (s *Server) Stop() error {
}

func (s *Server) handle(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", contentType)
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")

if req.Method == http.MethodOptions {
return
}
Expand Down Expand Up @@ -249,10 +254,6 @@ func (s *Server) handle(w http.ResponseWriter, req *http.Request) {
defer s.decreaseHttpConnCounter()

start := time.Now()
w.Header().Set("Content-Type", contentType)
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
var respLen int
if single {
respLen = s.handleSingleRequest(req, w, data)
Expand Down
126 changes: 106 additions & 20 deletions jsonrpc/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,108 +333,190 @@ func TestBatchRequests(t *testing.T) {

func TestRequestValidation(t *testing.T) {
type testCase struct {
Name string
Method string
Content []byte
ContentType string
ExpectedStatusCode int
ExpectedMessage string
Name string
Method string
Content []byte
ContentType string
ExpectedStatusCode int
ExpectedResponseHeaders map[string][]string
ExpectedMessage string
}

testCases := []testCase{
{
Name: "OPTION request",
Method: http.MethodOptions,
ExpectedStatusCode: http.StatusOK,
ExpectedMessage: "",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"application/json"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "",
},
{
Name: "GET request",
Method: http.MethodGet,
ExpectedStatusCode: http.StatusOK,
ExpectedMessage: "zkEVM JSON RPC Server",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"application/json"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "zkEVM JSON RPC Server",
},
{
Name: "HEAD request",
Method: http.MethodHead,
ExpectedStatusCode: http.StatusMethodNotAllowed,
ExpectedMessage: "",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "",
},
{
Name: "PUT request",
Method: http.MethodPut,
ExpectedStatusCode: http.StatusMethodNotAllowed,
ExpectedMessage: "method PUT not allowed\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "method PUT not allowed\n",
},
{
Name: "PATCH request",
Method: http.MethodPatch,
ExpectedStatusCode: http.StatusMethodNotAllowed,
ExpectedMessage: "method PATCH not allowed\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "method PATCH not allowed\n",
},
{
Name: "DELETE request",
Method: http.MethodDelete,
ExpectedStatusCode: http.StatusMethodNotAllowed,
ExpectedMessage: "method DELETE not allowed\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "method DELETE not allowed\n",
},
{
Name: "CONNECT request",
Method: http.MethodConnect,
ExpectedStatusCode: http.StatusNotFound,
ExpectedMessage: "404 page not found\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
},
ExpectedMessage: "404 page not found\n",
},
{
Name: "TRACE request",
Method: http.MethodTrace,
ExpectedStatusCode: http.StatusMethodNotAllowed,
ExpectedMessage: "method TRACE not allowed\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "method TRACE not allowed\n",
},
{
Name: "Request content bigger than limit",
Method: http.MethodPost,
Content: make([]byte, maxRequestContentLength+1),
ExpectedStatusCode: http.StatusRequestEntityTooLarge,
ExpectedMessage: "content length too large (5242881>5242880)\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "content length too large (5242881>5242880)\n",
},
{
Name: "Invalid content type",
Method: http.MethodPost,
ContentType: "text/html",
ExpectedStatusCode: http.StatusUnsupportedMediaType,
ExpectedMessage: "invalid content type, only application/json is supported\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "invalid content type, only application/json is supported\n",
},
{
Name: "Empty request body",
Method: http.MethodPost,
ContentType: contentType,
Content: []byte(""),
ExpectedStatusCode: http.StatusBadRequest,
ExpectedMessage: "empty request body\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "empty request body\n",
},
{
Name: "Invalid json",
Method: http.MethodPost,
ContentType: contentType,
Content: []byte("this is not a json format string"),
ExpectedStatusCode: http.StatusBadRequest,
ExpectedMessage: "invalid json object request body\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "invalid json object request body\n",
},
{
Name: "Incomplete json object",
Method: http.MethodPost,
ContentType: contentType,
Content: []byte("{ \"field\":"),
ExpectedStatusCode: http.StatusBadRequest,
ExpectedMessage: "invalid json object request body\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "invalid json object request body\n",
},
{
Name: "Incomplete json array",
Method: http.MethodPost,
ContentType: contentType,
Content: []byte("[ { \"field\":"),
ExpectedStatusCode: http.StatusBadRequest,
ExpectedMessage: "invalid json array request body\n",
ExpectedResponseHeaders: map[string][]string{
"Content-Type": {"text/plain; charset=utf-8"},
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Methods": {"POST, OPTIONS"},
"Access-Control-Allow-Headers": {"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"},
},
ExpectedMessage: "invalid json array request body\n",
},
}

Expand All @@ -460,6 +542,10 @@ func TestRequestValidation(t *testing.T) {
message := string(resBody)
assert.Equal(t, tc.ExpectedStatusCode, httpRes.StatusCode)
assert.Equal(t, tc.ExpectedMessage, message)

for responseHeaderKey, responseHeaderValue := range tc.ExpectedResponseHeaders {
assert.ElementsMatch(t, httpRes.Header[responseHeaderKey], responseHeaderValue)
}
})
}
}
Expand Down

0 comments on commit a66e1a8

Please sign in to comment.