Turned on checkstyle
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -21,10 +21,17 @@ import org.springframework.cloud.function.context.catalog.FunctionInspector;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
|
||||
/**
|
||||
* Simple implementation of a {@link StringConverter}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class BasicStringConverter implements StringConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConfigurableListableBeanFactory registry;
|
||||
|
||||
private FunctionInspector inspector;
|
||||
|
||||
public BasicStringConverter(FunctionInspector inspector,
|
||||
@@ -35,16 +42,14 @@ public class BasicStringConverter implements StringConverter {
|
||||
|
||||
@Override
|
||||
public Object convert(Object function, String value) {
|
||||
if (conversionService == null && registry != null) {
|
||||
ConversionService conversionService = this.registry
|
||||
.getConversionService();
|
||||
if (this.conversionService == null && this.registry != null) {
|
||||
ConversionService conversionService = this.registry.getConversionService();
|
||||
this.conversionService = conversionService != null ? conversionService
|
||||
: new DefaultConversionService();
|
||||
}
|
||||
Class<?> type = inspector.getInputType(function);
|
||||
return conversionService.canConvert(String.class, type)
|
||||
? conversionService.convert(value, type)
|
||||
: value;
|
||||
Class<?> type = this.inspector.getInputType(function);
|
||||
return this.conversionService.canConvert(String.class, type)
|
||||
? this.conversionService.convert(value, type) : value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2019 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -34,6 +34,8 @@ import java.util.stream.Stream;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.cloud.function.context.catalog.FunctionInspector;
|
||||
@@ -65,9 +67,6 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -123,23 +122,27 @@ public class RequestProcessor {
|
||||
.flatMap(body -> response(wrapper, body, false));
|
||||
}
|
||||
|
||||
public Mono<ResponseEntity<?>> post(FunctionWrapper wrapper, String body, boolean stream) {
|
||||
public Mono<ResponseEntity<?>> post(FunctionWrapper wrapper, String body,
|
||||
boolean stream) {
|
||||
Object function = wrapper.handler();
|
||||
Class<?> inputType = inspector.getInputType(function);
|
||||
Class<?> inputType = this.inspector.getInputType(function);
|
||||
Type itemType = getItemType(function);
|
||||
|
||||
Object input = body;
|
||||
|
||||
if (StringUtils.hasText(body)) {
|
||||
if (this.shouldUseJsonConversion(body, wrapper.headers.getContentType())) {
|
||||
Type jsonType = body.startsWith("[") && Collection.class.isAssignableFrom(inputType) || body.startsWith("{") ? inputType : Collection.class;
|
||||
Type jsonType = body.startsWith("[")
|
||||
&& Collection.class.isAssignableFrom(inputType)
|
||||
|| body.startsWith("{") ? inputType : Collection.class;
|
||||
if (body.startsWith("[")) {
|
||||
jsonType = ResolvableType.forClassWithGenerics((Class<?>)jsonType, (Class<?>) itemType).getType();
|
||||
jsonType = ResolvableType.forClassWithGenerics((Class<?>) jsonType,
|
||||
(Class<?>) itemType).getType();
|
||||
}
|
||||
input = mapper.toObject(body, jsonType);
|
||||
input = this.mapper.toObject(body, jsonType);
|
||||
}
|
||||
else {
|
||||
input = converter.convert(function, body);
|
||||
input = this.converter.convert(function, body);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +151,8 @@ public class RequestProcessor {
|
||||
|
||||
private boolean shouldUseJsonConversion(String body, MediaType contentType) {
|
||||
return (body.startsWith("[") || body.startsWith("{"))
|
||||
&& (contentType == null || (contentType != null && !"text".equalsIgnoreCase(contentType.getType())));
|
||||
&& (contentType == null || (contentType != null
|
||||
&& !"text".equalsIgnoreCase(contentType.getType())));
|
||||
}
|
||||
|
||||
public Mono<ResponseEntity<?>> stream(FunctionWrapper request) {
|
||||
@@ -171,7 +175,7 @@ public class RequestProcessor {
|
||||
Flux<?> flux;
|
||||
if (body != null) {
|
||||
if (Collection.class
|
||||
.isAssignableFrom(inspector.getInputType(wrapper.handler()))) {
|
||||
.isAssignableFrom(this.inspector.getInputType(wrapper.handler()))) {
|
||||
flux = Flux.just(body);
|
||||
}
|
||||
else {
|
||||
@@ -181,15 +185,18 @@ public class RequestProcessor {
|
||||
flux = Flux.fromIterable(iterable);
|
||||
}
|
||||
}
|
||||
else if (MultiValueMap.class.isAssignableFrom(inspector.getInputType(wrapper.handler()))) {
|
||||
else if (MultiValueMap.class
|
||||
.isAssignableFrom(this.inspector.getInputType(wrapper.handler()))) {
|
||||
flux = Flux.just(wrapper.params());
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Failed to determine input for function call with parameters: '" + wrapper.params
|
||||
+ "' and headers: `" + wrapper.headers + "`");
|
||||
throw new IllegalStateException(
|
||||
"Failed to determine input for function call with parameters: '"
|
||||
+ wrapper.params + "' and headers: `" + wrapper.headers
|
||||
+ "`");
|
||||
}
|
||||
|
||||
if (inspector.isMessage(function)) {
|
||||
if (this.inspector.isMessage(function)) {
|
||||
flux = messages(wrapper, function == null ? consumer : function, flux);
|
||||
}
|
||||
Mono<ResponseEntity<?>> responseEntityMono = null;
|
||||
@@ -224,7 +231,7 @@ public class RequestProcessor {
|
||||
|
||||
private Mono<ResponseEntity<?>> stream(FunctionWrapper request, Publisher<?> result) {
|
||||
BodyBuilder builder = ResponseEntity.ok();
|
||||
if (inspector.isMessage(request.handler())) {
|
||||
if (this.inspector.isMessage(request.handler())) {
|
||||
result = Flux.from(result)
|
||||
.doOnNext(value -> addHeaders(builder, (Message<?>) value))
|
||||
.map(message -> MessageUtils.unpack(request.handler(), message)
|
||||
@@ -242,7 +249,7 @@ public class RequestProcessor {
|
||||
Publisher<?> result, Boolean single, boolean getter) {
|
||||
|
||||
BodyBuilder builder = ResponseEntity.ok();
|
||||
if (inspector.isMessage(handler)) {
|
||||
if (this.inspector.isMessage(handler)) {
|
||||
result = Flux.from(result)
|
||||
.map(message -> MessageUtils.unpack(handler, message))
|
||||
.doOnNext(value -> addHeaders(builder, value))
|
||||
@@ -267,8 +274,8 @@ public class RequestProcessor {
|
||||
if (handler instanceof FluxWrapper) {
|
||||
handler = ((FluxWrapper<?>) handler).getTarget();
|
||||
}
|
||||
Class<?> type = inspector.getInputType(handler);
|
||||
Class<?> wrapper = inspector.getInputWrapper(handler);
|
||||
Class<?> type = this.inspector.getInputType(handler);
|
||||
Class<?> wrapper = this.inspector.getInputWrapper(handler);
|
||||
return Collection.class.isAssignableFrom(type) || Flux.class.equals(wrapper);
|
||||
}
|
||||
|
||||
@@ -276,8 +283,8 @@ public class RequestProcessor {
|
||||
if (handler instanceof FluxWrapper) {
|
||||
handler = ((FluxWrapper<?>) handler).getTarget();
|
||||
}
|
||||
Class<?> type = inspector.getOutputType(handler);
|
||||
Class<?> wrapper = inspector.getOutputWrapper(handler);
|
||||
Class<?> type = this.inspector.getOutputType(handler);
|
||||
Class<?> wrapper = this.inspector.getOutputWrapper(handler);
|
||||
if (Stream.class.isAssignableFrom(type)) {
|
||||
return false;
|
||||
}
|
||||
@@ -294,8 +301,7 @@ public class RequestProcessor {
|
||||
ResolvableType actualType = elementType;
|
||||
Class<?> resolvedType = elementType.resolve();
|
||||
ReactiveAdapter adapter = (resolvedType != null
|
||||
? getAdapterRegistry().getAdapter(resolvedType)
|
||||
: null);
|
||||
? getAdapterRegistry().getAdapter(resolvedType) : null);
|
||||
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
@@ -360,10 +366,8 @@ public class RequestProcessor {
|
||||
}
|
||||
|
||||
private Throwable handleReadError(MethodParameter parameter, Throwable ex) {
|
||||
return (ex instanceof DecodingException
|
||||
? new ServerWebInputException("Failed to read HTTP message", parameter,
|
||||
ex)
|
||||
: ex);
|
||||
return (ex instanceof DecodingException ? new ServerWebInputException(
|
||||
"Failed to read HTTP message", parameter, ex) : ex);
|
||||
}
|
||||
|
||||
private ServerWebInputException handleMissingBody(MethodParameter param) {
|
||||
@@ -377,13 +381,14 @@ public class RequestProcessor {
|
||||
|
||||
private Publisher<?> value(Function<Publisher<?>, Publisher<?>> function,
|
||||
Publisher<String> value) {
|
||||
Flux<?> input = Flux.from(value).map(body -> converter.convert(function, body));
|
||||
Flux<?> input = Flux.from(value)
|
||||
.map(body -> this.converter.convert(function, body));
|
||||
return Mono.from(function.apply(input));
|
||||
}
|
||||
|
||||
private Object getTargetFunction(Object function) {
|
||||
// we need to get the actual un-fluxed function so we can interrogate for types
|
||||
Object target = inspector.getRegistration(function).getTarget();
|
||||
Object target = this.inspector.getRegistration(function).getTarget();
|
||||
if (target instanceof FluxWrapper) {
|
||||
target = ((FluxWrapper<?>) target).getTarget();
|
||||
}
|
||||
@@ -391,12 +396,12 @@ public class RequestProcessor {
|
||||
}
|
||||
|
||||
private Type getItemType(Object function) {
|
||||
Class<?> inputType = inspector.getInputType(function);
|
||||
Class<?> inputType = this.inspector.getInputType(function);
|
||||
if (!Collection.class.isAssignableFrom(inputType)) {
|
||||
return inputType;
|
||||
}
|
||||
Type type = inspector.getRegistration(this.getTargetFunction(function)).getType()
|
||||
.getType();
|
||||
Type type = this.inspector.getRegistration(this.getTargetFunction(function))
|
||||
.getType().getType();
|
||||
if (type instanceof ParameterizedType) {
|
||||
type = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
}
|
||||
@@ -417,6 +422,9 @@ public class RequestProcessor {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for functions.
|
||||
*/
|
||||
public static class FunctionWrapper {
|
||||
|
||||
private final Function<Publisher<?>, Publisher<?>> function;
|
||||
@@ -442,7 +450,8 @@ public class RequestProcessor {
|
||||
}
|
||||
|
||||
public Object handler() {
|
||||
return function != null ? function : consumer != null ? consumer : supplier;
|
||||
return this.function != null ? this.function
|
||||
: this.consumer != null ? this.consumer : this.supplier;
|
||||
}
|
||||
|
||||
public Function<Publisher<?>, Publisher<?>> function() {
|
||||
@@ -458,7 +467,7 @@ public class RequestProcessor {
|
||||
}
|
||||
|
||||
public MultiValueMap<String, String> params() {
|
||||
return params;
|
||||
return this.params;
|
||||
}
|
||||
|
||||
public HttpHeaders headers() {
|
||||
@@ -488,5 +497,7 @@ public class RequestProcessor {
|
||||
public Publisher<String> argument() {
|
||||
return this.argument;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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
|
||||
* 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,
|
||||
@@ -23,6 +23,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
// @checkstyle:off
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
public class RestApplication {
|
||||
@@ -30,5 +31,6 @@ public class RestApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(RestApplication.class, args);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// @checkstyle:on
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.web;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -23,15 +23,33 @@ package org.springframework.cloud.function.web.constants;
|
||||
*/
|
||||
public abstract class WebRequestConstants {
|
||||
|
||||
/**
|
||||
* Function attribute name.
|
||||
*/
|
||||
public static final String FUNCTION = WebRequestConstants.class.getName()
|
||||
+ ".function";
|
||||
|
||||
/**
|
||||
* Consumer attribute name.
|
||||
*/
|
||||
public static final String CONSUMER = WebRequestConstants.class.getName()
|
||||
+ ".consumer";
|
||||
|
||||
/**
|
||||
* Supplier attribute name.
|
||||
*/
|
||||
public static final String SUPPLIER = WebRequestConstants.class.getName()
|
||||
+ ".supplier";
|
||||
|
||||
/**
|
||||
* Argument attribute name.
|
||||
*/
|
||||
public static final String ARGUMENT = WebRequestConstants.class.getName()
|
||||
+ ".argument";
|
||||
public static final String HANDLER = WebRequestConstants.class.getName()
|
||||
+ ".handler";
|
||||
|
||||
/**
|
||||
* Handler attribute name.
|
||||
*/
|
||||
public static final String HANDLER = WebRequestConstants.class.getName() + ".handler";
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -21,6 +21,7 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.function.web.RequestProcessor;
|
||||
import org.springframework.cloud.function.web.RequestProcessor.FunctionWrapper;
|
||||
@@ -38,8 +39,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Mark Fisher
|
||||
@@ -58,7 +57,7 @@ public class FunctionController {
|
||||
public Mono<ResponseEntity<?>> form(ServerWebExchange request) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return request.getFormData().doOnSuccess(params -> wrapper.params(params))
|
||||
.then(Mono.defer(() -> processor.post(wrapper, null, false)));
|
||||
.then(Mono.defer(() -> this.processor.post(wrapper, null, false)));
|
||||
}
|
||||
|
||||
@PostMapping(path = "/**", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@@ -67,7 +66,7 @@ public class FunctionController {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return request.getMultipartData()
|
||||
.doOnSuccess(params -> wrapper.params(multi(params)))
|
||||
.then(Mono.defer(() -> processor.post(wrapper, null, false)));
|
||||
.then(Mono.defer(() -> this.processor.post(wrapper, null, false)));
|
||||
}
|
||||
|
||||
private MultiValueMap<String, String> multi(MultiValueMap<String, Part> body) {
|
||||
@@ -87,7 +86,7 @@ public class FunctionController {
|
||||
@ResponseBody
|
||||
public Mono<ResponseEntity<?>> post(ServerWebExchange request) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.post(wrapper, request);
|
||||
return this.processor.post(wrapper, request);
|
||||
}
|
||||
|
||||
@PostMapping(path = "/**")
|
||||
@@ -95,7 +94,7 @@ public class FunctionController {
|
||||
public Mono<ResponseEntity<?>> post(ServerWebExchange request,
|
||||
@RequestBody(required = false) String body) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.post(wrapper, body, false);
|
||||
return this.processor.post(wrapper, body, false);
|
||||
}
|
||||
|
||||
@PostMapping(path = "/**", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
@@ -103,21 +102,21 @@ public class FunctionController {
|
||||
public Mono<ResponseEntity<?>> postStream(ServerWebExchange request,
|
||||
@RequestBody(required = false) String body) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.post(wrapper, body, true);
|
||||
return this.processor.post(wrapper, body, true);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/**")
|
||||
@ResponseBody
|
||||
public Mono<ResponseEntity<?>> get(ServerWebExchange request) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.get(wrapper);
|
||||
return this.processor.get(wrapper);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/**", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
@ResponseBody
|
||||
public Mono<ResponseEntity<?>> getStream(ServerWebExchange request) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.stream(wrapper);
|
||||
return this.processor.stream(wrapper);
|
||||
}
|
||||
|
||||
private FunctionWrapper wrapper(ServerWebExchange request) {
|
||||
@@ -139,4 +138,5 @@ public class FunctionController {
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -21,6 +21,7 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -35,8 +36,6 @@ import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -57,7 +56,7 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
public FunctionHandlerMapping(FunctionCatalog catalog,
|
||||
FunctionController controller) {
|
||||
this.functions = catalog;
|
||||
logger.info("FunctionCatalog: " + catalog);
|
||||
this.logger.info("FunctionCatalog: " + catalog);
|
||||
setOrder(super.getOrder() - 5);
|
||||
this.controller = controller;
|
||||
}
|
||||
@@ -65,9 +64,9 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
detectHandlerMethods(controller);
|
||||
while (prefix.endsWith("/")) {
|
||||
prefix = prefix.substring(0, prefix.length() - 1);
|
||||
detectHandlerMethods(this.controller);
|
||||
while (this.prefix.endsWith("/")) {
|
||||
this.prefix = this.prefix.substring(0, this.prefix.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,23 +77,23 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
@Override
|
||||
public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange request) {
|
||||
String path = request.getRequest().getPath().pathWithinApplication().value();
|
||||
if (StringUtils.hasText(prefix) && !path.startsWith(prefix)) {
|
||||
if (StringUtils.hasText(this.prefix) && !path.startsWith(this.prefix)) {
|
||||
return Mono.empty();
|
||||
}
|
||||
Mono<HandlerMethod> handler = super.getHandlerInternal(request);
|
||||
if (path == null) {
|
||||
return handler;
|
||||
}
|
||||
if (path.startsWith(prefix)) {
|
||||
path = path.substring(prefix.length());
|
||||
if (path.startsWith(this.prefix)) {
|
||||
path = path.substring(this.prefix.length());
|
||||
}
|
||||
Object function = findFunctionForGet(request, path);
|
||||
if (function == null) {
|
||||
function = findFunctionForPost(request, path);
|
||||
}
|
||||
if (function != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found function for POST: " + path);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Found function for POST: " + path);
|
||||
}
|
||||
request.getAttributes().put(WebRequestConstants.HANDLER, function);
|
||||
}
|
||||
@@ -107,12 +106,12 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
return null;
|
||||
}
|
||||
path = path.startsWith("/") ? path.substring(1) : path;
|
||||
Consumer<Publisher<?>> consumer = functions.lookup(Consumer.class, path);
|
||||
Consumer<Publisher<?>> consumer = this.functions.lookup(Consumer.class, path);
|
||||
if (consumer != null) {
|
||||
request.getAttributes().put(WebRequestConstants.CONSUMER, consumer);
|
||||
return consumer;
|
||||
}
|
||||
Function<Object, Object> function = functions.lookup(Function.class, path);
|
||||
Function<Object, Object> function = this.functions.lookup(Function.class, path);
|
||||
if (function != null) {
|
||||
request.getAttributes().put(WebRequestConstants.FUNCTION, function);
|
||||
return function;
|
||||
@@ -127,7 +126,7 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
path = path.startsWith("/") ? path.substring(1) : path;
|
||||
|
||||
Object functionForGet = null;
|
||||
Supplier<Publisher<?>> supplier = functions.lookup(Supplier.class, path);
|
||||
Supplier<Publisher<?>> supplier = this.functions.lookup(Supplier.class, path);
|
||||
if (supplier != null) {
|
||||
request.getAttributes().put(WebRequestConstants.SUPPLIER, supplier);
|
||||
functionForGet = supplier;
|
||||
@@ -135,7 +134,7 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
else {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String name = path;
|
||||
String[] splitPath = path.split("/");
|
||||
String[] splitPath = path.split("/");
|
||||
Function<Object, Object> function = null;
|
||||
for (int i = 0; i < splitPath.length || function != null; i++) {
|
||||
String element = splitPath[i];
|
||||
@@ -145,12 +144,11 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
builder.append(element);
|
||||
name = builder.toString();
|
||||
|
||||
function = functions.lookup(Function.class, name);
|
||||
function = this.functions.lookup(Function.class, name);
|
||||
if (function != null) {
|
||||
request.getAttributes().put(WebRequestConstants.FUNCTION, function);
|
||||
String value = path.length() > name.length()
|
||||
? path.substring(name.length() + 1)
|
||||
: null;
|
||||
? path.substring(name.length() + 1) : null;
|
||||
request.getAttributes().put(WebRequestConstants.ARGUMENT, value);
|
||||
functionForGet = function;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.function.web.flux;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@@ -34,8 +36,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.web.method.support.AsyncHandlerMethodReturnValueHandler;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Mark Fisher
|
||||
@@ -43,8 +43,8 @@ import reactor.core.publisher.Flux;
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ Flux.class, AsyncHandlerMethodReturnValueHandler.class })
|
||||
@ConditionalOnWebApplication(type=Type.REACTIVE)
|
||||
@Import({FunctionController.class, RequestProcessor.class})
|
||||
@ConditionalOnWebApplication(type = Type.REACTIVE)
|
||||
@Import({ FunctionController.class, RequestProcessor.class })
|
||||
@AutoConfigureAfter({ JacksonAutoConfiguration.class, GsonAutoConfiguration.class })
|
||||
public class ReactorAutoConfiguration {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -23,6 +23,10 @@ import java.util.function.Function;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.netty.DisposableServer;
|
||||
import reactor.netty.http.server.HttpServer;
|
||||
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.web.ErrorProperties;
|
||||
@@ -63,13 +67,7 @@ import static org.springframework.web.reactive.function.server.RequestPredicates
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.status;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.netty.DisposableServer;
|
||||
import reactor.netty.http.server.HttpServer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*
|
||||
@@ -148,7 +146,7 @@ class FunctionEndpointInitializer
|
||||
|
||||
private GenericApplicationContext context;
|
||||
|
||||
public ServerListener(GenericApplicationContext context) {
|
||||
ServerListener(GenericApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@@ -212,7 +210,7 @@ class FunctionEndpointFactory {
|
||||
|
||||
private RequestProcessor processor;
|
||||
|
||||
public FunctionEndpointFactory(FunctionCatalog catalog, FunctionInspector inspector,
|
||||
FunctionEndpointFactory(FunctionCatalog catalog, FunctionInspector inspector,
|
||||
RequestProcessor processor, Environment environment) {
|
||||
String handler = environment.resolvePlaceholders("${function.handler}");
|
||||
if (handler.startsWith("$")) {
|
||||
@@ -242,13 +240,13 @@ class FunctionEndpointFactory {
|
||||
public <T> RouterFunction<?> functionEndpoints() {
|
||||
return route(POST("/"), request -> {
|
||||
Class<T> outputType = (Class<T>) this.inspector.getOutputType(this.function);
|
||||
FunctionWrapper wrapper = RequestProcessor.wrapper(function, null, null);
|
||||
FunctionWrapper wrapper = RequestProcessor.wrapper(this.function, null, null);
|
||||
Mono<ResponseEntity<?>> stream = request.bodyToMono(String.class)
|
||||
.flatMap(content -> processor.post(wrapper, content, false));
|
||||
.flatMap(content -> this.processor.post(wrapper, content, false));
|
||||
return stream.flatMap(entity -> status(entity.getStatusCode())
|
||||
.headers(headers -> headers.addAll(entity.getHeaders()))
|
||||
.body(Mono.just((T) entity.getBody()), outputType));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -23,6 +23,7 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.function.web.RequestProcessor;
|
||||
import org.springframework.cloud.function.web.RequestProcessor.FunctionWrapper;
|
||||
@@ -36,8 +37,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Mark Fisher
|
||||
@@ -56,7 +55,7 @@ public class FunctionController {
|
||||
@ResponseBody
|
||||
public Mono<ResponseEntity<?>> form(WebRequest request) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.post(wrapper, null, false);
|
||||
return this.processor.post(wrapper, null, false);
|
||||
}
|
||||
|
||||
@PostMapping(path = "/**")
|
||||
@@ -64,7 +63,7 @@ public class FunctionController {
|
||||
public Mono<ResponseEntity<?>> post(WebRequest request,
|
||||
@RequestBody(required = false) String body) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.post(wrapper, body, false);
|
||||
return this.processor.post(wrapper, body, false);
|
||||
}
|
||||
|
||||
@PostMapping(path = "/**", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
@@ -72,22 +71,23 @@ public class FunctionController {
|
||||
public Mono<ResponseEntity<Publisher<?>>> postStream(WebRequest request,
|
||||
@RequestBody(required = false) String body) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.post(wrapper, body, true).map(response -> ResponseEntity.ok()
|
||||
.headers(response.getHeaders()).body((Publisher<?>) response.getBody()));
|
||||
return this.processor.post(wrapper, body, true)
|
||||
.map(response -> ResponseEntity.ok().headers(response.getHeaders())
|
||||
.body((Publisher<?>) response.getBody()));
|
||||
}
|
||||
|
||||
@GetMapping(path = "/**")
|
||||
@ResponseBody
|
||||
public Mono<ResponseEntity<?>> get(WebRequest request) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.get(wrapper);
|
||||
return this.processor.get(wrapper);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/**", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
@ResponseBody
|
||||
public Mono<ResponseEntity<Publisher<?>>> getStream(WebRequest request) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
return processor.stream(wrapper).map(response -> ResponseEntity.ok()
|
||||
return this.processor.stream(wrapper).map(response -> ResponseEntity.ok()
|
||||
.headers(response.getHeaders()).body((Publisher<?>) response.getBody()));
|
||||
}
|
||||
|
||||
@@ -116,4 +116,5 @@ public class FunctionController {
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -56,7 +56,7 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
public FunctionHandlerMapping(FunctionCatalog catalog,
|
||||
FunctionController controller) {
|
||||
this.functions = catalog;
|
||||
logger.info("FunctionCatalog: " + catalog);
|
||||
this.logger.info("FunctionCatalog: " + catalog);
|
||||
setOrder(super.getOrder() - 5);
|
||||
this.controller = controller;
|
||||
}
|
||||
@@ -64,9 +64,9 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
detectHandlerMethods(controller);
|
||||
while (prefix.endsWith("/")) {
|
||||
prefix = prefix.substring(0, prefix.length() - 1);
|
||||
detectHandlerMethods(this.controller);
|
||||
while (this.prefix.endsWith("/")) {
|
||||
this.prefix = this.prefix.substring(0, this.prefix.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,24 +86,24 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
if (path == null) {
|
||||
return handler;
|
||||
}
|
||||
if (StringUtils.hasText(prefix) && !path.startsWith(prefix)) {
|
||||
if (StringUtils.hasText(this.prefix) && !path.startsWith(this.prefix)) {
|
||||
return null;
|
||||
}
|
||||
if (path.startsWith(prefix)) {
|
||||
path = path.substring(prefix.length());
|
||||
if (path.startsWith(this.prefix)) {
|
||||
path = path.substring(this.prefix.length());
|
||||
}
|
||||
Object function = findFunctionForGet(request, path);
|
||||
if (function != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found function for GET: " + path);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Found function for GET: " + path);
|
||||
}
|
||||
request.setAttribute(WebRequestConstants.HANDLER, function);
|
||||
return handler;
|
||||
}
|
||||
function = findFunctionForPost(request, path);
|
||||
if (function != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found function for POST: " + path);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Found function for POST: " + path);
|
||||
}
|
||||
request.setAttribute(WebRequestConstants.HANDLER, function);
|
||||
return handler;
|
||||
@@ -116,12 +116,12 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
return null;
|
||||
}
|
||||
path = path.startsWith("/") ? path.substring(1) : path;
|
||||
Consumer<Publisher<?>> consumer = functions.lookup(Consumer.class, path);
|
||||
Consumer<Publisher<?>> consumer = this.functions.lookup(Consumer.class, path);
|
||||
if (consumer != null) {
|
||||
request.setAttribute(WebRequestConstants.CONSUMER, consumer);
|
||||
return consumer;
|
||||
}
|
||||
Function<Object, Object> function = functions.lookup(Function.class, path);
|
||||
Function<Object, Object> function = this.functions.lookup(Function.class, path);
|
||||
if (function != null) {
|
||||
request.setAttribute(WebRequestConstants.FUNCTION, function);
|
||||
return function;
|
||||
@@ -134,7 +134,7 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
return null;
|
||||
}
|
||||
path = path.startsWith("/") ? path.substring(1) : path;
|
||||
Supplier<Publisher<?>> supplier = functions.lookup(Supplier.class, path);
|
||||
Supplier<Publisher<?>> supplier = this.functions.lookup(Supplier.class, path);
|
||||
if (supplier != null) {
|
||||
request.setAttribute(WebRequestConstants.SUPPLIER, supplier);
|
||||
return supplier;
|
||||
@@ -150,7 +150,8 @@ public class FunctionHandlerMapping extends RequestMappingHandlerMapping
|
||||
name = builder.toString();
|
||||
value = path.length() > name.length() ? path.substring(name.length() + 1)
|
||||
: null;
|
||||
Function<Object, Object> function = functions.lookup(Function.class, name);
|
||||
Function<Object, Object> function = this.functions.lookup(Function.class,
|
||||
name);
|
||||
if (function != null) {
|
||||
request.setAttribute(WebRequestConstants.FUNCTION, function);
|
||||
request.setAttribute(WebRequestConstants.ARGUMENT, value);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.function.web.mvc;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@@ -34,15 +36,13 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.web.method.support.AsyncHandlerMethodReturnValueHandler;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnWebApplication(type=Type.SERVLET)
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@ConditionalOnClass({ Flux.class, AsyncHandlerMethodReturnValueHandler.class })
|
||||
@Import({ FunctionController.class, RequestProcessor.class })
|
||||
@AutoConfigureAfter({ JacksonAutoConfiguration.class, GsonAutoConfiguration.class })
|
||||
@@ -60,4 +60,5 @@ public class ReactorAutoConfiguration {
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
return new BasicStringConverter(inspector, beanFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -25,4 +25,5 @@ import java.util.function.Supplier;
|
||||
public interface DestinationResolver {
|
||||
|
||||
String destination(Supplier<?> supplier, String name, Object value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -25,9 +25,9 @@ import org.springframework.http.HttpHeaders;
|
||||
*
|
||||
*/
|
||||
public interface RequestBuilder {
|
||||
|
||||
|
||||
URI uri(String destination);
|
||||
|
||||
|
||||
HttpHeaders headers(String destination, Object value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -31,7 +31,9 @@ import org.springframework.http.HttpHeaders;
|
||||
class SimpleRequestBuilder implements RequestBuilder {
|
||||
|
||||
private String baseUrl = "http://${destination}";
|
||||
|
||||
private Map<String, String> headers = new LinkedHashMap<>();
|
||||
|
||||
private Environment environment;
|
||||
|
||||
SimpleRequestBuilder(Environment environment) {
|
||||
@@ -42,10 +44,10 @@ class SimpleRequestBuilder implements RequestBuilder {
|
||||
public HttpHeaders headers(String destination, Object value) {
|
||||
// TODO: add message headers if any
|
||||
HttpHeaders result = new HttpHeaders();
|
||||
for (String key : headers.keySet()) {
|
||||
String header = headers.get(key);
|
||||
for (String key : this.headers.keySet()) {
|
||||
String header = this.headers.get(key);
|
||||
header = header.replace("${destination}", destination);
|
||||
header = environment.resolvePlaceholders(header);
|
||||
header = this.environment.resolvePlaceholders(header);
|
||||
result.add(key, header);
|
||||
}
|
||||
return result;
|
||||
@@ -54,8 +56,8 @@ class SimpleRequestBuilder implements RequestBuilder {
|
||||
@Override
|
||||
public URI uri(String destination) {
|
||||
try {
|
||||
return new URI(environment
|
||||
.resolvePlaceholders(baseUrl.replace("${destination}", destination)));
|
||||
return new URI(this.environment.resolvePlaceholders(
|
||||
this.baseUrl.replace("${destination}", destination)));
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new IllegalStateException("Cannot create URI", e);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -68,16 +68,20 @@ class SupplierAutoConfiguration {
|
||||
|
||||
static class SourceActiveCondition extends AnyNestedCondition {
|
||||
|
||||
public SourceActiveCondition() {
|
||||
SourceActiveCondition() {
|
||||
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
||||
}
|
||||
|
||||
@ConditionalOnNotWebApplication
|
||||
static class OnNotWebapp {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(prefix = "spring.cloud.function.web.supplier", name = "enabled")
|
||||
static class Enabled {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -21,6 +21,11 @@ import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
import org.springframework.cloud.function.context.FunctionCatalog;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -28,11 +33,6 @@ import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
/**
|
||||
* Forwards items obtained from a {@link Supplier} or set of suppliers to an external HTTP
|
||||
* endpoint.
|
||||
@@ -62,7 +62,7 @@ class SupplierExporter implements SmartLifecycle {
|
||||
|
||||
private volatile Disposable subscription;
|
||||
|
||||
public SupplierExporter(RequestBuilder requestBuilder,
|
||||
SupplierExporter(RequestBuilder requestBuilder,
|
||||
DestinationResolver destinationResolver, FunctionCatalog catalog,
|
||||
WebClient client, SupplierProperties props) {
|
||||
this.requestBuilder = requestBuilder;
|
||||
@@ -84,10 +84,10 @@ class SupplierExporter implements SmartLifecycle {
|
||||
this.ok = true;
|
||||
|
||||
Flux<Object> streams = Flux.empty();
|
||||
Set<String> names = this.supplier == null ? catalog.getNames(Supplier.class)
|
||||
Set<String> names = this.supplier == null ? this.catalog.getNames(Supplier.class)
|
||||
: Collections.singleton(this.supplier);
|
||||
for (String name : names) {
|
||||
Supplier<Flux<Object>> supplier = catalog.lookup(Supplier.class, name);
|
||||
Supplier<Flux<Object>> supplier = this.catalog.lookup(Supplier.class, name);
|
||||
streams = streams.mergeWith(forward(supplier, name));
|
||||
}
|
||||
|
||||
@@ -105,13 +105,14 @@ class SupplierExporter implements SmartLifecycle {
|
||||
|
||||
private Flux<ClientResponse> forward(Supplier<Flux<Object>> supplier, String name) {
|
||||
return supplier.get().publishOn(Schedulers.parallel()).flatMap(value -> {
|
||||
String destination = destinationResolver.destination(supplier, name, value);
|
||||
String destination = this.destinationResolver.destination(supplier, name,
|
||||
value);
|
||||
return post(uri(destination), destination, value);
|
||||
});
|
||||
}
|
||||
|
||||
private Mono<ClientResponse> post(URI uri, String destination, Object value) {
|
||||
Mono<ClientResponse> result = client.post().uri(uri)
|
||||
Mono<ClientResponse> result = this.client.post().uri(uri)
|
||||
.headers(headers -> headers(headers, destination, value))
|
||||
.body(BodyInserters.fromObject(value)).exchange();
|
||||
if (this.debug) {
|
||||
@@ -121,11 +122,11 @@ class SupplierExporter implements SmartLifecycle {
|
||||
}
|
||||
|
||||
private void headers(HttpHeaders headers, String destination, Object value) {
|
||||
headers.putAll(requestBuilder.headers(destination, value));
|
||||
headers.putAll(this.requestBuilder.headers(destination, value));
|
||||
}
|
||||
|
||||
private URI uri(String destination) {
|
||||
return requestBuilder.uri(destination);
|
||||
return this.requestBuilder.uri(destination);
|
||||
}
|
||||
|
||||
public boolean isOk() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -29,10 +29,17 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
public class SupplierProperties {
|
||||
|
||||
private boolean autoStartup = true;
|
||||
|
||||
private boolean debug = true;
|
||||
|
||||
private String name;
|
||||
|
||||
private String templateUrl;
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
private Map<String, String> headers = new LinkedHashMap<>();
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
@@ -41,8 +48,6 @@ public class SupplierProperties {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
private Map<String, String> headers = new LinkedHashMap<>();
|
||||
|
||||
public boolean isAutoStartup() {
|
||||
return this.autoStartup;
|
||||
}
|
||||
@@ -59,23 +64,24 @@ public class SupplierProperties {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
public String getTemplateUrl() {
|
||||
return this.templateUrl;
|
||||
}
|
||||
|
||||
public void setTemplateUrl(String templateUrl) {
|
||||
this.templateUrl = templateUrl;
|
||||
}
|
||||
|
||||
public String getTemplateUrl() {
|
||||
return this.templateUrl;
|
||||
}
|
||||
|
||||
public Map<String, String> getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.web.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -28,12 +29,16 @@ import org.springframework.messaging.MessageHeaders;
|
||||
* @author Dave Syer
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class HeaderUtils {
|
||||
public final class HeaderUtils {
|
||||
|
||||
private static HttpHeaders IGNORED = new HttpHeaders();
|
||||
|
||||
private static HttpHeaders REQUEST_ONLY = new HttpHeaders();
|
||||
|
||||
private HeaderUtils() {
|
||||
throw new IllegalStateException("Can't instantiate a utility class");
|
||||
}
|
||||
|
||||
static {
|
||||
IGNORED.add(MessageHeaders.ID, "");
|
||||
IGNORED.add(HttpHeaders.CONTENT_LENGTH, "0");
|
||||
@@ -86,4 +91,5 @@ public class HeaderUtils {
|
||||
private static Collection<?> multi(Object value) {
|
||||
return value instanceof Collection ? (Collection<?>) value : Arrays.asList(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
{"properties": [
|
||||
{
|
||||
"name": "spring.cloud.function.web.path",
|
||||
"type": "java.lang.String",
|
||||
"description": "Path to web resources for functions (should start with / if not empty).",
|
||||
"defaultValue": ""
|
||||
}]
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.cloud.function.web.path",
|
||||
"type": "java.lang.String",
|
||||
"description": "Path to web resources for functions (should start with / if not empty).",
|
||||
"defaultValue": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.function.web.flux.ReactorAutoConfiguration,\
|
||||
org.springframework.cloud.function.web.mvc.ReactorAutoConfiguration,\
|
||||
org.springframework.cloud.function.web.source.SupplierAutoConfiguration
|
||||
|
||||
org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc=\
|
||||
org.springframework.cloud.function.web.flux.ReactorAutoConfiguration,\
|
||||
org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration
|
||||
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
org.springframework.cloud.function.web.function.FunctionEndpointInitializer
|
||||
org.springframework.cloud.function.web.function.FunctionEndpointInitializer
|
||||
|
||||
Reference in New Issue
Block a user