Class: Datadog::AppSec::RouteNormalizer::RoutePattern Private

Inherits:
Object
  • Object
show all
Defined in:
lib/datadog/appsec/route_normalizer/route_pattern.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Normalizes a route spec pattern into the route format, inspired by OpenAPI v3 path templating (best effort)

Example:

/users/:id           => /users/{id}
/photos/:id.:format  => /photos/{id+format}
/posts/:id(.:format) => /posts/{id+format}
/files/*path         => /files/{path}
/hello world         => /hello%20world

NOTE: When a request path is supplied, optional groups (...) are resolved against it: a group is kept only when the path actually matched it.

NOTE: Without a request path (or for paths longer than MAX_RESOLVE_LENGTH), optional markers are flattened and kept as if present.

Defined Under Namespace

Classes: Checkpoint

Constant Summary collapse

GROUP_OPEN_CHAR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"("
GROUP_CLOSE_CHAR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

")"
OPTIONAL_GROUP_SUFFIX_CHAR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"?"
OPTIONAL_GROUP_SIGILS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

[
  GROUP_OPEN_CHAR,
  GROUP_CLOSE_CHAR,
  OPTIONAL_GROUP_SUFFIX_CHAR,
].join
NAMED_PARAM_PREFIX_CHAR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

":"
GLOB_PARAM_PREFIX_CHAR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"*"
PATTERN_STRUCTURE_CHARS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

[
  NAMED_PARAM_PREFIX_CHAR,
  GLOB_PARAM_PREFIX_CHAR,
  GROUP_OPEN_CHAR,
  GROUP_CLOSE_CHAR,
].join
PARAM_NAME_CHARS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

[*"a".."z", *"A".."Z", *"0".."9", "_"].join
EXCLUDED_PARAM_NAME_TERMINATOR_CHARS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

[
  PARAM_NAME_CHARS,
  PATTERN_STRUCTURE_CHARS,
].join
MAX_RESOLVE_LENGTH =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

8192
PARAM_START_SIGILS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Param sigils mark where dynamic route syntax may start

Example:

users    -> no
:id      -> yes
user-:id -> yes
*        -> yes
foo:     -> yes (validated later by {PARAM_TOKENS})
/[:\*]/
PARAM_TOKENS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

/:\w+|(?<!\w)\*\w*/

Instance Method Summary collapse

Constructor Details

#initialize(pattern) ⇒ RoutePattern

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of RoutePattern.



70
71
72
# File 'lib/datadog/appsec/route_normalizer/route_pattern.rb', line 70

def initialize(pattern)
  @pattern = pattern
end

Instance Method Details

#normalize(path: nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/datadog/appsec/route_normalizer/route_pattern.rb', line 74

def normalize(path: nil)
  @path_index = 0
  @pattern_index = 0

  @path = path || ""
  @path_length = @path.length
  @pattern_length = @pattern.length

  nameless_counter = 0
  pattern = resolve_pattern_optionals(path)

  result = pattern.split("/", -1).each_with_object(+"") do |segment, memo|
    memo << "/" unless memo.empty? && segment.empty?
    next if segment.empty?

    unless segment.match?(PARAM_START_SIGILS)
      memo << RouteText.escape(segment)
      next
    end

    tokens = segment.scan(PARAM_TOKENS)

    if tokens.empty?
      memo << RouteText.escape(segment)
      next
    end

    names = tokens.map do |token|
      if token.length > 1
        token[1..-1]
      else
        "param#{nameless_counter += 1}"
      end
    end

    memo << "{#{names.join("+")}}"
  end

  result.start_with?("/") ? result : "/#{result}"
end