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

Reflecting the case-insensitivity of http headers #275

Merged
merged 2 commits into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void messageHashes() {

mh.expect( ExampleSystem.MODEL,
"ALL MESSAGES",
"D1FA41700482366067D91A38D0C4E233 0122 21.3 KiB",
"FD907B745292C2C0980111694D69A8E8 0122 21.3 KiB",
"REQUESTS --> USER",
"00000000000000000000000000000000 0000 0 B",
"RESPONSES <-- USER",
Expand All @@ -70,29 +70,29 @@ void messageHashes() {
"RESPONSES <-- WEB_UI",
"7F6603B1CDD0593C7CF9771790C07911 0002 151 B",
"REQUESTS --> UI",
"323C8E3297DC898D2793EDDF60D8C5EC 0014 1.9 KiB",
"7B274E372CB060D8AD2E171A1308684D 0014 1.9 KiB",
"RESPONSES <-- UI",
"A670C078235AEB12636A0D130438A0BF 0014 2.6 KiB",
"2A8921FF7B8A91F7503AD3A6CD8F11D6 0014 2.6 KiB",
"REQUESTS --> CORE",
"681B2BB38FB90027F44C8467727F8D58 0015 2.3 KiB",
"1DF594DDAA7A732ED57E86BBF5A46348 0015 2.3 KiB",
"RESPONSES <-- CORE",
"11BFA337817BB5B4C8AE414F410F271E 0015 3.7 KiB",
"D4A0C1DF9D0851FE08B0D622C9A911C9 0015 3.7 KiB",
"REQUESTS --> QUEUE",
"3A79459ABD8CA52EA136B5DC00F15787 0007 975 B",
"CB06D74485A51EE84AA11C58B7BBE764 0007 975 B",
"RESPONSES <-- QUEUE",
"63C8D46EC4602B3FDC93973FCC286190 0007 1.3 KiB",
"C4D61888FE5F3D71D0A2EBCF9894CAC8 0007 1.3 KiB",
"REQUESTS --> STORE",
"A01276774007C68063E237FE73FC1C95 0006 939 B",
"774BC6DDD7772EE419E8705E1A0BBA34 0006 939 B",
"RESPONSES <-- STORE",
"50EF3C22818B95725B78A802470AD28B 0006 1.1 KiB",
"3DD66292776363BB0FC0E5F2443DDD7C 0006 1.1 KiB",
"REQUESTS --> DB",
"A06D030C1A8192CFE446CD5893217196 0008 2.6 KiB",
"RESPONSES <-- DB",
"3F7C757B6981B4A5844357C399720641 0008 1.1 KiB",
"REQUESTS --> HISTOGRAM",
"51B9735B70AE590E97230E245263CC7B 0009 1.1 KiB",
"BF8DDDB8D319B876FADD333BCB149E4F 0009 1.1 KiB",
"RESPONSES <-- HISTOGRAM",
"4C0832B1D6CB88891B5D6C902D35F7B1 0009 1.6 KiB" );
"1744EA709AEE2A8718AE343B15C399BC 0009 1.6 KiB" );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ public byte[] content() {
* @return The complete formatted body
*/
protected String enchunken( String content, boolean wire ) {
if( wire && "chunked".equals( get( header( "Transfer-Encoding" ) ) ) ) {
if( wire && "chunked".equals( get( header( "transfer-encoding" ) ) ) ) {
return String.format( ""
+ "%s\r\n" // chunk length
+ "%s\r\n" // chunk
Expand All @@ -196,7 +196,7 @@ protected String enchunken( String content, boolean wire ) {
* @return The actual content
*/
protected String dechunken( String chunked ) {
if( "chunked".equals( get( header( "Transfer-Encoding" ) ) ) ) {
if( "chunked".equals( get( header( "transfer-encoding" ) ) ) ) {
StringBuilder unchunked = new StringBuilder();
String input = "\r\n" + chunked; // so we can catch the first chunk with our regex
Matcher m = chunkLength.matcher( input );
Expand Down Expand Up @@ -248,16 +248,24 @@ protected static boolean isHeaderField( String field ) {
}

/**
* Creates a header field name. Note that
* <a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-field-names">header
* fields are case-insensitive</a>. Accordingly, this method will convert the
* supplied name to lower-case before adding the sigils that identify it as a
* header field.
*
* @param name The desired header name
* @return The value to pass as the field name in {@link #set(String, Object)}
* and {@link #get(String)}
*/
public static String header( String name ) {
return HEADER_PRESUFIX + name + HEADER_PRESUFIX;
return HEADER_PRESUFIX + name.toLowerCase() + HEADER_PRESUFIX;
}

/**
* The inverse of {@link #header(String)}
* The inverse of {@link #header(String)}. Bear in mind that
* {@link #header(String)} lower-casing behaviour is a destructive operation, so
* the inversion might not be perfect.
*
* @param name The value returned from {@link #header(String)}
* @return The value passed to that invocation of {@link #header(String)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ public HttpReq( byte[] content, Function<byte[], Message> bodyParse ) {
while( !lines.isEmpty() && !(headerLine = lines.removeFirst()).isEmpty() ) {
Matcher h = HEADER_LINE_PATTERN.matcher( headerLine );
if( h.matches() ) {
set( HEADER_PRESUFIX + h.group( "name" ).trim() + HEADER_PRESUFIX,
h.group( "value" ).trim() );
set( header( h.group( "name" ).trim() ), h.group( "value" ).trim() );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public HttpRes( byte[] content, Function<byte[], Message> bodyParse ) {
while( !lines.isEmpty() && !(headerLine = lines.removeFirst()).isEmpty() ) {
Matcher h = HEADER_LINE_PATTERN.matcher( headerLine );
if( h.matches() ) {
set( HEADER_PRESUFIX + h.group( "name" ).trim() + HEADER_PRESUFIX,
set( header( h.group( "name" ).trim() ),
h.group( "value" ).trim() );
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.mastercard.test.flow.msg.http;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

/**
* Exercises generic functionality of the {@link HttpMsg} superclass
*/
@SuppressWarnings("static-method")
class HttpMsgTest {

/**
* Illustrates the lower-casing behaviour of {@link HttpMsg#header(String)}
*/
@Test
void header() {
assertEquals( "^mixed-case^", HttpMsg.header( "MiXeD-cAsE" ),
"name is lower-cased and sigils are added" );

assertEquals( "mixed-case", HttpMsg.unheader( HttpMsg.header( "MiXeD-cAsE" ) ),
"unheader cannot restore the input casing" );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ void chunked() {

assertEquals( ""
+ "GET /foo/bar HTTP/1.1\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "transfer-encoding: chunked\r\n"
+ "\r\n"
+ "{\n"
+ " \"body\" : \"content\"\n"
Expand All @@ -250,7 +250,7 @@ void chunked() {

assertEquals( ""
+ "GET /foo/bar HTTP/1.1\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "transfer-encoding: chunked\r\n"
+ "\r\n"
+ "12\r\n" // remember this is hex
+ "{\"body\":\"content\"}\r\n"
Expand Down Expand Up @@ -295,7 +295,7 @@ void masking() {

assertEquals( ""
+ "GET /foo/_mp_/bar?q=_mq_&r=_mr_ HTTP/1.1\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "transfer-encoding: chunked\r\n"
+ "\r\n"
+ "{\n"
+ " \"body\" : \"masked\"\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ void bodyMasking() {
}

/**
* Honouring chunked Transfer-Encoding
* Honouring chunked <code>transfer-encoding</code>
*/
@Test
void chunked() {
Expand All @@ -242,15 +242,15 @@ void chunked() {
.set( "body", "content" );

assertEquals( "HTTP/1.1 200 OK\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "transfer-encoding: chunked\r\n"
+ "\r\n"
+ "{\n"
+ " \"body\" : \"content\"\n"
+ "}",
msg.assertable() );

assertEquals( "HTTP/1.1 200 OK\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "transfer-encoding: chunked\r\n"
+ "\r\n"
+ "12\r\n"
+ "{\"body\":\"content\"}\r\n"
Expand Down