Skip to content

Commit 38aecd6

Browse files
committed
Add a fallback to inferred route for ApiSecurity::RouteExtractor
1 parent 5a1bda1 commit 38aecd6

File tree

5 files changed

+21
-7
lines changed

5 files changed

+21
-7
lines changed

lib/datadog/appsec/api_security/route_extractor.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require_relative '../../tracing/contrib/rack/route_from_path_inference'
4+
35
module Datadog
46
module AppSec
57
module APISecurity
@@ -60,13 +62,16 @@ def self.route_pattern(request)
6062
.recognize(request) { |route, _| break route.path.spec.to_s }
6163

6264
# NOTE: If rails is unable to recognize request it returns empty Array
65+
# We want to return nil in that case to skip this request in the Sampler
6366
pattern = nil if pattern&.empty?
6467

6568
# NOTE: If rails can't recognize the request, we are going to fallback
6669
# to generic request path
6770
(pattern || request.path).delete_suffix(RAILS_FORMAT_SUFFIX)
6871
else
69-
request.path
72+
Tracing::Contrib::Rack::RouteFromPathInference.infer(request.path).tap do |inferred_route|
73+
request.env[Tracing::Contrib::Rack::Ext::DATADOG_INFERRED_ROUTE] = inferred_route
74+
end
7075
end
7176
end
7277
end

lib/datadog/tracing/contrib/rack/ext.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module Ext
1212
ENV_ANALYTICS_ENABLED = 'DD_TRACE_RACK_ANALYTICS_ENABLED'
1313
ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_RACK_ANALYTICS_SAMPLE_RATE'
1414
RACK_ENV_REQUEST_SPAN = 'datadog.rack_request_span'
15+
DATADOG_INFERRED_ROUTE = 'datadog.inferred_route'
1516
SPAN_HTTP_PROXY_REQUEST = 'http.proxy.request'
1617
SPAN_HTTP_PROXY_QUEUE = 'http.proxy.queue'
1718
SPAN_REQUEST = 'rack.request'

sig/datadog/appsec/api_security/route_extractor.rbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module Datadog
1616

1717
RAILS_FORMAT_SUFFIX: String
1818

19-
def self.route_pattern: (APISecurity::_Request request) -> String
19+
def self.route_pattern: (APISecurity::_Request request) -> String?
2020
end
2121
end
2222
end

sig/datadog/tracing/contrib/rack/ext.rbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ module Datadog
1111

1212
RACK_ENV_REQUEST_SPAN: "datadog.rack_request_span"
1313

14+
DATADOG_INFERRED_ROUTE: ::String
15+
1416
SPAN_HTTP_PROXY_REQUEST: "http.proxy.request"
1517

1618
SPAN_HTTP_PROXY_QUEUE: "http.proxy.queue"

spec/datadog/appsec/api_security/route_extractor_spec.rb

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,13 @@
104104
let(:route_set) { double('ActionDispatch::Routing::RouteSet', router: router) }
105105
let(:request) { double('Rack::Request', env: {}, script_name: '', path: '/users/1') }
106106

107-
it { expect(described_class.route_pattern(request)).to eq('/users/1') }
107+
it { expect(described_class.route_pattern(request)).to eq('/users/{param:int}') }
108+
109+
it 'persists inferred route in the request env' do
110+
expect { described_class.route_pattern(request) }
111+
.to change { request.env[Datadog::Tracing::Contrib::Rack::Ext::DATADOG_INFERRED_ROUTE] }
112+
.from(nil).to('/users/{param:int}')
113+
end
108114
end
109115

110116
context 'when route_uri_pattern is not set and request path_parameters is present' do
@@ -130,8 +136,8 @@
130136
let(:action_dispatch_request) { double('ActionDispatch::Request', env: {}, script_name: '', path: '/users/1') }
131137

132138
it 'uses action dispatch request for route recognition' do
133-
expect(router).to receive(:recognize).with(action_dispatch_request).and_return('/users/1')
134-
expect(described_class.route_pattern(request)).to eq('/users/1')
139+
expect(router).to receive(:recognize).with(action_dispatch_request).and_return('/users/:id(.:format)')
140+
expect(described_class.route_pattern(request)).to eq('/users/:id')
135141
end
136142
end
137143

@@ -143,8 +149,8 @@
143149
let(:request) { double('Rack::Request', env: {}, script_name: '', path: '/users/1', head?: false) }
144150

145151
it 'uses action dispatch request for route recognition' do
146-
expect(router).to receive(:recognize).with(request).and_return('/users/1')
147-
expect(described_class.route_pattern(request)).to eq('/users/1')
152+
expect(router).to receive(:recognize).with(request).and_return('/users/:id(.:format)')
153+
expect(described_class.route_pattern(request)).to eq('/users/:id')
148154
end
149155
end
150156
end

0 commit comments

Comments
 (0)