Skip to content
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

Support for Case-Sensitive HTTP Headers in Karate Mock Server #2653

Merged
merged 4 commits into from
Feb 17, 2025

Conversation

srmppn
Copy link

@srmppn srmppn commented Feb 16, 2025

Description

Dear Karate Mock Team,

I truly appreciate your time and effort in developing and maintaining the Karate mock server as an open-source project.

Recently, I needed to integrate the mock server for testing with a legacy system that requires HTTP/1 headers or specific header formats. For example, the system expects the header exactly as "X-Special-Header" and not "x-special-header" to function correctly.

I noticed that even after configuring the lowerCaseResponseHeaders property to false, the headers were still converted to lowercase due to Armeria server’s adherence to HTTP/2/gRPC standards.

Fortunately, the Armeria team has provided an interface for mapping HTTP/2 headers to HTTP/1 headers Armeria Issue #3196., but it requires manual mapping. My initial thought was to provide an option for specifying HTTP/1 header configurations, for example:

java -jar karate.jar --http1header='X-Special-Header'

This option could then be used to map headers in the Armeria server like so:

sb.http1HeaderNaming(http2Header -> http1Headers.getOrDefault(http2Header, http2Header))

However, I believe it would be a better solution to collect the original HTTP headers directly from the provided Scenario and use them as references for mapping, rather than manually specifying each header through configuration options.

I have made an initial attempt at implementing this solution, and it worked as I tested myself. However, this may not work when performing high TPS or load testing. My solution currently uses the same httpHeaderReference from HttpHeaderTracking, but different features might require different header formats. For instance:

Scenario: pathMatches('/api/test1')  
    * def responseHeaders = { "X-Special-Header": "test" }  

Scenario: pathMatches('/api/test2')  
    * def responseHeaders = { "X-special-header": "test" }  

In such cases, headers may override each other since HTTP/2 uses lowercase for mapping. While we could add the scenario as a prefix to the httpHeaderReference, I believe it's a rare situation to have different scenarios with different header formats. Therefore, I have provided a simpler solution for now.

Thank you for your attention, and I look forward to hearing your thoughts on this.

Best regards,

@@ -132,6 +132,9 @@ public class Main implements Callable<Void> {
@Option(names = {"-H", "--hook"}, split = ",", description = "class name of a RuntimeHook (or RuntimeHookFactory) to add")
List<String> hookFactoryClassNames;

@Option(names = {"--keep-original-headers"}, description = "keeping original headers given in the mock scenario or configure")
Copy link
Author

Choose a reason for hiding this comment

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

Allow the mock server to enable or disable the headers format, as not everyone may need to use HTTP/1 headers like I do 👍

@ptrthomas
Copy link
Member

@srmppn thanks, will merge - can you create a new issue just for better visibility when we make the next release (no ETA yet, will be 1.5.2)

@ptrthomas ptrthomas merged commit cc5236e into karatelabs:develop Feb 17, 2025
3 checks passed
@srmppn
Copy link
Author

srmppn commented Feb 17, 2025

Should I add the flag --keep-original-headers to the documentation as well 🤔

@ptrthomas
Copy link
Member

@srmppn yes that would be good. for historical reasons the CLI docs are here: https://github.com/karatelabs/karate/tree/master/karate-netty#usage

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

Successfully merging this pull request may close these issues.

2 participants