Skip to content

feat: Add RequestId filter#10274

Open
patel-vansh wants to merge 9 commits into
codeigniter4:4.8from
patel-vansh:feat/request-id
Open

feat: Add RequestId filter#10274
patel-vansh wants to merge 9 commits into
codeigniter4:4.8from
patel-vansh:feat/request-id

Conversation

@patel-vansh
Copy link
Copy Markdown
Contributor

@patel-vansh patel-vansh commented Jun 3, 2026

Description
This PR adds RequestId filter which will improve debugging, traceability, as well as better logging for each request.

This filter is fully opt-in, that means there's no BC here. The filter line is commented so that users can easily add if needed.

Request id is generated during early lifecycle. Incoming header X-Request-ID will be prioritized over auto generation of request ids, so that CDN/web server/load balancer can generate request id for better traceability.

If the header is not present, the framework will create request id via bin2hex(random_bytes(16)) function, that means the framework-generated ids will be of length 32.

Why only bin2hex?
I initially thought of UUID v4, but due to lack of in-built support for UUID, I changed that to bin2hex. Adding a new external dependency for just this one thing would be less feasible, IMO. And also random_bytes(16) should provide enough randomness so collision would be highly unlikely.

If there is some other better way to generate id, then I would surely change to that.

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value (without duplication)
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@github-actions github-actions Bot added the 4.8 PRs that target the `4.8` branch. label Jun 3, 2026
Copy link
Copy Markdown
Member

@michalsn michalsn left a comment

Choose a reason for hiding this comment

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

Thanks for working on this. I agree that having a request ID can be useful. However, I am not sure we should add this directly to IncomingRequest. I would prefer to see this as documentation only, or provide an opt-in filter that's disabled by default. This is a path similar to those followed by Symfony and Laravel.

If we provide an example or filter, it should store the value in context()->set('request_id', $id) so $logGlobalContext can pick it up, set X-Request-ID on the response in after(), and validate incoming IDs: non-empty, bounded length, and safe characters only.

Let's see what others think.

@memleakd
Copy link
Copy Markdown
Contributor

memleakd commented Jun 3, 2026

Thanks for working on this. I agree that having a request ID is useful.

I also use this in my projects, but with a filter-based approach, and it has worked well in practice. I think that shape fits better here than adding it directly to IncomingRequest.

The filter can resolve or generate the ID early, validate any incoming X-Request-ID, store it in context()->set('request_id', $id) so $logGlobalContext can include it in logs, and expose the same ID back on the response as X-Request-ID.

This avoids keeping separate request-id state on the request object, keeps the feature opt-in, and makes the ID useful for logs, response headers, and support/debug workflows.

@patel-vansh
Copy link
Copy Markdown
Contributor Author

Thanks @michalsn and @memleakd for your reviews. I've changed the implementation. Added a filter which is completely opt-in, so there's no BC. This filter will set request_id key in Context class so that $logGlobalContext can automatically log request IDs.

@patel-vansh patel-vansh requested a review from michalsn June 4, 2026 10:23
@patel-vansh patel-vansh changed the title feat: Add Request ID to IncomingRequest feat: Add RequestId filter Jun 4, 2026
Copy link
Copy Markdown
Contributor

@memleakd memleakd left a comment

Choose a reason for hiding this comment

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

Thanks for updating this. I think the filter direction is much better. I added a few comments on things that still look worth checking.

Comment thread system/Filters/RequestId.php
$response->setHeader('X-Request-ID', context()->get('request_id'));

return null;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this handle the case where request_id is missing from context?

If only the after filter is enabled, or context is cleared before after() runs, this currently sets X-Request-ID to an empty value. It may be safer to either resolve/generate the ID here as a fallback, or skip setting the header when no valid ID exists.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think skipping would be better, changed according to that.

Comment thread tests/system/Filters/RequestIdTest.php

The ID is generated via ``bin2hex(random_bytes(16))``, so it is a 32-character hexadecimal string.

To enable this filter, simply un-comment the ``requestid`` alias in the ``$required['before']`` and ``$required['after']`` array in **app/Config/Filters.php**:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For upgraded apps, should this also mention adding the requestid alias? Existing app/Config/Filters.php files will not have it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't think upgradation notes should be added inside normal docs. IMO, it more belongs to changelog and upgrade guide rather than here. That's why I haven't added that in first place.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've now added a line in upgrade_480.rst so that the apps upgrading can easily do so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sorry, I should have worded that better. I meant the wording here could be adjusted since some apps may still need to add the alias first:

- To enable this filter, simply un-comment the
+ To enable this filter, add/uncomment the

Thanks for adding the upgrade note!

Comment thread user_guide_src/source/incoming/filters.rst Outdated
@patel-vansh patel-vansh requested a review from memleakd June 4, 2026 13:06
Copy link
Copy Markdown
Contributor

@memleakd memleakd left a comment

Choose a reason for hiding this comment

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

Thanks for the updates. This looks much better now. Just two small things left for me:

Comment thread app/Config/Filters.php
Comment on lines 55 to +57
'before' => [
'forcehttps', // Force Global Secure Requests
// 'requestid', // Request ID for each request
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should requestid run before forcehttps? Otherwise a forced HTTPS redirect can happen before the request ID is created, so after() will not add X-Request-ID.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The test file is discovered now, but the tests still only cover before(). Maybe we should add a few after() tests too, like checking that the response gets X-Request-ID and that valid/invalid incoming IDs are reflected correctly in the response.

Comment thread system/Config/Filters.php
Comment on lines 68 to +70
'before' => [
'forcehttps', // Force Global Secure Requests
// 'requestid', // Request ID for each request
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as above

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

Labels

4.8 PRs that target the `4.8` branch.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants