Skip to content

Commit

Permalink
feat(telemetry): replace unique ids for resources with a slug
Browse files Browse the repository at this point in the history
  • Loading branch information
williamhbaker committed Apr 7, 2021
1 parent 07c030a commit 53b4e52
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 16 deletions.
78 changes: 66 additions & 12 deletions kit/transport/http/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import (
"fmt"
"net/http"
"path"
"regexp"
"strings"
"time"

"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/kit/platform/errors"

"github.com/go-chi/chi"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/kit/tracing"
ua "github.com/mileusna/useragent"
"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -111,17 +110,32 @@ func UserAgent(r *http.Request) string {
return ua.Parse(header).Name
}

// Constants used for normalizing paths
const (
fileSlug = ":file_name"
shardSlug = ":shard_id"
)

func normalizePath(p string) string {
// Normalize any paths used during backup or restore processes
p = normalizeBackupAndRestore(p)

// Go through each part of the path and normalize IDs and UI assets
var parts []string
for head, tail := shiftPath(p); ; head, tail = shiftPath(tail) {
piece := head
if len(piece) == platform.IDLength {
if _, err := platform.IDFromString(head); err == nil {

// Normalize any ID's in the path as the ":id" slug
if len(piece) == influxdb.IDLength {
if _, err := influxdb.IDFromString(head); err == nil {
piece = ":id"
}
}
parts = append(parts, piece)

if tail == "/" {
// Normalize UI asset file names. The UI asset file is the last part of the path.
parts[len(parts)-1] = normalizeAssetFile(parts[len(parts)-1])
break
}
}
Expand All @@ -137,18 +151,58 @@ func shiftPath(p string) (head, tail string) {
return p[1:i], p[i:]
}

// Normalize the file name for a UI asset
// For example: 838442d56d.svg will return as :file_id.svg
// Files names that do not have one of the listed extensions will be returned unchanged
func normalizeAssetFile(f string) string {
exts := []string{
".js",
".svg",
".woff2",
".wasm",
".map",
".LICENSE",
}

for _, ext := range exts {
if strings.HasSuffix(f, ext) {
return fileSlug + ext
}
}

return f
}

// Normalize paths used during the backup and restore process.
// Paths not matching any of the patterns will be returned unchanged.
func normalizeBackupAndRestore(pth string) string {
patterns := map[string]string{
`restore/shards/\d+`: path.Join("restore/shards", shardSlug),
`backup/shards/\d+`: path.Join("backup/shards", shardSlug),
}

for p, s := range patterns {
re := regexp.MustCompile(p)
if re.MatchString(pth) {
return re.ReplaceAllString(pth, s)
}
}

return pth
}

type OrgContext string

const CtxOrgKey OrgContext = "orgID"

// ValidResource make sure a resource exists when a sub system needs to be mounted to an api
func ValidResource(api *API, lookupOrgByResourceID func(context.Context, platform.ID) (platform.ID, error)) Middleware {
func ValidResource(api *API, lookupOrgByResourceID func(context.Context, influxdb.ID) (influxdb.ID, error)) Middleware {
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
statusW := NewStatusResponseWriter(w)
id, err := platform.IDFromString(chi.URLParam(r, "id"))
id, err := influxdb.IDFromString(chi.URLParam(r, "id"))
if err != nil {
api.Err(w, r, platform.ErrCorruptID(err))
api.Err(w, r, influxdb.ErrCorruptID(err))
return
}

Expand All @@ -157,8 +211,8 @@ func ValidResource(api *API, lookupOrgByResourceID func(context.Context, platfor
orgID, err := lookupOrgByResourceID(ctx, *id)
if err != nil {
// if this function returns an error we will squash the error message and replace it with a not found error
api.Err(w, r, &errors.Error{
Code: errors.ENotFound,
api.Err(w, r, &influxdb.Error{
Code: influxdb.ENotFound,
Msg: "404 page not found",
})
return
Expand All @@ -172,11 +226,11 @@ func ValidResource(api *API, lookupOrgByResourceID func(context.Context, platfor
}

// OrgIDFromContext ....
func OrgIDFromContext(ctx context.Context) *platform.ID {
func OrgIDFromContext(ctx context.Context) *influxdb.ID {
v := ctx.Value(CtxOrgKey)
if v == nil {
return nil
}
id := v.(platform.ID)
id := v.(influxdb.ID)
return &id
}
37 changes: 33 additions & 4 deletions kit/transport/http/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import (
"path"
"testing"

"github.com/influxdata/influxdb/v2/kit/platform"

"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/pkg/testttp"
"github.com/stretchr/testify/assert"
)
Expand All @@ -19,7 +18,7 @@ func Test_normalizePath(t *testing.T) {
}{
{
name: "1",
path: path.Join("/api/v2/organizations", platform.ID(2).String()),
path: path.Join("/api/v2/organizations", influxdb.ID(2).String()),
expected: "/api/v2/organizations/:id",
},
{
Expand All @@ -34,9 +33,39 @@ func Test_normalizePath(t *testing.T) {
},
{
name: "4",
path: path.Join("/api/v2/organizations", platform.ID(2).String(), "users", platform.ID(3).String()),
path: path.Join("/api/v2/organizations", influxdb.ID(2).String(), "users", influxdb.ID(3).String()),
expected: "/api/v2/organizations/:id/users/:id",
},
{
name: "5",
path: "/838442d56d.svg",
expected: "/" + fileSlug + ".svg",
},
{
name: "6",
path: "/838442d56d.svg/extra",
expected: "/838442d56d.svg/extra",
},
{
name: "7",
path: "/api/v2/restore/shards/1001",
expected: path.Join("/api/v2/restore/shards/", shardSlug),
},
{
name: "8",
path: "/api/v2/restore/shards/1001/extra",
expected: path.Join("/api/v2/restore/shards/", shardSlug, "extra"),
},
{
name: "9",
path: "/api/v2/backup/shards/1005",
expected: path.Join("/api/v2/backup/shards/", shardSlug),
},
{
name: "10",
path: "/api/v2/backup/shards/1005/extra",
expected: path.Join("/api/v2/backup/shards/", shardSlug, "extra"),
},
}

for _, tt := range tests {
Expand Down

0 comments on commit 53b4e52

Please sign in to comment.