Skip to content

Allow blocking on fastify path params #5889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

IlyasShabi
Copy link
Contributor

What does this PR do?

Allow blocking on fastify path params

Motivation

Plugin Checklist

Additional Notes

Copy link

github-actions bot commented Jun 12, 2025

Overall package size

Self size: 9.67 MB
Deduped: 106.17 MB
No deduping: 106.69 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------| | @datadog/libdatadog | 0.7.0 | 35.02 MB | 35.02 MB | | @datadog/native-appsec | 8.5.2 | 19.33 MB | 19.34 MB | | @datadog/native-iast-taint-tracking | 4.0.0 | 11.72 MB | 11.73 MB | | @datadog/pprof | 5.8.2 | 9.56 MB | 9.93 MB | | @opentelemetry/core | 1.30.1 | 908.66 kB | 7.16 MB | | protobufjs | 7.5.3 | 2.95 MB | 5.6 MB | | @datadog/wasm-js-rewriter | 4.0.1 | 2.85 MB | 3.58 MB | | @datadog/native-metrics | 3.1.1 | 1.02 MB | 1.43 MB | | @opentelemetry/api | 1.8.0 | 1.21 MB | 1.21 MB | | import-in-the-middle | 1.14.0 | 120.58 kB | 841.68 kB | | source-map | 0.7.4 | 226 kB | 226 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | lru-cache | 7.18.3 | 133.92 kB | 133.92 kB | | pprof-format | 2.1.0 | 111.69 kB | 111.69 kB | | @datadog/sketches-js | 2.1.1 | 109.9 kB | 109.9 kB | | lodash.sortby | 4.7.0 | 75.76 kB | 75.76 kB | | ignore | 5.3.2 | 53.63 kB | 53.63 kB | | istanbul-lib-coverage | 3.2.2 | 34.37 kB | 34.37 kB | | rfdc | 1.4.1 | 27.15 kB | 27.15 kB | | @isaacs/ttlcache | 1.4.1 | 25.2 kB | 25.2 kB | | dc-polyfill | 0.1.9 | 25.11 kB | 25.11 kB | | tlhunter-sorted-set | 0.1.0 | 24.94 kB | 24.94 kB | | shell-quote | 1.8.2 | 23.54 kB | 23.54 kB | | limiter | 1.1.5 | 23.17 kB | 23.17 kB | | retry | 0.13.1 | 18.85 kB | 18.85 kB | | semifies | 1.0.0 | 15.84 kB | 15.84 kB | | jest-docblock | 29.7.0 | 8.99 kB | 12.76 kB | | crypto-randomuuid | 1.0.0 | 11.18 kB | 11.18 kB | | ttl-set | 1.0.0 | 4.61 kB | 9.69 kB | | mutexify | 1.4.0 | 5.71 kB | 8.74 kB | | path-to-regexp | 0.1.12 | 6.6 kB | 6.6 kB | | koalas | 1.0.2 | 6.47 kB | 6.47 kB | | module-details-from-path | 1.0.4 | 3.96 kB | 3.96 kB |

🤖 This report was automatically generated by heaviest-objects-in-the-universe

Copy link

codecov bot commented Jun 12, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 80.75%. Comparing base (0b3ab0c) to head (528f1c3).
Report is 5 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5889      +/-   ##
==========================================
- Coverage   81.62%   80.75%   -0.88%     
==========================================
  Files         455      462       +7     
  Lines       19589    19907     +318     
==========================================
+ Hits        15990    16075      +85     
- Misses       3599     3832     +233     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@datadog-datadog-prod-us1
Copy link

datadog-datadog-prod-us1 bot commented Jun 12, 2025

Datadog Report

Branch report: ishabi/fastify-path-params
Commit report: 81438b8
Test service: dd-trace-js-integration-tests

✅ 0 Failed, 1257 Passed, 0 Skipped, 20m 44.5s Total Time

@pr-commenter
Copy link

pr-commenter bot commented Jun 12, 2025

Benchmarks

Benchmark execution time: 2025-06-16 08:40:22

Comparing candidate commit 528f1c3 in PR branch ishabi/fastify-path-params with baseline commit 0b3ab0c in branch master.

Found 0 performance improvements and 0 performance regressions! Performance is the same for 1274 metrics, 49 unstable metrics.

@IlyasShabi IlyasShabi changed the title Ishabi/fastify path params Allow blocking on fastify path params Jun 12, 2025
@IlyasShabi IlyasShabi force-pushed the ishabi/fastify-path-params branch from af324cd to f072775 Compare June 12, 2025 15:54
@IlyasShabi IlyasShabi marked this pull request as ready for review June 12, 2025 16:21
@IlyasShabi IlyasShabi requested review from a team as code owners June 12, 2025 16:21
})

app.register(async function (nested) {
nested.get('/:nestedDuplicatedParameter', async (request, reply) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why we have this nestedDuplicatedParameter in express test, is that we have two parameters with the same name in different routes.
Here, we don't have any other parameter called nestedDuplicatedParameter, so the property name is wrong, and should be something like secondParam, or in the prefix, it should be also nestedDuplicatedParameter.
Maybe this example does make no sense in fastify.


app.addHook('preHandler', paramHookSpy)

app.get('/callback-path-param/:callbackedParameter', (request, reply) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for this test, in express tests, :callbackedParameter is called as it is, because we are listening for app.param('callbackedParameter'...). Does it make sense here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter name doesn't make sense here because in Fastify we have a global hook that runs for all routes using app.addHook('preHandler', paramHookSpy)

@IlyasShabi IlyasShabi requested a review from uurien June 13, 2025 09:04
Comment on lines +337 to +344
try {
await axios.get('/multiple-path-params/testattack/testattack')

return Promise.reject(new Error('Request should not return 200'))
} catch (e) {
assert.equal(e.response.status, 403)
assert.deepEqual(e.response.data, JSON.parse(json))
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using try / catch, we could switch to the native assert and use assert.rejects. That provides more information and is IMO easier to reason about.

@@ -133,6 +134,17 @@ function preValidation (request, reply, done) {
if (abortController.signal.aborted) return
}

if (pathParamsReadCh.hasSubscribers && request.params) {
const abortController = new AbortController()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating new AbortControllers is quite expensive. Could we just reuse an already defined controller?
I believe it's possible to unify the up to three controllers to a single one.

Comment on lines 137 to 146
if (pathParamsReadCh.hasSubscribers && request.params) {
const abortController = new AbortController()

pathParamsReadCh.publish({
req,
res,
abortController,
params: request.params
})
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uhm where is the blocking ?

pathParamsReadCh.publish({
req,
res,
abortController,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you do this for the 3 different calls, you don't create it until it's needed, but you also cache it for the others. Wdyt ?

Suggested change
abortController,
abortController: abortController ?? abortController = new AbortController(),

@@ -264,7 +264,11 @@ withVersions('fastify', 'fastify', version => {
})

describe('Suspicious request blocking - path parameters', () => {
let server, paramHookSpy, axios
// Skip Fastify v1 - preValidation hook is not supported
if (semver.lt(semver.coerce(version), '2.0.0')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we don't really support blocking before 2.0.0 we should consider appsec only support fastify starting from v2 and add that to the relevant doc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants