From c780960624c796ef7c086fcb8e6f19e41bb993d9 Mon Sep 17 00:00:00 2001 From: jansupol Date: Tue, 13 Feb 2024 13:09:41 +0100 Subject: [PATCH] Prevent Response with Status 1xx, 204, 205 & 304 Signed-off-by: jansupol --- .../internal/OutboundJaxrsResponse.java | 18 ++++++++-- .../jersey/internal/localization.properties | 6 +++- .../jersey/message/internal/ResponseTest.java | 33 ++++++++++++++++++- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundJaxrsResponse.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundJaxrsResponse.java index 4db8b21d92..0bcc4f6e0a 100644 --- a/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundJaxrsResponse.java +++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundJaxrsResponse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -380,9 +380,21 @@ public jakarta.ws.rs.core.Response build() { if (st == null) { st = context.hasEntity() ? Status.OK : Status.NO_CONTENT; } + + checkStatusAndEntity(st); + return new OutboundJaxrsResponse(st, new OutboundMessageContext(context)); } + private void checkStatusAndEntity(StatusType status) { + if (status.getFamily() == Status.Family.INFORMATIONAL + || status == Status.NO_CONTENT || status == Status.RESET_CONTENT || status == Status.NOT_MODIFIED) { + if (context.hasEntity()) { + throw new IllegalArgumentException(LocalizationMessages.RESPONSE_HAS_ENTITY(status.getStatusCode())); + } + } + } + @SuppressWarnings({"CloneDoesntCallSuperClone", "CloneDoesntDeclareCloneNotSupportedException"}) @Override public ResponseBuilder clone() { @@ -392,7 +404,7 @@ public ResponseBuilder clone() { @Override public jakarta.ws.rs.core.Response.ResponseBuilder status(StatusType status) { if (status == null) { - throw new IllegalArgumentException("Response status must not be 'null'"); + throw new IllegalArgumentException(LocalizationMessages.RESPONSE_STATUS_NULL()); } this.status = status; @@ -402,7 +414,7 @@ public jakarta.ws.rs.core.Response.ResponseBuilder status(StatusType status) { @Override public ResponseBuilder status(int status, final String reasonPhrase) { if (status < 100 || status > 599) { - throw new IllegalArgumentException("Response status must not be less than '100' or greater than '599'"); + throw new IllegalArgumentException(LocalizationMessages.RESPONSE_STATUS_OUT_OF_BOUNDS()); } final Status.Family family = Status.Family.familyOf(status); diff --git a/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties b/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties index b60bf25045..97b948b64e 100644 --- a/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties +++ b/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2018 Payara Foundation and/or its affiliates. # # This program and the accompanying materials are made available under the @@ -132,6 +132,10 @@ provider.could.not.be.created=The class {0} implementing provider {1} could not provider.not.found=The class {0} implementing the provider {1} is not found. The provider implementation is ignored. query.param.null=One or more of query value parameters are null. response.closed=Response is closed. +response.has.entity=A response with status {0} must not have an entity. +response.status.null=Response status must not be 'null'. +response.status.out.of.bounds=Response status must not be less than '100' or greater than '599'. + # {0} - fully qualified name of connector class; {1} - header names some.headers.not.sent=There are some request headers that have not been sent by connector [{0}]. Probably you added \ those headers in WriterInterceptor or MessageBodyWriter. That feature is not supported by the connector. Please, \ diff --git a/core-common/src/test/java/org/glassfish/jersey/message/internal/ResponseTest.java b/core-common/src/test/java/org/glassfish/jersey/message/internal/ResponseTest.java index ec4421bdc4..bc35aedb11 100644 --- a/core-common/src/test/java/org/glassfish/jersey/message/internal/ResponseTest.java +++ b/core-common/src/test/java/org/glassfish/jersey/message/internal/ResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -81,4 +81,35 @@ public void reasonPhraseTest() { assertEquals(123, response.getStatus()); assertEquals("test", response.getStatusInfo().getReasonPhrase()); } + + @Test + public void testEntityForbidden() { + try { + Response.status(Status.NO_CONTENT).entity("test").build(); + throw new IllegalStateException("NO CONTENT with entity"); + } catch (IllegalArgumentException e) { + // ok + } + + try { + Response.status(Status.NOT_MODIFIED).entity("test").build(); + throw new IllegalStateException("NOT MODIFIED with entity"); + } catch (IllegalArgumentException e) { + // ok + } + + try { + Response.status(Status.RESET_CONTENT).entity("test").build(); + throw new IllegalStateException("RESET CONTENT with entity"); + } catch (IllegalArgumentException e) { + // ok + } + + try { + Response.status(152).entity("test").build(); + throw new IllegalStateException("INFORMATIONAL with entity"); + } catch (IllegalArgumentException e) { + // ok + } + } }