Skip to content

Commit 57c0258

Browse files
committed
Handle URL Connection file not found 404
Fixes gh-3451
1 parent 2692645 commit 57c0258

File tree

3 files changed

+108
-6
lines changed

3 files changed

+108
-6
lines changed

spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/RestClientProxyExchange.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.cloud.gateway.server.mvc.handler;
1818

19+
import java.io.FileNotFoundException;
1920
import java.io.IOException;
2021
import java.io.InputStream;
2122
import java.io.OutputStream;
@@ -69,9 +70,15 @@ private static int copyBody(Request request, OutputStream outputStream) throws I
6970
}
7071

7172
private ServerResponse doExchange(Request request, ClientHttpResponse clientResponse) throws IOException {
72-
InputStream body = clientResponse.getBody();
73-
// put the body input stream in a request attribute so filters can read it.
74-
MvcUtils.putAttribute(request.getServerRequest(), MvcUtils.CLIENT_RESPONSE_INPUT_STREAM_ATTR, body);
73+
try {
74+
InputStream body = clientResponse.getBody();
75+
// put the body input stream in a request attribute so filters can read it.
76+
MvcUtils.putAttribute(request.getServerRequest(), MvcUtils.CLIENT_RESPONSE_INPUT_STREAM_ATTR, body);
77+
}
78+
catch (FileNotFoundException e) {
79+
// if using SimpleClientHttpRequestFactory
80+
return ServerResponse.notFound().build();
81+
}
7582
ServerResponse serverResponse = GatewayServerResponse.status(clientResponse.getStatusCode())
7683
.build((req, httpServletResponse) -> {
7784
try (clientResponse) {

spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -275,12 +275,12 @@ public void stripPrefixPostWorks() {
275275
public void setStatusGatewayRouterFunctionWorks() {
276276
restClient.get()
277277
.uri("/status/201")
278+
.header("Host", "www.setstatus.org")
278279
.exchange()
279280
.expectStatus()
280281
.isEqualTo(HttpStatus.TOO_MANY_REQUESTS)
281282
.expectHeader()
282-
.valueEquals("x-status", "201"); // .expectBody(String.class).isEqualTo("Failed
283-
// with 201");
283+
.valueEquals("x-status", "201");
284284
}
285285

286286
@Test
@@ -981,6 +981,11 @@ public void clientResponseBodyAttributeWorks() {
981981
});
982982
}
983983

984+
@Test
985+
public void notFoundWorks() {
986+
restClient.get().uri("/status/404").header("Host", "www.notfound.org").exchange().expectStatus().isNotFound();
987+
}
988+
984989
@SpringBootConfiguration
985990
@EnableAutoConfiguration
986991
@LoadBalancerClient(name = "httpbin", configuration = TestLoadBalancerConfig.Httpbin.class)
@@ -1032,7 +1037,7 @@ public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
10321037
public RouterFunction<ServerResponse> gatewayRouterFunctionsSetStatusAndAddRespHeader() {
10331038
// @formatter:off
10341039
return route("testsetstatus")
1035-
.GET("/status/{status}", http())
1040+
.GET("/status/{status}", host("**.setstatus.org"), http())
10361041
.before(new HttpbinUriResolver())
10371042
.after(setStatus(HttpStatus.TOO_MANY_REQUESTS))
10381043
.after(addResponseHeader("X-Status", "{status}"))
@@ -1600,6 +1605,16 @@ public RouterFunction<ServerResponse> gatewayRouterFunctionsReadResponseBody() {
16001605
// @formatter:on
16011606
}
16021607

1608+
@Bean
1609+
public RouterFunction<ServerResponse> gatewayRouterFunctions404() {
1610+
// @formatter:off
1611+
return route("testnotfound")
1612+
.GET("/status/404", host("**.notfound.org"), http())
1613+
.before(new HttpbinUriResolver())
1614+
.build();
1615+
// @formatter:on
1616+
}
1617+
16031618
@Bean
16041619
public FilterRegistrationBean myFilter() {
16051620
FilterRegistrationBean<MyFilter> reg = new FilterRegistrationBean<>(new MyFilter());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright 2013-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.gateway.server.mvc;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
import org.springframework.boot.SpringBootConfiguration;
23+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
24+
import org.springframework.boot.test.context.SpringBootTest;
25+
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
26+
import org.springframework.boot.test.web.server.LocalServerPort;
27+
import org.springframework.cloud.gateway.server.mvc.test.HttpbinTestcontainers;
28+
import org.springframework.cloud.gateway.server.mvc.test.HttpbinUriResolver;
29+
import org.springframework.cloud.gateway.server.mvc.test.TestLoadBalancerConfig;
30+
import org.springframework.cloud.gateway.server.mvc.test.client.TestRestClient;
31+
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
32+
import org.springframework.context.annotation.Bean;
33+
import org.springframework.test.context.ContextConfiguration;
34+
import org.springframework.web.servlet.function.RouterFunction;
35+
import org.springframework.web.servlet.function.ServerResponse;
36+
37+
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
38+
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
39+
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;
40+
41+
@SuppressWarnings("unchecked")
42+
@SpringBootTest(properties = { "spring.cloud.gateway.mvc.http-client.type=autodetect" },
43+
webEnvironment = WebEnvironment.RANDOM_PORT)
44+
@ContextConfiguration(initializers = HttpbinTestcontainers.class)
45+
public class SimpleHttpClientIntegrationTests {
46+
47+
static {
48+
// if set type to autodetect above
49+
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
50+
}
51+
52+
@LocalServerPort
53+
int port;
54+
55+
@Autowired
56+
TestRestClient restClient;
57+
58+
@Test
59+
public void simpleHttpClientNotFoundWorks() {
60+
restClient.get().uri("/status/404").header("Host", "www.notfound.org").exchange().expectStatus().isNotFound();
61+
}
62+
63+
@SpringBootConfiguration
64+
@EnableAutoConfiguration
65+
@LoadBalancerClient(name = "httpbin", configuration = TestLoadBalancerConfig.Httpbin.class)
66+
protected static class TestConfiguration {
67+
68+
@Bean
69+
public RouterFunction<ServerResponse> gatewayRouterFunctions404() {
70+
// @formatter:off
71+
return route("testnotfound")
72+
.GET("/status/404", host("**.notfound.org"), http())
73+
.before(new HttpbinUriResolver())
74+
.build();
75+
// @formatter:on
76+
}
77+
78+
}
79+
80+
}

0 commit comments

Comments
 (0)