From f575ed9c17e45edc9b011b694aa5828059007d57 Mon Sep 17 00:00:00 2001 From: Andrey Beletsky Date: Wed, 14 Aug 2019 23:22:25 +0700 Subject: [PATCH] Move proxy handlers and accounts tests into proxy package --- api/handlers.go | 61 +---------------------- api/handlers_test.go | 66 ++----------------------- {api => app/proxy}/accounts_test.go | 23 +++++++-- app/proxy/handlers_test.go | 76 +++++++++++++++++++++++++++++ app/proxy/proxy_test.go | 61 +---------------------- 5 files changed, 100 insertions(+), 187 deletions(-) rename {api => app/proxy}/accounts_test.go (95%) create mode 100644 app/proxy/handlers_test.go diff --git a/api/handlers.go b/api/handlers.go index a8920e06..fbea7ff4 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -1,81 +1,22 @@ package api import ( - "encoding/json" "fmt" - "io/ioutil" "net/http" "github.com/lbryio/lbrytv/app/player" - "github.com/lbryio/lbrytv/app/proxy" - "github.com/lbryio/lbrytv/app/users" - "github.com/lbryio/lbrytv/config" "github.com/lbryio/lbrytv/internal/monitor" "github.com/gorilla/mux" - log "github.com/sirupsen/logrus" ) var logger = monitor.NewModuleLogger("api") -// Index just serves a blank home page +// Index serves a blank home page func Index(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) } -// Proxy takes client request body and feeds it to the proxy module -func Proxy(w http.ResponseWriter, req *http.Request) { - var accountID string - - if req.Method == "OPTIONS" { - w.WriteHeader(http.StatusOK) - return - } - if req.Body == nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("empty request body")) - return - } - - body, err := ioutil.ReadAll(req.Body) - if err != nil { - log.Panicf("error: %v", err.Error()) - } - - ur, err := proxy.UnmarshalRequest(body) - if err != nil { - response, _ := json.Marshal(proxy.NewErrorResponse(err.Error(), proxy.ErrProxy)) - w.WriteHeader(http.StatusBadRequest) - w.Write(response) - return - } - - if config.AccountsEnabled() { - accountID, err = users.GetAccountIDFromRequest(req) - if err != nil { - response, _ := json.Marshal(proxy.NewErrorResponse(err.Error(), proxy.ErrAuthFailed)) - w.WriteHeader(http.StatusForbidden) - w.Write(response) - return - } - } else { - accountID = "" - } - - lbrynetResponse, err := proxy.Proxy(ur, accountID) - if err != nil { - logger.LogF(monitor.F{"query": ur, "error": err}).Error("proxy errored") - response, _ := json.Marshal(proxy.NewErrorResponse(err.Error(), proxy.ErrProxy)) - w.WriteHeader(http.StatusServiceUnavailable) - w.Write(response) - return - } - - w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.WriteHeader(http.StatusOK) - w.Write(lbrynetResponse) -} - func stream(uri string, w http.ResponseWriter, req *http.Request) { err := player.PlayURI(uri, w, req) // Only output error if player has not pushed anything to the client yet diff --git a/api/handlers_test.go b/api/handlers_test.go index 53115aa3..840eba9f 100644 --- a/api/handlers_test.go +++ b/api/handlers_test.go @@ -1,78 +1,20 @@ package api import ( - "bytes" - "encoding/json" "io" "net/http" "net/http/httptest" - "strings" "testing" - ljsonrpc "github.com/lbryio/lbry.go/extras/jsonrpc" "github.com/stretchr/testify/assert" - "github.com/ybbus/jsonrpc" ) -func TestProxyOptions(t *testing.T) { - request, _ := http.NewRequest("OPTIONS", "/api/proxy", nil) - rr := httptest.NewRecorder() - http.HandlerFunc(Proxy).ServeHTTP(rr, request) - response := rr.Result() - assert.Equal(t, http.StatusOK, response.StatusCode) -} - -func TestProxyNilQuery(t *testing.T) { - request, _ := http.NewRequest("POST", "/api/proxy", nil) - rr := httptest.NewRecorder() - http.HandlerFunc(Proxy).ServeHTTP(rr, request) - assert.Equal(t, http.StatusBadRequest, rr.Code) - assert.Equal(t, "empty request body", rr.Body.String()) -} - -func TestProxyInvalidQuery(t *testing.T) { - var parsedResponse jsonrpc.RPCResponse - - request, _ := http.NewRequest("POST", "/api/proxy", bytes.NewBuffer([]byte("yo"))) - rr := httptest.NewRecorder() - http.HandlerFunc(Proxy).ServeHTTP(rr, request) - assert.Equal(t, http.StatusBadRequest, rr.Code) - err := json.Unmarshal(rr.Body.Bytes(), &parsedResponse) - if err != nil { - panic(err) - } - assert.True(t, strings.HasPrefix(parsedResponse.Error.Message, "client json parse error: invalid character 'y'")) -} - -func TestProxy(t *testing.T) { - var query *jsonrpc.RPCRequest - var queryBody []byte - var parsedResponse jsonrpc.RPCResponse - resolveResponse := make(ljsonrpc.ResolveResponse) - - query = jsonrpc.NewRequest("resolve", map[string]string{"urls": "one"}) - queryBody, _ = json.Marshal(query) - request, _ := http.NewRequest("POST", "/api/proxy", bytes.NewBuffer(queryBody)) - rr := httptest.NewRecorder() - - http.HandlerFunc(Proxy).ServeHTTP(rr, request) - - assert.Equal(t, http.StatusOK, rr.Code) - assert.Equal(t, "application/json; charset=utf-8", rr.HeaderMap["Content-Type"][0]) - err := json.Unmarshal(rr.Body.Bytes(), &parsedResponse) - if err != nil { - panic(err) - } - ljsonrpc.Decode(parsedResponse.Result, &resolveResponse) - assert.Equal(t, "one", resolveResponse["one"].Name) -} - func TestContentByURL_NoPayment(t *testing.T) { - req, _ := http.NewRequest("GET", "http://localhost:40080/content/url", nil) - req.URL.RawQuery = "pra-onde-vamos-em-2018-seguran-a-online#3a508cce1fda3b7c1a2502cb4323141d40a2cf0b" - req.Header.Add("Range", "bytes=0-1023") + r, _ := http.NewRequest("GET", "http://localhost:40080/content/url", nil) + r.URL.RawQuery = "pra-onde-vamos-em-2018-seguran-a-online#3a508cce1fda3b7c1a2502cb4323141d40a2cf0b" + r.Header.Add("Range", "bytes=0-1023") rr := httptest.NewRecorder() - http.HandlerFunc(ContentByURL).ServeHTTP(rr, req) + http.HandlerFunc(ContentByURL).ServeHTTP(rr, r) assert.Equal(t, http.StatusPaymentRequired, rr.Code) _, err := rr.Body.ReadByte() diff --git a/api/accounts_test.go b/app/proxy/accounts_test.go similarity index 95% rename from api/accounts_test.go rename to app/proxy/accounts_test.go index 66c30920..91302315 100644 --- a/api/accounts_test.go +++ b/app/proxy/accounts_test.go @@ -1,4 +1,4 @@ -package api +package proxy import ( "bytes" @@ -25,8 +25,13 @@ const dummyServerURL = "http://127.0.0.1:59999" const proxySuffix = "/api/proxy" const testSetupWait = 200 * time.Millisecond +var svc *Service + func TestMain(m *testing.M) { // call flag.Parse() here if TestMain uses flags + go launchGrumpyServer() + svc = NewService(config.GetLbrynet()) + config.Override("AccountsEnabled", true) defer config.RestoreOverridden() @@ -38,6 +43,7 @@ func TestMain(m *testing.M) { } c, connCleanup := storage.CreateTestConn(params) c.SetDefaultConnection() + defer connCleanup() defer lbrynet.RemoveAccount(dummyUserID) @@ -117,7 +123,8 @@ func TestWithValidAuthToken(t *testing.T) { r.Header.Add("X-Lbry-Auth-Token", "d94ab9865f8416d107935d2ca644509c") rr := httptest.NewRecorder() - http.HandlerFunc(Proxy).ServeHTTP(rr, r) + handler := &RequestHandler{svc} + handler.Handle(rr, r) require.Equal(t, http.StatusOK, rr.Code) err := json.Unmarshal(rr.Body.Bytes(), &response) require.Nil(t, err) @@ -171,9 +178,11 @@ func TestWithValidAuthTokenConcurrent(t *testing.T) { qBody, _ := json.Marshal(q) r, _ := http.NewRequest("POST", proxySuffix, bytes.NewBuffer(qBody)) r.Header.Add("X-Lbry-Auth-Token", "d94ab9865f8416d107935d2ca644509c") + rr := httptest.NewRecorder() + handler := &RequestHandler{svc} + handler.Handle(rr, r) - http.HandlerFunc(Proxy).ServeHTTP(rr, r) require.Equal(t, http.StatusOK, rr.Code) json.Unmarshal(rr.Body.Bytes(), &response) require.Nil(t, response.Error) @@ -208,7 +217,9 @@ func TestWithWrongAuthToken(t *testing.T) { r.Header.Add("X-Lbry-Auth-Token", "xXxXxXx") rr := httptest.NewRecorder() - http.HandlerFunc(Proxy).ServeHTTP(rr, r) + handler := &RequestHandler{svc} + handler.Handle(rr, r) + assert.Equal(t, http.StatusForbidden, rr.Code) err := json.Unmarshal(rr.Body.Bytes(), &response) require.Nil(t, err) @@ -235,7 +246,9 @@ func TestWithoutToken(t *testing.T) { r, _ := http.NewRequest("POST", proxySuffix, bytes.NewBuffer(qBody)) rr := httptest.NewRecorder() - http.HandlerFunc(Proxy).ServeHTTP(rr, r) + handler := &RequestHandler{svc} + handler.Handle(rr, r) + require.Equal(t, http.StatusOK, rr.Code) err := json.Unmarshal(rr.Body.Bytes(), &response) diff --git a/app/proxy/handlers_test.go b/app/proxy/handlers_test.go new file mode 100644 index 00000000..22519771 --- /dev/null +++ b/app/proxy/handlers_test.go @@ -0,0 +1,76 @@ +package proxy + +import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + ljsonrpc "github.com/lbryio/lbry.go/extras/jsonrpc" + "github.com/stretchr/testify/assert" + "github.com/ybbus/jsonrpc" +) + +func TestProxyOptions(t *testing.T) { + r, _ := http.NewRequest("OPTIONS", "/api/proxy", nil) + + rr := httptest.NewRecorder() + handler := &RequestHandler{svc} + handler.Handle(rr, r) + + response := rr.Result() + assert.Equal(t, http.StatusOK, response.StatusCode) +} + +func TestProxyNilQuery(t *testing.T) { + r, _ := http.NewRequest("POST", "/api/proxy", nil) + + rr := httptest.NewRecorder() + handler := &RequestHandler{svc} + handler.Handle(rr, r) + + assert.Equal(t, http.StatusBadRequest, rr.Code) + assert.Equal(t, "empty request body", rr.Body.String()) +} + +func TestProxyInvalidQuery(t *testing.T) { + var parsedResponse jsonrpc.RPCResponse + + r, _ := http.NewRequest("POST", "/api/proxy", bytes.NewBuffer([]byte("yo"))) + + rr := httptest.NewRecorder() + handler := &RequestHandler{svc} + handler.Handle(rr, r) + + assert.Equal(t, http.StatusOK, rr.Code) + err := json.Unmarshal(rr.Body.Bytes(), &parsedResponse) + if err != nil { + panic(err) + } + assert.Contains(t, parsedResponse.Error.Message, "invalid character 'y' looking for beginning of value") +} + +func TestProxy(t *testing.T) { + var query *jsonrpc.RPCRequest + var queryBody []byte + var parsedResponse jsonrpc.RPCResponse + resolveResponse := make(ljsonrpc.ResolveResponse) + + query = jsonrpc.NewRequest("resolve", map[string]string{"urls": "one"}) + queryBody, _ = json.Marshal(query) + r, _ := http.NewRequest("POST", "/api/proxy", bytes.NewBuffer(queryBody)) + + rr := httptest.NewRecorder() + handler := &RequestHandler{svc} + handler.Handle(rr, r) + + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, "application/json; charset=utf-8", rr.HeaderMap["Content-Type"][0]) + err := json.Unmarshal(rr.Body.Bytes(), &parsedResponse) + if err != nil { + panic(err) + } + ljsonrpc.Decode(parsedResponse.Result, &resolveResponse) + assert.Equal(t, "one", resolveResponse["one"].Name) +} diff --git a/app/proxy/proxy_test.go b/app/proxy/proxy_test.go index ce3b8f0e..9c461e4d 100644 --- a/app/proxy/proxy_test.go +++ b/app/proxy/proxy_test.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - "os" "strings" "sync" "testing" @@ -175,11 +174,6 @@ func call(t *testing.T, method string, params ...interface{}) jsonrpc.RPCRespons return response } -func TestMain(m *testing.M) { - go launchGrumpyServer() - os.Exit(m.Run()) -} - // TestForwardCallWithHTTPError tests for HTTP level error connecting to a port that no server is listening on func TestForwardCall_HTTPError(t *testing.T) { config.Override("Lbrynet", "http://127.0.0.1:49999") @@ -235,60 +229,7 @@ func TestUnmarshalRequest(t *testing.T) { assert.True(t, strings.HasPrefix(err.Error(), "client json parse error: invalid character 'y'")) } -func TestForwardCall(t *testing.T) { - var err error - var query *jsonrpc.RPCRequest - var response jsonrpc.RPCResponse - var rawResponse []byte - - streamURI := "what#6769855a9aa43b67086f9ff3c1a5bacb5698a27a" - query = jsonrpc.NewRequest(methodResolve, map[string]string{paramUrls: streamURI}) - queryBody, _ := json.Marshal(query) - query, err = UnmarshalRequest(queryBody) - rawResponse, err = ForwardCall(*query) - if err != nil { - t.Errorf("failed with an unexpected error: %v", err) - return - } else if response.Error != nil { - t.Errorf("daemon errored: %v", response.Error.Message) - return - } - - query = jsonrpc.NewRequest(methodGet, map[string]string{"uri": streamURI}) - _, err = ForwardCall(*query) - if err != nil { - t.Errorf("failed with an unexpected error: %v", err) - return - } - if response.Error != nil { - t.Errorf("daemon errored: %v", response.Error.Message) - return - } - - var resolveResponse *ljsonrpc.ResolveResponse - json.Unmarshal(rawResponse, &response) - response.GetObject(&resolveResponse) - outpoint := fmt.Sprintf("%v:%v", (*resolveResponse)[streamURI].Txid, 0) - - query = jsonrpc.NewRequest(methodFileList, map[string]string{"outpoint": outpoint}) - rawResponse, err = ForwardCall(*query) - if err != nil { - t.Errorf("file_list of outpoint %v failed with an unexpected error: %v", outpoint, err) - return - } - - var fileListResponse *ljsonrpc.FileListResponse - json.Unmarshal(rawResponse, &response) - assert.Nil(t, response.Error) - response.GetObject(&fileListResponse) - - if len(*fileListResponse) == 0 { - t.Errorf("not enough results, daemon responded with %v", fileListResponse) - return - } -} - -func TesProxy_WithCache(t *testing.T) { +func TesProxyWithCache(t *testing.T) { var ( err error query *jsonrpc.RPCRequest