rpc: minor cleanups to RPC PR
This commit is contained in:
		
							
								
								
									
										32
									
								
								rpc/http.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								rpc/http.go
									
									
									
									
									
								
							| @@ -20,6 +20,7 @@ import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| @@ -151,41 +152,36 @@ func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||||
| 	if r.Method == "GET" && r.ContentLength == 0 && r.URL.RawQuery == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if responseCode, errorMessage := httpErrorResponse(r); responseCode != 0 { | ||||
| 		http.Error(w, errorMessage, responseCode) | ||||
| 	if code, err := validateRequest(r); err != nil { | ||||
| 		http.Error(w, err.Error(), code) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// All checks passed, create a codec that reads direct from the request body | ||||
| 	// untilEOF and writes the response to w and order the server to process a | ||||
| 	// single request. | ||||
| 	codec := NewJSONCodec(&httpReadWriteNopCloser{r.Body, w}) | ||||
| 	defer codec.Close() | ||||
|  | ||||
| 	w.Header().Set("content-type", "application/json") | ||||
| 	w.Header().Set("content-type", contentType) | ||||
| 	srv.ServeSingleRequest(codec, OptionMethodInvocation) | ||||
| } | ||||
|  | ||||
| // Returns a non-zero response code and error message if the request is invalid. | ||||
| func httpErrorResponse(r *http.Request) (int, string) { | ||||
| // validateRequest returns a non-zero response code and error message if the | ||||
| // request is invalid. | ||||
| func validateRequest(r *http.Request) (int, error) { | ||||
| 	if r.Method == "PUT" || r.Method == "DELETE" { | ||||
| 		errorMessage := "method not allowed" | ||||
| 		return http.StatusMethodNotAllowed, errorMessage | ||||
| 		return http.StatusMethodNotAllowed, errors.New("method not allowed") | ||||
| 	} | ||||
|  | ||||
| 	if r.ContentLength > maxHTTPRequestContentLength { | ||||
| 		errorMessage := fmt.Sprintf("content length too large (%d>%d)", r.ContentLength, maxHTTPRequestContentLength) | ||||
| 		return http.StatusRequestEntityTooLarge, errorMessage | ||||
| 		err := fmt.Errorf("content length too large (%d>%d)", r.ContentLength, maxHTTPRequestContentLength) | ||||
| 		return http.StatusRequestEntityTooLarge, err | ||||
| 	} | ||||
|  | ||||
| 	ct := r.Header.Get("content-type") | ||||
| 	mt, _, err := mime.ParseMediaType(ct) | ||||
| 	mt, _, err := mime.ParseMediaType(r.Header.Get("content-type")) | ||||
| 	if err != nil || mt != contentType { | ||||
| 		errorMessage := fmt.Sprintf("invalid content type, only %s is supported", contentType) | ||||
| 		return http.StatusUnsupportedMediaType, errorMessage | ||||
| 		err := fmt.Errorf("invalid content type, only %s is supported", contentType) | ||||
| 		return http.StatusUnsupportedMediaType, err | ||||
| 	} | ||||
|  | ||||
| 	return 0, "" | ||||
| 	return 0, nil | ||||
| } | ||||
|  | ||||
| func newCorsHandler(srv *Server, allowedOrigins []string) http.Handler { | ||||
|   | ||||
| @@ -1,3 +1,19 @@ | ||||
| // Copyright 2017 The go-ethereum Authors | ||||
| // This file is part of the go-ethereum library. | ||||
| // | ||||
| // The go-ethereum library is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU Lesser General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // (at your option) any later version. | ||||
| // | ||||
| // The go-ethereum library is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU Lesser General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU Lesser General Public License | ||||
| // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| package rpc | ||||
|  | ||||
| import ( | ||||
| @@ -8,33 +24,31 @@ import ( | ||||
| ) | ||||
|  | ||||
| func TestHTTPErrorResponseWithDelete(t *testing.T) { | ||||
| 	httpErrorResponseTest(t, "DELETE", contentType, "", http.StatusMethodNotAllowed) | ||||
| 	testHTTPErrorResponse(t, "DELETE", contentType, "", http.StatusMethodNotAllowed) | ||||
| } | ||||
|  | ||||
| func TestHTTPErrorResponseWithPut(t *testing.T) { | ||||
| 	httpErrorResponseTest(t, "PUT", contentType, "", http.StatusMethodNotAllowed) | ||||
| 	testHTTPErrorResponse(t, "PUT", contentType, "", http.StatusMethodNotAllowed) | ||||
| } | ||||
|  | ||||
| func TestHTTPErrorResponseWithMaxContentLength(t *testing.T) { | ||||
| 	body := make([]rune, maxHTTPRequestContentLength+1, maxHTTPRequestContentLength+1) | ||||
| 	httpErrorResponseTest(t, | ||||
| 	testHTTPErrorResponse(t, | ||||
| 		"POST", contentType, string(body), http.StatusRequestEntityTooLarge) | ||||
| } | ||||
|  | ||||
| func TestHTTPErrorResponseWithEmptyContentType(t *testing.T) { | ||||
| 	httpErrorResponseTest(t, "POST", "", "", http.StatusUnsupportedMediaType) | ||||
| 	testHTTPErrorResponse(t, "POST", "", "", http.StatusUnsupportedMediaType) | ||||
| } | ||||
|  | ||||
| func TestHTTPErrorResponseWithValidRequest(t *testing.T) { | ||||
| 	httpErrorResponseTest(t, "POST", contentType, "", 0) | ||||
| 	testHTTPErrorResponse(t, "POST", contentType, "", 0) | ||||
| } | ||||
|  | ||||
| func httpErrorResponseTest(t *testing.T, | ||||
| 	method, contentType, body string, expectedResponse int) { | ||||
|  | ||||
| func testHTTPErrorResponse(t *testing.T, method, contentType, body string, expected int) { | ||||
| 	request := httptest.NewRequest(method, "http://url.com", strings.NewReader(body)) | ||||
| 	request.Header.Set("content-type", contentType) | ||||
| 	if response, _ := httpErrorResponse(request); response != expectedResponse { | ||||
| 		t.Fatalf("response code should be %d not %d", expectedResponse, response) | ||||
| 	if code, _ := validateRequest(request); code != expected { | ||||
| 		t.Fatalf("response code should be %d not %d", expected, code) | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user