Skip to content

Commit

Permalink
fix(webhook): Fix webhook and possible http client nullpointer except…
Browse files Browse the repository at this point in the history
…ion (#3518)

* fix(webhook): Fix webhook and possible http client nullpointer exception

* fix(http-client): Ignore empty entries
  • Loading branch information
sbuettner authored Oct 21, 2024
1 parent ed511b2 commit c004654
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -85,10 +84,10 @@ protected static ResponseEntity<?> toResponseEntity(WebhookHttpResponse webhookH
}

protected static Object escapeValue(Object value) {
if (Objects.requireNonNull(value) instanceof String s) {
return HtmlUtils.htmlEscape(s);
}
return value;
return switch (value) {
case String s -> HtmlUtils.htmlEscape(s);
case null, default -> value;
};
}

@RequestMapping(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
<dependency>
<groupId>io.camunda.connector</groupId>
<artifactId>connector-runtime-spring</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.camunda.connector</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,58 @@ public void testSuccessfulProcessingWithResponseBodyExpression() throws Exceptio
assertEquals("test", responseEntity.getBody().tenantId());
}

@Test
public void testSuccessfulProcessingWithPartialResponseBodyExpression() throws Exception {
var webhookConnectorExecutable = mock(WebhookConnectorExecutable.class);

var element =
new InboundConnectorElement(
Map.of("inbound.context", "myPath"),
null,
new ProcessElement("processA", 1, 1, "myElement", "myTenant"));

var correlationHandlerMock = mock(InboundCorrelationHandler.class);
var factory = new DefaultProcessElementContextFactory(secretProvider, (e) -> {}, mapper);
when(correlationHandlerMock.correlate(any(), any()))
.thenReturn(
new CorrelationResult.Success.ProcessInstanceCreated(
factory.createContext(element), 1L, "test"));

WebhookResult webhookResult = mock(WebhookResult.class);
when(webhookResult.request()).thenReturn(new MappedHttpRequest(Map.of(), Map.of(), Map.of()));
when(webhookResult.response()).thenReturn((c) -> WebhookHttpResponse.ok(null));
when(webhookConnectorExecutable.triggerWebhook(any(WebhookProcessingPayload.class)))
.thenReturn(webhookResult);

var webhookDef = webhookDefinition("processA", 1, "myPath");
var webhookContext =
new InboundConnectorContextImpl(
secretProvider,
v -> {},
webhookDef,
correlationHandlerMock,
(e) -> {},
mapper,
EvictingQueue.create(10));

// Register webhook function 'implementation'
webhookConnectorRegistry.register(
new RegisteredExecutable.Activated(webhookConnectorExecutable, webhookContext));

deployProcess("processA");

ResponseEntity<?> responseEntity =
controller.inbound(
"myPath",
new HashMap<>(),
"{}".getBytes(),
new HashMap<>(),
new MockHttpServletRequest());

assertEquals(200, responseEntity.getStatusCode().value());
assertNull(responseEntity.getBody());
}

public void deployProcess(String bpmnProcessId) {
zeebeClient
.newDeployResourceCommand()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.io.BufferedInputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
Expand Down Expand Up @@ -127,11 +126,14 @@ private HttpEntity createMultiPartEntity(Map<?, ?> body, ContentType contentType
builder.setMode(HttpMultipartMode.LEGACY);
Optional.ofNullable(contentType.getParameter("boundary")).ifPresent(builder::setBoundary);
for (Map.Entry<?, ?> entry : body.entrySet()) {
if (Objects.requireNonNull(entry.getValue()) instanceof Document document) {
streamDocumentContent(entry, document, builder);
} else {
builder.addTextBody(
String.valueOf(entry.getKey()), String.valueOf(entry.getValue()), MULTIPART_FORM_DATA);
switch (entry.getValue()) {
case Document document -> streamDocumentContent(entry, document, builder);
case null -> {}
default ->
builder.addTextBody(
String.valueOf(entry.getKey()),
String.valueOf(entry.getValue()),
MULTIPART_FORM_DATA);
}
}
return builder.build();
Expand Down

0 comments on commit c004654

Please sign in to comment.