Skip to content

Commit

Permalink
[DwC] Limit DwC Headers when Connecting to Megaclite (#559)
Browse files Browse the repository at this point in the history
  • Loading branch information
MatKuhr authored Aug 27, 2024
1 parent 3168bbb commit 921f74c
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
package com.sap.cloud.sdk.cloudplatform.connectivity;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
Expand All @@ -26,6 +27,41 @@ public class DwcHeaderProvider implements DestinationHeaderProvider
@Getter
private static final DwcHeaderProvider instance = new DwcHeaderProvider();

@Nonnull
private final Collection<String> limiters;

/**
* Default constructor.
*/
public DwcHeaderProvider()
{
this(List.of());
}

DwcHeaderProvider( @Nonnull final Collection<String> limiters )
{
this.limiters = limiters.stream().map(String::toLowerCase).toList();
}

/**
* The HA Proxy on CF imposes a limit on header size. When accessing the destination service via megaclite not all
* DwC headers are required.
*
* @return A header provider configured to only forward dwc headers required for destination service access.
*/
static DwcHeaderProvider limitedHeaderProviderForDestinationAccess()
{
return new DwcHeaderProvider(
List
.of(
"dwc-tenant",
"dwc-subdomain",
"dwc-jwt",
"dwc-ias-jwt",
"dwc-megaclite-xsuaa-authorities",
"dwc-operation-id"));
}

@Nonnull
@Override
public List<Header> getHeaders( @Nonnull final DestinationRequestContext requestContext )
Expand All @@ -45,6 +81,7 @@ public List<Header> getHeaders( @Nonnull final DestinationRequestContext request
.getHeaderNames()
.stream()
.filter(name -> name.toLowerCase(Locale.ENGLISH).startsWith("dwc-"))
.filter(name -> limiters.isEmpty() || limiters.contains(name.toLowerCase(Locale.ENGLISH)))
.flatMap(name -> headerContainer.getHeaderValues(name).stream().map(value -> new Header(name, value)))
.collect(Collectors.toList());
if( headers.isEmpty() ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ HttpDestination getMegacliteDestination( @Nullable final String path )
return DefaultHttpDestination
.builder(destinationUrl)
.securityConfiguration(SecurityConfigurationStrategy.FROM_PLATFORM)
.headerProviders(DwcHeaderProvider.getInstance())
.headerProviders(DwcHeaderProvider.limitedHeaderProviderForDestinationAccess())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,31 @@ void testCaseInsensitive()
new Header("dwc-header1", "dwc-value1"),
new Header("dwc-header2", "dwc-value2"));
}

@Test
void testLimitedHeaders()
{
final DestinationRequestContext requestContext = mock(DestinationRequestContext.class);

final RequestHeaderContainer headers =
DefaultRequestHeaderContainer
.builder()
.withHeader("header1", "value1")
.withHeader("DWC-header1", "dwc-value1")
.withHeader("dWc-subdomain", "subdomain")
.withHeader("dWc-TENANT", "tenant")
.withHeader("dwc-jwt", "jwt")
.build();

var sut = DwcHeaderProvider.limitedHeaderProviderForDestinationAccess();
final List<Header> dwcHeaders =
RequestHeaderAccessor.executeWithHeaderContainer(headers, () -> sut.getHeaders(requestContext));

assertThat(dwcHeaders).hasSize(3);
assertThat(dwcHeaders)
.containsExactlyInAnyOrder(
new Header("dwc-subdomain", "subdomain"),
new Header("dwc-tenant", "tenant"),
new Header("dwc-jwt", "jwt"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void testSubscriberDestination()
assertThat(result.getSecurityConfigurationStrategy()).isEqualTo(SecurityConfigurationStrategy.FROM_PLATFORM);
assertThat(result.getProxyType()).contains(ProxyType.INTERNET);
assertThat(DefaultHttpDestination.fromDestination(result).customHeaderProviders)
.contains(DwcHeaderProvider.getInstance());
.hasAtLeastOneElementOfType(DwcHeaderProvider.class);
}

@Test
Expand All @@ -142,7 +142,7 @@ void testProviderDestination()
assertThat(result.getSecurityConfigurationStrategy()).isEqualTo(SecurityConfigurationStrategy.FROM_PLATFORM);
assertThat(result.getProxyType()).contains(ProxyType.INTERNET);
assertThat(DefaultHttpDestination.fromDestination(result).customHeaderProviders)
.contains(DwcHeaderProvider.getInstance());
.hasAtLeastOneElementOfType(DwcHeaderProvider.class);
}

@Test
Expand Down
2 changes: 2 additions & 0 deletions release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
- Upgrade to version `1.66.0` of `gRPC` dependencies coming in transitively when using `connectivity-ztis`
- Improve the error handling for OData batch requests.
In case an OData error is given within a batch response it will now be parsed and returned as `ODataServiceErrorException`.
- Reduce the amount of DwC headers sent when communicating via megaclite.
This reduces the risk of exceeding the maximum header size limit of the Cloud Foundry infrastructure.
- Improve the error handling for requests to the destination service.
In case of an error a potential response body will now be logged with the error message.

Expand Down

0 comments on commit 921f74c

Please sign in to comment.