Skip to content

Commit 79cea44

Browse files
kabirclaudegemini-code-assist[bot]
authored
fix: Allow POST requests without Content-Type header when body is empty (#759)
Per RFC 9110 §8.3, Content-Type header is only meaningful when a message body is present. The HTTP+JSON transport was incorrectly returning 415 (ContentTypeNotSupportedError) for POST requests with no body and no Content-Type header. This fix adds validateContentTypeForOptionalBody() method to handle endpoints like POST /tasks/{id}:cancel where the body is optional. When the body is null or empty, Content-Type validation is skipped. When body content is present, Content-Type must still be application/json. This allows bodyless POST requests to be processed correctly and return appropriate errors (404 TaskNotFoundError, 409 TaskNotCancelableError) instead of 415. Fixes #747 🦕 --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent c14ec7f commit 79cea44

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ public void getTask(RoutingContext rc) {
346346
*/
347347
@Route(regex = "^\\/(?<tenant>[^\\/]*\\/?)tasks\\/(?<taskId>[^/]+):cancel$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING)
348348
public void cancelTask(@Body String body, RoutingContext rc) {
349-
if (!validateContentType(rc)) {
349+
if (!validateContentTypeForOptionalBody(rc, body)) {
350350
return;
351351
}
352352
String taskId = rc.pathParam("taskId");
@@ -624,6 +624,25 @@ private boolean validateContentType(RoutingContext rc) {
624624
return true;
625625
}
626626

627+
/**
628+
* Check if the request content type is application/json when body content is present.
629+
* Per RFC 9110 §8.3, Content-Type is only meaningful when a message body is present.
630+
* Use this for endpoints where the body is optional.
631+
*
632+
* @param rc the routing context
633+
* @param body the request body (may be null or empty)
634+
* @return true if validation passes, false if Content-Type error should be returned
635+
*/
636+
private boolean validateContentTypeForOptionalBody(RoutingContext rc, @Nullable String body) {
637+
// If body is null or empty, Content-Type is not required
638+
if (body == null || body.isBlank()) {
639+
return true;
640+
}
641+
642+
// Body has content - validate Content-Type
643+
return validateContentType(rc);
644+
}
645+
627646
/**
628647
* Retrieves the public agent card for agent discovery.
629648
*

0 commit comments

Comments
 (0)