diff --git a/api/types/apicache.go b/api/types/v1/apicache.go similarity index 100% rename from api/types/apicache.go rename to api/types/v1/apicache.go diff --git a/api/types/apicache_test.go b/api/types/v1/apicache_test.go similarity index 100% rename from api/types/apicache_test.go rename to api/types/v1/apicache_test.go diff --git a/api/types/apitypes.go b/api/types/v1/apitypes.go similarity index 99% rename from api/types/apitypes.go rename to api/types/v1/apitypes.go index d9cb9347e..506c5b1ac 100644 --- a/api/types/apitypes.go +++ b/api/types/v1/apitypes.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2021, The Decred developers +// Copyright (c) 2019-2022, The Decred developers // Copyright (c) 2017, Jonathan Chappelow // See LICENSE for details. diff --git a/api/types/apitypes_test.go b/api/types/v1/apitypes_test.go similarity index 100% rename from api/types/apitypes_test.go rename to api/types/v1/apitypes_test.go diff --git a/api/types/insightapitypes.go b/api/types/v1/insightapitypes.go similarity index 99% rename from api/types/insightapitypes.go rename to api/types/v1/insightapitypes.go index c0cec758d..7aa248623 100644 --- a/api/types/insightapitypes.go +++ b/api/types/v1/insightapitypes.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2021, The Decred developers +// Copyright (c) 2018-2022, The Decred developers // Copyright (c) 2017, Jonathan Chappelow // See LICENSE for details. diff --git a/blockdata/blockdata.go b/blockdata/blockdata.go index 5c5447d52..4ae36a254 100644 --- a/blockdata/blockdata.go +++ b/blockdata/blockdata.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2021, The Decred developers +// Copyright (c) 2020-2022, The Decred developers // Copyright (c) 2017, Jonathan Chappelow // See LICENSE for details. @@ -16,7 +16,7 @@ import ( chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v4" "github.com/decred/dcrd/wire" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/db/dbtypes" "github.com/decred/dcrdata/v8/stakedb" "github.com/decred/dcrdata/v8/txhelpers" diff --git a/cmd/dcrdata/internal/api/apirouter.go b/cmd/dcrdata/internal/api/apirouter.go index 4d35bf479..9d33b0635 100644 --- a/cmd/dcrdata/internal/api/apirouter.go +++ b/cmd/dcrdata/internal/api/apirouter.go @@ -18,6 +18,11 @@ type apiMux struct { *chi.Mux } +// Versions returns a list of API versions supported. +func (am *apiMux) Versions() []APIVersion { + return supportedAPIVersions[:] +} + type fileMux struct { *chi.Mux } diff --git a/cmd/dcrdata/internal/api/apiroutes.go b/cmd/dcrdata/internal/api/apiroutes.go index 5dd518871..ce6b0e0ed 100644 --- a/cmd/dcrdata/internal/api/apiroutes.go +++ b/cmd/dcrdata/internal/api/apiroutes.go @@ -36,7 +36,7 @@ import ( "github.com/decred/dcrdata/exchanges/v3" "github.com/decred/dcrdata/gov/v6/agendas" "github.com/decred/dcrdata/gov/v6/politeia" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/db/cache" "github.com/decred/dcrdata/v8/db/dbtypes" "github.com/decred/dcrdata/v8/txhelpers" @@ -160,7 +160,7 @@ func NewContext(cfg *AppContextConfig) *appContext { xcBot: cfg.XcBot, AgendaDB: cfg.AgendasDBInstance, ProposalsDB: cfg.ProposalsDB, - Status: apitypes.NewStatus(uint32(nodeHeight), conns, APIVersion, cfg.AppVer, cfg.Params.Name), + Status: apitypes.NewStatus(uint32(nodeHeight), conns, currentAPIVersion, cfg.AppVer, cfg.Params.Name), maxCSVAddrs: cfg.MaxAddrs, charts: cfg.Charts, } diff --git a/cmd/dcrdata/internal/api/insight/apimiddleware.go b/cmd/dcrdata/internal/api/insight/apimiddleware.go index 7e6d4a30e..6d35af828 100644 --- a/cmd/dcrdata/internal/api/insight/apimiddleware.go +++ b/cmd/dcrdata/internal/api/insight/apimiddleware.go @@ -15,7 +15,7 @@ import ( "strings" m "github.com/decred/dcrdata/cmd/dcrdata/internal/middleware" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/go-chi/chi/v5" ) diff --git a/cmd/dcrdata/internal/api/insight/apirouter.go b/cmd/dcrdata/internal/api/insight/apirouter.go index 78b9d7303..33b541879 100644 --- a/cmd/dcrdata/internal/api/insight/apirouter.go +++ b/cmd/dcrdata/internal/api/insight/apirouter.go @@ -19,8 +19,10 @@ type ApiMux struct { *chi.Mux } -// APIVersion is an integer value, incremented for breaking changes -const APIVersion = 0 +// Versions returns a list of API versions supported. +func (am *ApiMux) Versions() []APIVersion { + return supportedAPIVersions[:] +} // NewInsightAPIRouter returns a new HTTP path router, ApiMux, for the Insight // API, app. diff --git a/cmd/dcrdata/internal/api/insight/apiroutes.go b/cmd/dcrdata/internal/api/insight/apiroutes.go index 92a85215a..8f17ae6b2 100644 --- a/cmd/dcrdata/internal/api/insight/apiroutes.go +++ b/cmd/dcrdata/internal/api/insight/apiroutes.go @@ -26,7 +26,7 @@ import ( m "github.com/decred/dcrdata/cmd/dcrdata/internal/middleware" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/db/dbtypes" "github.com/decred/dcrdata/v8/txhelpers" ) diff --git a/cmd/dcrdata/internal/api/insight/apiroutes_test.go b/cmd/dcrdata/internal/api/insight/apiroutes_test.go index 34f924fc1..d37f88cdf 100644 --- a/cmd/dcrdata/internal/api/insight/apiroutes_test.go +++ b/cmd/dcrdata/internal/api/insight/apiroutes_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" ) func Test_dateFromStr(t *testing.T) { diff --git a/cmd/dcrdata/internal/api/insight/converter.go b/cmd/dcrdata/internal/api/insight/converter.go index 94455c7c0..2a3474186 100644 --- a/cmd/dcrdata/internal/api/insight/converter.go +++ b/cmd/dcrdata/internal/api/insight/converter.go @@ -11,7 +11,7 @@ import ( "github.com/decred/dcrd/dcrutil/v4" chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v4" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/txhelpers" ) diff --git a/cmd/dcrdata/internal/api/insight/version.go b/cmd/dcrdata/internal/api/insight/version.go new file mode 100644 index 000000000..d46d127e9 --- /dev/null +++ b/cmd/dcrdata/internal/api/insight/version.go @@ -0,0 +1,15 @@ +// Copyright (c) 2017-2022, The dcrdata developers +// See LICENSE for details. + +package insight + +// APIVersion is an integer value, incremented for breaking changes. +type APIVersion int32 + +// currentVersion is the most recent version supported. +const currentAPIVersion = 1 + +// supportedAPIVersions is a list of supported API versions. +var supportedAPIVersions = [...]APIVersion{ + currentAPIVersion, +} diff --git a/cmd/dcrdata/internal/api/version.go b/cmd/dcrdata/internal/api/version.go index d98564e1b..9e1022369 100644 --- a/cmd/dcrdata/internal/api/version.go +++ b/cmd/dcrdata/internal/api/version.go @@ -3,8 +3,16 @@ package api -// APIVersion is an integer value, incremented for breaking changes -const APIVersion = 1 +// APIVersion is an integer value, incremented for breaking changes. +type APIVersion int32 + +// currentVersion is the most recent version supported. +const currentAPIVersion = 1 + +// supportedAPIVersions is a list of supported API versions. +var supportedAPIVersions = [...]APIVersion{ + currentAPIVersion, +} // CommitHash may be set on the build command line: // go build -ldflags "-X main.CommitHash=`git rev-parse --short HEAD`" diff --git a/cmd/dcrdata/internal/explorer/websockethandlers.go b/cmd/dcrdata/internal/explorer/websockethandlers.go index eee63313f..798701cc0 100644 --- a/cmd/dcrdata/internal/explorer/websockethandlers.go +++ b/cmd/dcrdata/internal/explorer/websockethandlers.go @@ -13,7 +13,7 @@ import ( "strings" "time" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/db/dbtypes" "github.com/decred/dcrdata/v8/explorer/types" pstypes "github.com/decred/dcrdata/v8/pubsub/types" diff --git a/cmd/dcrdata/internal/middleware/apimiddleware.go b/cmd/dcrdata/internal/middleware/apimiddleware.go index 49fbedb18..184635f65 100644 --- a/cmd/dcrdata/internal/middleware/apimiddleware.go +++ b/cmd/dcrdata/internal/middleware/apimiddleware.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2021, The Decred developers +// Copyright (c) 2018-2022, The Decred developers // Copyright (c) 2017, The dcrdata developers // See LICENSE for details. @@ -22,7 +22,7 @@ import ( chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v4" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/didip/tollbooth/v6" "github.com/didip/tollbooth/v6/limiter" "github.com/go-chi/chi/v5" @@ -60,6 +60,7 @@ const ( ctxXcToken ctxStickWidth ctxIndent + ctxAPIVersion ) type DataSource interface { @@ -1101,3 +1102,24 @@ func RetrieveStickWidthCtx(r *http.Request) string { } return bin } + +// APIVersionCtx adds supported API version to a request context. +func APIVersionCtx(version int) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r = r.WithContext(context.WithValue(r.Context(), ctxAPIVersion, version)) + next.ServeHTTP(w, r) + }) + } +} + +// RetrieveAPIVersion pulls the API version of this request form the request's +// context. Unused +func RetrieveAPIVersion(r *http.Request) int { + version, ok := r.Context().Value(ctxAPIVersion).(int) + if !ok { + // The request was sent to the default API route, so no version was set. + return 0 + } + return version +} diff --git a/cmd/dcrdata/main.go b/cmd/dcrdata/main.go index bfc68f06a..b721d5814 100644 --- a/cmd/dcrdata/main.go +++ b/cmd/dcrdata/main.go @@ -727,15 +727,26 @@ func _main(ctx context.Context) error { // SyncStatusAPIIntercept returns a json response if the sync status page is // enabled (no the full explorer while syncing). webMux.With(explore.SyncStatusAPIIntercept).Group(func(r chi.Router) { - // Mount the dcrdata's REST API. + // Mount the default dcrdata REST API. r.Mount("/api", apiMux.Mux) - // Setup and mount the Insight API. + // Mount versioned dcrdata REST API. + for _, version := range apiMux.Versions() { + r.With(mw.APIVersionCtx(int(version))).Mount(fmt.Sprintf("/api/v%d", version), apiMux.Mux) + } + + // Setup the Insight API. insightApp := insight.NewInsightAPI(dcrdClient, chainDB, activeChain, mpm, cfg.IndentJSON, app.Status) insightApp.SetReqRateLimit(cfg.InsightReqRateLimit) insightMux := insight.NewInsightAPIRouter(insightApp, cfg.UseRealIP, cfg.CompressAPI, cfg.MaxCSVAddrs) + + // Mount the dcrdata insight REST API. r.Mount("/insight/api", insightMux.Mux) + // Mount the versioned insight REST API. + for _, version := range insightMux.Versions() { + r.With(mw.APIVersionCtx(int(version))).Mount(fmt.Sprintf("/insight/api/v%d", version), insightMux.Mux) + } if insightSocketServer != nil { r.With(mw.NoOrigin).Get("/insight/socket.io/", insightSocketServer.ServeHTTP) diff --git a/db/dcrpg/insightapi.go b/db/dcrpg/insightapi.go index 16cfcb699..daafdab41 100644 --- a/db/dcrpg/insightapi.go +++ b/db/dcrpg/insightapi.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2021, The Decred developers +// Copyright (c) 2018-2022, The Decred developers // Copyright (c) 2017, The dcrdata developers // See LICENSE for details. @@ -14,7 +14,7 @@ import ( "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/db/cache" "github.com/decred/dcrdata/v8/db/dbtypes" "github.com/decred/dcrdata/v8/txhelpers" diff --git a/db/dcrpg/pgblockchain.go b/db/dcrpg/pgblockchain.go index 6ff5254ec..ecb01c4c1 100644 --- a/db/dcrpg/pgblockchain.go +++ b/db/dcrpg/pgblockchain.go @@ -33,7 +33,7 @@ import ( "github.com/lib/pq" "github.com/decred/dcrdata/db/dcrpg/v8/internal" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/blockdata" "github.com/decred/dcrdata/v8/db/cache" "github.com/decred/dcrdata/v8/db/dbtypes" diff --git a/db/dcrpg/queries.go b/db/dcrpg/queries.go index d06cf1f22..bb40b527b 100644 --- a/db/dcrpg/queries.go +++ b/db/dcrpg/queries.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2021, The Decred developers +// Copyright (c) 2018-2022, The Decred developers // Copyright (c) 2017, The dcrdata developers // See LICENSE for details. @@ -23,7 +23,7 @@ import ( "github.com/decred/dcrd/wire" "github.com/decred/dcrdata/db/dcrpg/v8/internal" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/db/cache" "github.com/decred/dcrdata/v8/db/dbtypes" "github.com/decred/dcrdata/v8/txhelpers" diff --git a/mempool/collector.go b/mempool/collector.go index ed0018dc4..980b7f9b6 100644 --- a/mempool/collector.go +++ b/mempool/collector.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2021, The Decred developers +// Copyright (c) 2018-2022, The Decred developers // Copyright (c) 2017, Jonathan Chappelow // See LICENSE for details. @@ -17,7 +17,7 @@ import ( "github.com/decred/dcrd/dcrutil/v4" chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v4" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" exptypes "github.com/decred/dcrdata/v8/explorer/types" "github.com/decred/dcrdata/v8/txhelpers" ) diff --git a/mempool/mempoolcache.go b/mempool/mempoolcache.go index 18a49fe34..fe125087a 100644 --- a/mempool/mempoolcache.go +++ b/mempool/mempoolcache.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2021, The Decred developers +// Copyright (c) 2019-2022, The Decred developers // Copyright (c) 2017, Jonathan Chappelow // See LICENSE for details. @@ -11,7 +11,7 @@ import ( "github.com/decred/dcrd/dcrutil/v4" chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v4" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/db/dbtypes" exptypes "github.com/decred/dcrdata/v8/explorer/types" ) diff --git a/mempool/mptypes.go b/mempool/mptypes.go index 351c19d16..5ffc00260 100644 --- a/mempool/mptypes.go +++ b/mempool/mptypes.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2021, The Decred developers +// Copyright (c) 2019-2022, The Decred developers // See LICENSE for details. package mempool @@ -8,7 +8,7 @@ import ( "github.com/decred/dcrd/chaincfg/chainhash" chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v4" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" ) // MempoolInfo models basic data about the node's mempool diff --git a/stakedb/stakedb.go b/stakedb/stakedb.go index 919ba2a0d..d419fdb1a 100644 --- a/stakedb/stakedb.go +++ b/stakedb/stakedb.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2021, The Decred developers +// Copyright (c) 2018-2022, The Decred developers // Copyright (c) 2018, The dcrdata developers // Copyright (c) 2017, Jonathan Chappelow // See LICENSE for details. @@ -21,7 +21,7 @@ import ( "github.com/decred/dcrd/dcrutil/v4" "github.com/decred/dcrd/wire" - apitypes "github.com/decred/dcrdata/v8/api/types" + apitypes "github.com/decred/dcrdata/v8/api/types/v1" "github.com/decred/dcrdata/v8/txhelpers" )