Refactors httpbin controller into its own test class (#219)

This commit is contained in:
Biju Kunjummen
2018-03-02 08:04:39 -08:00
committed by Spencer Gibb
parent 4ed06c46c3
commit 1ca71510d0
2 changed files with 135 additions and 107 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,12 +17,7 @@
package org.springframework.cloud.gateway.test;
import java.io.IOException;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -40,19 +35,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
@@ -60,8 +44,6 @@ import com.netflix.loadbalancer.ServerList;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_HANDLER_MAPPER_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* @author Spencer Gibb
@@ -87,8 +69,6 @@ public class BaseWebClientTests {
this.testClient = WebTestClient.bindToServer().baseUrl(baseUri).build();
}
@RestController
@RequestMapping("/httpbin")
@Configuration
@RibbonClients({
@RibbonClient(name = "testservice", configuration = TestRibbonConfig.class),
@@ -96,93 +76,11 @@ public class BaseWebClientTests {
})
@Import(PermitAllSecurityConfiguration.class)
protected static class DefaultTestConfig {
private static final Log log = LogFactory.getLog(DefaultTestConfig.class);
@RequestMapping("/")
public String home(ServerWebExchange exchange) {
return "httpbin compatible home";
}
@RequestMapping(path = "/headers", method = {RequestMethod.GET, RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String, Object> headers(ServerWebExchange exchange) {
HashMap<String, Object> map = new HashMap<>();
addHeaders(exchange, map);
return map;
}
private void addHeaders(ServerWebExchange exchange, HashMap<String, Object> map) {
HashMap<String, String> headers = new HashMap<>();
exchange.getRequest().getHeaders().forEach((name, values) -> {
if (log.isDebugEnabled()) {
log.debug("Header, name: "+name+", "+values);
}
headers.put(name, values.get(0));
});
map.put("headers", headers);
}
@RequestMapping(path = "/delay/{sec}", produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String, Object> get(ServerWebExchange exchange, @PathVariable int sec) throws InterruptedException {
int delay = Math.min(sec, 10);
Thread.sleep(delay * 1000);
return get(exchange);
}
@RequestMapping(path = "/get", produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String, Object> get(ServerWebExchange exchange) {
HashMap<String, Object> map = new HashMap<>();
addHeaders(exchange, map);
HashMap<String, String> params = new HashMap<>();
exchange.getRequest().getQueryParams().forEach((name, values) -> {
params.put(name, values.get(0));
});
map.put("args", params);
return map;
}
@RequestMapping(value = "/post", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map<String, Object>> postFormData(@RequestBody Mono<MultiValueMap<String, Part>> parts) {
// StringDecoder decoder = StringDecoder.allMimeTypes(true);
return parts.flux().flatMap(map -> Flux.fromIterable(map.values()))
.flatMap(map -> Flux.fromIterable(map))
.filter(part -> part instanceof FilePart)
.reduce(new HashMap<String, Object>(), (files, part) -> {
MediaType contentType = part.headers().getContentType();
long contentLength = part.headers().getContentLength();
files.put(part.name(), "data:"+contentType+";base64,"+contentLength); //TODO: get part data
return files;
}).map(files -> Collections.singletonMap("files", files));
}
@RequestMapping(path = "/post", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map<String, Object>> postUrlEncoded(ServerWebExchange exchange) throws IOException {
return post(exchange, null);
}
@RequestMapping(path = "/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map<String, Object>> post(ServerWebExchange exchange,
@RequestBody(required = false) String body) throws IOException {
HashMap<String, Object> ret = new HashMap<>();
ret.put("data", body);
HashMap<String, Object> form = new HashMap<>();
ret.put("form", form);
return exchange.getFormData().flatMap(map -> {
for (Map.Entry<String, List<String>> entry: map.entrySet()) {
for (String value : entry.getValue()) {
form.put(entry.getKey(), value);
}
}
return Mono.just(ret);
});
}
@RequestMapping("/status/{status}")
public ResponseEntity<String> status(@PathVariable int status) {
return ResponseEntity.status(status).body("Failed with "+status);
@Bean
public HttpBinCompatibleController httpBinController() {
return new HttpBinCompatibleController();
}
@Bean

View File

@@ -0,0 +1,130 @@
/*
* Copyright 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.springframework.cloud.gateway.test;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.IOException;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/httpbin")
public class HttpBinCompatibleController {
private static final Log log = LogFactory.getLog(HttpBinCompatibleController.class);
@RequestMapping("/")
public String home() {
return "httpbin compatible home";
}
@RequestMapping(path = "/headers", method = {
RequestMethod.GET, RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map<String, Object>> headers(ServerWebExchange exchange) {
return getHeaders(exchange);
}
@RequestMapping(path = "/delay/{sec}", produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map<String, Object>> get(ServerWebExchange exchange, @PathVariable int sec) throws InterruptedException {
int delay = Math.min(sec, 10);
return get(exchange).delayElement(Duration.ofSeconds(delay));
}
@RequestMapping(path = "/get", produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map<String, Object>> get(ServerWebExchange exchange) {
return getHeaders(exchange).map(map -> {
HashMap<String, Object> result = new HashMap<>(map);
HashMap<String, String> params = new HashMap<>();
exchange.getRequest().getQueryParams().forEach((name, values) -> {
params.put(name, values.get(0));
});
result.put("args", params);
return result;
});
}
@RequestMapping(value = "/post", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map<String, Object>> postFormData(@RequestBody Mono<MultiValueMap<String, Part>> parts) {
// StringDecoder decoder = StringDecoder.allMimeTypes(true);
return parts.flux().flatMap(map -> Flux.fromIterable(map.values()))
.flatMap(map -> Flux.fromIterable(map))
.filter(part -> part instanceof FilePart)
.reduce(new HashMap<String, Object>(), (files, part) -> {
MediaType contentType = part.headers().getContentType();
long contentLength = part.headers().getContentLength();
files.put(part.name(), "data:"+contentType+";base64,"+contentLength); //TODO: get part data
return files;
}).map(files -> Collections.singletonMap("files", files));
}
@RequestMapping(path = "/post", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map<String, Object>> postUrlEncoded(ServerWebExchange exchange) throws
IOException {
return post(exchange, null);
}
@RequestMapping(path = "/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map<String, Object>> post(ServerWebExchange exchange,
@RequestBody(required = false) String body) throws IOException {
HashMap<String, Object> ret = new HashMap<>();
ret.put("data", body);
HashMap<String, Object> form = new HashMap<>();
ret.put("form", form);
return exchange.getFormData().flatMap(map -> {
for (Map.Entry<String, List<String>> entry: map.entrySet()) {
for (String value : entry.getValue()) {
form.put(entry.getKey(), value);
}
}
return Mono.just(ret);
});
}
@RequestMapping("/status/{status}")
public ResponseEntity<String> status(@PathVariable int status) {
return ResponseEntity.status(status).body("Failed with "+status);
}
private Mono<Map<String, Object>> getHeaders(ServerWebExchange exchange) {
return Flux.fromIterable(exchange.getRequest().getHeaders().entrySet())
.collectMap(entry -> entry.getKey(), entry -> entry.getValue().get(0))
.map(map -> {
Map<String, Object> result = new HashMap<>();
result.put("headers", map);
return result;
});
}
}