summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Lee <64482439+algojohnlee@users.noreply.github.com>2023-06-22 12:17:04 -0400
committerGitHub <noreply@github.com>2023-06-22 12:17:04 -0400
commitc046df2e6b499627d901275991e66e3bb67138f6 (patch)
treeb577b828d810324091bea2838ac394963fda33cf
parent75d63d133f3e69c76ffeebcf2f555ed0f2e64fa7 (diff)
parent796ac9f5795a02c941e010205334d6ca50d9b6dd (diff)
Merge pull request #5489 from algorand/relbeta3.16.3v3.16.3-beta
-rw-r--r--buildnumber.dat2
-rw-r--r--daemon/algod/api/server/router.go32
-rw-r--r--daemon/algod/api/server/router_test.go37
-rw-r--r--daemon/algod/api/server/v2/test/handlers_test.go34
-rw-r--r--daemon/algod/api/server/v2/test/helpers.go2
5 files changed, 67 insertions, 40 deletions
diff --git a/buildnumber.dat b/buildnumber.dat
index 0cfbf0888..00750edc0 100644
--- a/buildnumber.dat
+++ b/buildnumber.dat
@@ -1 +1 @@
-2
+3
diff --git a/daemon/algod/api/server/router.go b/daemon/algod/api/server/router.go
index 6797bd988..b599194ab 100644
--- a/daemon/algod/api/server/router.go
+++ b/daemon/algod/api/server/router.go
@@ -51,8 +51,8 @@ const (
apiV1Tag = "/v1"
// TokenHeader is the header where we put the token.
TokenHeader = "X-Algo-API-Token"
- // maxRequestBodyBytes is the maximum request body size that we allow in our APIs.
- maxRequestBodyBytes = "10MB"
+ // MaxRequestBodyBytes is the maximum request body size that we allow in our APIs.
+ MaxRequestBodyBytes = "10MB"
)
// wrapCtx passes a common context to each request without a global variable.
@@ -79,8 +79,13 @@ func NewRouter(logger logging.Logger, node APINodeInterface, shutdown <-chan str
if err := tokens.ValidateAPIToken(adminAPIToken); err != nil {
logger.Errorf("Invalid adminAPIToken was passed to NewRouter ('%s'): %v", adminAPIToken, err)
}
- adminAuthenticator := middlewares.MakeAuth(TokenHeader, []string{adminAPIToken})
- apiAuthenticator := middlewares.MakeAuth(TokenHeader, []string{adminAPIToken, apiToken})
+ adminMiddleware := []echo.MiddlewareFunc{
+ middlewares.MakeAuth(TokenHeader, []string{adminAPIToken}),
+ }
+ publicMiddleware := []echo.MiddlewareFunc{
+ middleware.BodyLimit(MaxRequestBodyBytes),
+ middlewares.MakeAuth(TokenHeader, []string{adminAPIToken, apiToken}),
+ }
e := echo.New()
@@ -93,7 +98,6 @@ func NewRouter(logger logging.Logger, node APINodeInterface, shutdown <-chan str
e.Use(
middlewares.MakeLogger(logger),
middlewares.MakeCORS(TokenHeader),
- middleware.BodyLimit(maxRequestBodyBytes),
)
// Request Context
@@ -104,14 +108,14 @@ func NewRouter(logger logging.Logger, node APINodeInterface, shutdown <-chan str
// Route pprof requests to DefaultServeMux.
// The auth middleware removes /urlAuth/:token so that it can be routed correctly.
if node.Config().EnableProfiler {
- e.GET("/debug/pprof/*", echo.WrapHandler(http.DefaultServeMux), adminAuthenticator)
- e.GET(fmt.Sprintf("%s/debug/pprof/*", middlewares.URLAuthPrefix), echo.WrapHandler(http.DefaultServeMux), adminAuthenticator)
+ e.GET("/debug/pprof/*", echo.WrapHandler(http.DefaultServeMux), adminMiddleware...)
+ e.GET(fmt.Sprintf("%s/debug/pprof/*", middlewares.URLAuthPrefix), echo.WrapHandler(http.DefaultServeMux), adminMiddleware...)
}
// Registering common routes (no auth)
registerHandlers(e, "", common.Routes, ctx)
// Registering v1 routes
- registerHandlers(e, apiV1Tag, routes.V1Routes, ctx, apiAuthenticator)
+ registerHandlers(e, apiV1Tag, routes.V1Routes, ctx, publicMiddleware...)
// Registering v2 routes
v2Handler := v2.Handlers{
@@ -119,17 +123,17 @@ func NewRouter(logger logging.Logger, node APINodeInterface, shutdown <-chan str
Log: logger,
Shutdown: shutdown,
}
- nppublic.RegisterHandlers(e, &v2Handler, apiAuthenticator)
- npprivate.RegisterHandlers(e, &v2Handler, adminAuthenticator)
- ppublic.RegisterHandlers(e, &v2Handler, apiAuthenticator)
- pprivate.RegisterHandlers(e, &v2Handler, adminAuthenticator)
+ nppublic.RegisterHandlers(e, &v2Handler, publicMiddleware...)
+ npprivate.RegisterHandlers(e, &v2Handler, adminMiddleware...)
+ ppublic.RegisterHandlers(e, &v2Handler, publicMiddleware...)
+ pprivate.RegisterHandlers(e, &v2Handler, adminMiddleware...)
if node.Config().EnableFollowMode {
- data.RegisterHandlers(e, &v2Handler, apiAuthenticator)
+ data.RegisterHandlers(e, &v2Handler, publicMiddleware...)
}
if node.Config().EnableExperimentalAPI {
- experimental.RegisterHandlers(e, &v2Handler, apiAuthenticator)
+ experimental.RegisterHandlers(e, &v2Handler, publicMiddleware...)
}
return e
diff --git a/daemon/algod/api/server/router_test.go b/daemon/algod/api/server/router_test.go
index 98e772f27..37fc3be74 100644
--- a/daemon/algod/api/server/router_test.go
+++ b/daemon/algod/api/server/router_test.go
@@ -22,22 +22,15 @@ import (
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/suite"
"github.com/algorand/go-algorand/daemon/algod/api/server/lib"
"github.com/algorand/go-algorand/daemon/algod/api/server/v1/routes"
-
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/test/partitiontest"
)
-type TestSuite struct {
- suite.Suite
- e *echo.Echo
-}
-
-func (s *TestSuite) SetupSuite() {
- s.e = echo.New()
+func setupRouter() *echo.Echo {
+ e := echo.New()
// Make a deep copy of the routes array with handlers.
v1RoutesCopy := make([]lib.Route, len(routes.V1Routes))
for _, route := range routes.V1Routes {
@@ -51,10 +44,13 @@ func (s *TestSuite) SetupSuite() {
// Make a ReqContext with an initialized logger to prevent nil dereferencing.
reqCtx := lib.ReqContext{Log: logging.NewLogger()}
// Registering v1 routes
- registerHandlers(s.e, apiV1Tag, v1RoutesCopy, reqCtx)
+ registerHandlers(e, apiV1Tag, v1RoutesCopy, reqCtx)
+ return e
}
-func (s *TestSuite) TestGetTransactionV1Sunset() {
+func TestGetTransactionV1Sunset(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
testCases := []struct {
path string
route string
@@ -67,21 +63,16 @@ func (s *TestSuite) TestGetTransactionV1Sunset() {
}
rec := httptest.NewRecorder()
- ctx := s.e.NewContext(nil, rec)
+ e := setupRouter()
+ ctx := e.NewContext(nil, rec)
for _, testCase := range testCases {
- s.e.Router().Find(http.MethodGet, testCase.path, ctx)
- assert.Equal(s.T(), testCase.route, ctx.Path())
+ e.Router().Find(http.MethodGet, testCase.path, ctx)
+ assert.Equal(t, testCase.route, ctx.Path())
// Check that router correctly routes to the v1Sunset handler.
- assert.Equal(s.T(), nil, ctx.Handler()(ctx))
- assert.NotNil(s.T(), rec.Body)
- assert.Equal(s.T(), http.StatusGone, rec.Code)
+ assert.Equal(t, nil, ctx.Handler()(ctx))
+ assert.NotNil(t, rec.Body)
+ assert.Equal(t, http.StatusGone, rec.Code)
}
-
-}
-
-func TestTestSuite(t *testing.T) {
- partitiontest.PartitionTest(t)
- suite.Run(t, new(TestSuite))
}
diff --git a/daemon/algod/api/server/v2/test/handlers_test.go b/daemon/algod/api/server/v2/test/handlers_test.go
index e30169b4a..a4625d41c 100644
--- a/daemon/algod/api/server/v2/test/handlers_test.go
+++ b/daemon/algod/api/server/v2/test/handlers_test.go
@@ -24,15 +24,16 @@ import (
"fmt"
"io"
"math"
+ "net"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
+ "github.com/algorand/go-algorand/daemon/algod/api/server"
"github.com/algorand/go-algorand/ledger/eval"
"github.com/algorand/go-algorand/ledger/ledgercore"
-
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@@ -2203,3 +2204,34 @@ func TestDeltasForTxnGroup(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 501, rec.Code)
}
+
+func TestRouterRequestBody(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ mockLedger, _, _, _, _ := testingenv(t, 1, 1, true)
+ mockNode := makeMockNode(mockLedger, t.Name(), nil, cannedStatusReportGolden, false)
+ dummyShutdownChan := make(chan struct{})
+ l, err := net.Listen("tcp", ":0") // create listener so requests are buffered
+ e := server.NewRouter(logging.TestingLog(t), mockNode, dummyShutdownChan, "", "", l, 1000)
+ go e.Start(":0")
+ defer e.Close()
+
+ // Admin API call greater than max body bytes should succeed
+ assert.Equal(t, "10MB", server.MaxRequestBodyBytes)
+ stringReader := strings.NewReader(strings.Repeat("a", 50_000_000))
+ req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("https://%s/v2/participation", e.Listener.Addr().String()), stringReader)
+ assert.NoError(t, err)
+ rec := httptest.NewRecorder()
+ e.ServeHTTP(rec, req)
+ assert.Equal(t, http.StatusOK, rec.Code)
+
+ // Public API call greater than max body bytes fails
+ assert.Equal(t, "10MB", server.MaxRequestBodyBytes)
+ stringReader = strings.NewReader(strings.Repeat("a", 50_000_000))
+ req, err = http.NewRequest(http.MethodPost, fmt.Sprintf("https://%s/v2/transactions", e.Listener.Addr().String()), stringReader)
+ assert.NoError(t, err)
+ rec = httptest.NewRecorder()
+ e.ServeHTTP(rec, req)
+ assert.Equal(t, http.StatusRequestEntityTooLarge, rec.Code)
+}
diff --git a/daemon/algod/api/server/v2/test/helpers.go b/daemon/algod/api/server/v2/test/helpers.go
index bcc1e15d8..75ee461ca 100644
--- a/daemon/algod/api/server/v2/test/helpers.go
+++ b/daemon/algod/api/server/v2/test/helpers.go
@@ -103,7 +103,7 @@ type mockNode struct {
}
func (m *mockNode) InstallParticipationKey(partKeyBinary []byte) (account.ParticipationID, error) {
- panic("implement me")
+ return account.ParticipationID{}, nil
}
func (m *mockNode) ListParticipationKeys() ([]account.ParticipationRecord, error) {