Skip to content

Conversation

vpaturet
Copy link
Contributor

@vpaturet vpaturet commented Oct 14, 2025

Summary

Enable access to HTTP response headers through the ResponseMapper interface by introducing OtpHttpResponse wrapper class that encapsulates the body content, headers and status code.
This is required for example to implement support for e-tag.

Note: The integration tests use com.sun.net.httpserver.HttpServer for emulating a simple HTTP server.


Key Changes:

  • Created OtpHttpResponse class with case-insensitive header access
  • Updated ResponseMapper interface signature from InputStream to OtpHttpResponse
  • Modified all ResponseMapper implementations to use response.body()
  • Added comprehensive unit tests for OtpHttpResponse functionality
  • Enhanced integration tests to verify header access works correctly

Benefits:

  • Enables HTTP caching with ETag and Last-Modified headers
  • Supports rate limit monitoring via response headers
  • Allows content type inspection and validation
  • Facilitates debugging with header access

Implementation Details:

  • OtpHttpResponse provides immutable, case-insensitive header access
  • Supports multi-value headers (e.g., Set-Cookie)
  • InputStream lifecycle remains managed by OtpHttpClient
  • Breaking change: All ResponseMapper implementations require update

Issue

No

Unit tests

Added unit tests

Documentation

No

Enable access to HTTP response headers through the ResponseMapper interface
by introducing OtpHttpResponse wrapper class that encapsulates both headers
and body content.

Key Changes:
- Created OtpHttpResponse class with case-insensitive header access
- Updated ResponseMapper interface signature from InputStream to OtpHttpResponse
- Modified all ResponseMapper implementations to use response.body()
- Added comprehensive unit tests for OtpHttpResponse functionality
- Enhanced integration tests to verify header access works correctly

Benefits:
- Enables HTTP caching with ETag and Last-Modified headers
- Supports rate limit monitoring via response headers
- Allows content type inspection and validation
- Facilitates debugging with header access

Implementation Details:
- OtpHttpResponse provides immutable, case-insensitive header access
- Supports multi-value headers (e.g., Set-Cookie)
- InputStream lifecycle remains managed by OtpHttpClient
- Breaking change: All ResponseMapper implementations require update

Files Modified:
- 13 source files updated to use response.body()
- 2 test files updated
- 1 integration test enhanced with header access tests

All existing tests pass. No functional changes to HTTP request behavior.
Only adds capability to access response headers when needed.
@vpaturet vpaturet force-pushed the feature/http-response-headers branch from 1b1af02 to ebe3585 Compare October 14, 2025 13:39
Copy link

codecov bot commented Oct 14, 2025

Codecov Report

❌ Patch coverage is 61.33333% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.17%. Comparing base (e895874) to head (fc4c68a).
⚠️ Report is 142 commits behind head on dev-2.x.

Files with missing lines Patch % Lines
...rg/opentripplanner/framework/io/OtpHttpClient.java 26.66% 22 Missing ⚠️
.../opentripplanner/framework/io/OtpHttpResponse.java 92.30% 1 Missing and 1 partial ⚠️
...anner/ext/siri/updater/azure/SiriAzureUpdater.java 0.00% 1 Missing ⚠️
...anner/ext/vehicleparking/bikely/BikelyUpdater.java 0.00% 1 Missing ⚠️
.../updater/alert/gtfs/GtfsRealtimeAlertsUpdater.java 0.00% 1 Missing ⚠️
...ipplanner/updater/support/siri/SiriHttpLoader.java 0.00% 1 Missing ⚠️
...r/google/GooglePubsubEstimatedTimetableSource.java 0.00% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             dev-2.x    #6971      +/-   ##
=============================================
+ Coverage      72.13%   72.17%   +0.03%     
- Complexity     19673    19853     +180     
=============================================
  Files           2127     2156      +29     
  Lines          79562    80090     +528     
  Branches        8041     8089      +48     
=============================================
+ Hits           57396    57804     +408     
- Misses         19332    19438     +106     
- Partials        2834     2848      +14     

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

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vpaturet vpaturet self-assigned this Oct 14, 2025
@vpaturet vpaturet added !Improvement A functional improvement or micro feature +Skip Changelog This is not a relevant change for a product owner since last release. labels Oct 14, 2025
@vpaturet vpaturet force-pushed the feature/http-response-headers branch 2 times, most recently from a984c7b to 51a14da Compare October 16, 2025 09:24
@vpaturet vpaturet force-pushed the feature/http-response-headers branch 3 times, most recently from 21114c2 to e9d6910 Compare October 16, 2025 13:21
@vpaturet vpaturet marked this pull request as ready for review October 16, 2025 13:31
@vpaturet vpaturet requested a review from a team as a code owner October 16, 2025 13:31
@vpaturet vpaturet force-pushed the feature/http-response-headers branch from e9d6910 to 38f4063 Compare October 16, 2025 13:34
@leonardehrenfried
Copy link
Member

leonardehrenfried commented Oct 16, 2025

If you add the label "Integration Test", then they are run for this PR.

testower
testower previously approved these changes Oct 16, 2025
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need a more general strategy for handling response codes. We now have special cases for 204 and 304. I don't think there is a one-size-fits-all solution here and we will need to have different handling of response codes for different situations.

This would be my suggestion:

  • By default we fail on anything other than 200
  • We expose another api executeAndMapWithoutValidation() (or some better name) where you don't get response code validation and then your ResponseMapper can do whatever it wants depending on the response code. That way we don't need special logic in the OtpHttpClient for 204/304/whatever. This should be feasible now that the mapper gets the whole response.

}

// Handle NOT_MODIFIED response.
if (response.getEntity() == null) {

Choose a reason for hiding this comment

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

Suggestion: you could change this to if (response.getCode() == SC_NOT_MODIFIED) and move it to before the previous if statement. I think that would make the logic more straightforward.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

private static boolean isFailedRequest(org.apache.hc.core5.http.HttpResponse response) {
return (
(response.getCode() < SC_OK || response.getCode() >= SC_REDIRECTION) &&
response.getCode() != SC_NOT_MODIFIED

Choose a reason for hiding this comment

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

It's a bit inconsistent to add an exception for 304. I think the correct thing in that case would be to treat all 3XX as non-failed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems to me that OTP cannot process correctly 3XX responses, apart from 304.
I don't think we have support for redirection for example.

response.getHeaders(),
response.getCode()
);
return contentMapper.apply(httpResponse);

Choose a reason for hiding this comment

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

I think contentMapper should be renamed responseMapper now. For all places in this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

@vpaturet vpaturet added the +Integration Test Activate the integration tests on PR label Oct 17, 2025
@vpaturet
Copy link
Contributor Author

I think we need a more general strategy for handling response codes. We now have special cases for 204 and 304. I don't think there is a one-size-fits-all solution here and we will need to have different handling of response codes for different situations.

This would be my suggestion:

* By default we fail on anything other than 200

* We expose another api `executeAndMapWithoutValidation()` (or some better name) where you don't get response code validation and then your `ResponseMapper` can do whatever it wants depending on the response code. That way we don't need special logic in the OtpHttpClient for 204/304/whatever. This should be feasible now that the mapper gets the whole response.

We can discuss this in the developer meeting.

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

Labels

!Improvement A functional improvement or micro feature +Integration Test Activate the integration tests on PR +Skip Changelog This is not a relevant change for a product owner since last release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants