|
|
|
@ -98,13 +98,13 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part> |
|
|
|
Map<String, Object> hints) { |
|
|
|
Map<String, Object> hints) { |
|
|
|
|
|
|
|
|
|
|
|
return Mono.error(new UnsupportedOperationException( |
|
|
|
return Mono.error(new UnsupportedOperationException( |
|
|
|
"This reader does not support reading a single element.")); |
|
|
|
"Can't read a multipart request body into a single Part.")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Consume and feed input to the Synchronoss parser, then adapt parser |
|
|
|
* Consume and feed input to the Synchronoss parser, then listen for parser |
|
|
|
* output events to {@code Flux<Sink<Part>>}. |
|
|
|
* output events and adapt to {@code Flux<Sink<Part>>}. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private static class SynchronossPartGenerator implements Consumer<FluxSink<Part>> { |
|
|
|
private static class SynchronossPartGenerator implements Consumer<FluxSink<Part>> { |
|
|
|
|
|
|
|
|
|
|
|
@ -112,11 +112,13 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part> |
|
|
|
|
|
|
|
|
|
|
|
private final DataBufferFactory bufferFactory; |
|
|
|
private final DataBufferFactory bufferFactory; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SynchronossPartGenerator(ReactiveHttpInputMessage inputMessage, DataBufferFactory factory) { |
|
|
|
SynchronossPartGenerator(ReactiveHttpInputMessage inputMessage, DataBufferFactory factory) { |
|
|
|
this.inputMessage = inputMessage; |
|
|
|
this.inputMessage = inputMessage; |
|
|
|
this.bufferFactory = factory; |
|
|
|
this.bufferFactory = factory; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void accept(FluxSink<Part> emitter) { |
|
|
|
public void accept(FluxSink<Part> emitter) { |
|
|
|
HttpHeaders headers = this.inputMessage.getHeaders(); |
|
|
|
HttpHeaders headers = this.inputMessage.getHeaders(); |
|
|
|
@ -176,12 +178,14 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part> |
|
|
|
|
|
|
|
|
|
|
|
private final AtomicInteger terminated = new AtomicInteger(0); |
|
|
|
private final AtomicInteger terminated = new AtomicInteger(0); |
|
|
|
|
|
|
|
|
|
|
|
FluxSinkAdapterListener(FluxSink<Part> sink, DataBufferFactory bufferFactory, MultipartContext context) { |
|
|
|
|
|
|
|
|
|
|
|
FluxSinkAdapterListener(FluxSink<Part> sink, DataBufferFactory factory, MultipartContext context) { |
|
|
|
this.sink = sink; |
|
|
|
this.sink = sink; |
|
|
|
this.bufferFactory = bufferFactory; |
|
|
|
this.bufferFactory = factory; |
|
|
|
this.context = context; |
|
|
|
this.context = context; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void onPartFinished(StreamStorage storage, Map<String, List<String>> headers) { |
|
|
|
public void onPartFinished(StreamStorage storage, Map<String, List<String>> headers) { |
|
|
|
HttpHeaders httpHeaders = new HttpHeaders(); |
|
|
|
HttpHeaders httpHeaders = new HttpHeaders(); |
|
|
|
@ -192,14 +196,14 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part> |
|
|
|
private Part createPart(StreamStorage storage, HttpHeaders httpHeaders) { |
|
|
|
private Part createPart(StreamStorage storage, HttpHeaders httpHeaders) { |
|
|
|
String filename = MultipartUtils.getFileName(httpHeaders); |
|
|
|
String filename = MultipartUtils.getFileName(httpHeaders); |
|
|
|
if (filename != null) { |
|
|
|
if (filename != null) { |
|
|
|
return new SynchronossFilePart(httpHeaders, storage, this.bufferFactory, filename); |
|
|
|
return new SynchronossFilePart(httpHeaders, filename, storage, this.bufferFactory); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (MultipartUtils.isFormField(httpHeaders, this.context)) { |
|
|
|
else if (MultipartUtils.isFormField(httpHeaders, this.context)) { |
|
|
|
String value = MultipartUtils.readFormParameterValue(storage, httpHeaders); |
|
|
|
String value = MultipartUtils.readFormParameterValue(storage, httpHeaders); |
|
|
|
return new SynchronossFormFieldPart(httpHeaders, this.bufferFactory, value); |
|
|
|
return new SynchronossFormFieldPart(httpHeaders, this.bufferFactory, value); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
return new DefaultSynchronossPart(httpHeaders, storage, this.bufferFactory); |
|
|
|
return new SynchronossPart(httpHeaders, storage, this.bufferFactory); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -229,20 +233,25 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part> |
|
|
|
|
|
|
|
|
|
|
|
private abstract static class AbstractSynchronossPart implements Part { |
|
|
|
private abstract static class AbstractSynchronossPart implements Part { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String name; |
|
|
|
|
|
|
|
|
|
|
|
private final HttpHeaders headers; |
|
|
|
private final HttpHeaders headers; |
|
|
|
|
|
|
|
|
|
|
|
private final DataBufferFactory bufferFactory; |
|
|
|
private final DataBufferFactory bufferFactory; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AbstractSynchronossPart(HttpHeaders headers, DataBufferFactory bufferFactory) { |
|
|
|
AbstractSynchronossPart(HttpHeaders headers, DataBufferFactory bufferFactory) { |
|
|
|
Assert.notNull(headers, "HttpHeaders is required"); |
|
|
|
Assert.notNull(headers, "HttpHeaders is required"); |
|
|
|
Assert.notNull(bufferFactory, "'bufferFactory' is required"); |
|
|
|
Assert.notNull(bufferFactory, "'bufferFactory' is required"); |
|
|
|
|
|
|
|
this.name = MultipartUtils.getFieldName(headers); |
|
|
|
this.headers = headers; |
|
|
|
this.headers = headers; |
|
|
|
this.bufferFactory = bufferFactory; |
|
|
|
this.bufferFactory = bufferFactory; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public String name() { |
|
|
|
public String name() { |
|
|
|
return MultipartUtils.getFieldName(this.headers); |
|
|
|
return this.name; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
@ -250,26 +259,27 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part> |
|
|
|
return this.headers; |
|
|
|
return this.headers; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected DataBufferFactory getBufferFactory() { |
|
|
|
DataBufferFactory getBufferFactory() { |
|
|
|
return this.bufferFactory; |
|
|
|
return this.bufferFactory; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class DefaultSynchronossPart extends AbstractSynchronossPart { |
|
|
|
private static class SynchronossPart extends AbstractSynchronossPart { |
|
|
|
|
|
|
|
|
|
|
|
private final StreamStorage storage; |
|
|
|
private final StreamStorage storage; |
|
|
|
|
|
|
|
|
|
|
|
DefaultSynchronossPart(HttpHeaders headers, StreamStorage storage, DataBufferFactory factory) { |
|
|
|
|
|
|
|
|
|
|
|
SynchronossPart(HttpHeaders headers, StreamStorage storage, DataBufferFactory factory) { |
|
|
|
super(headers, factory); |
|
|
|
super(headers, factory); |
|
|
|
Assert.notNull(storage, "'storage' is required"); |
|
|
|
Assert.notNull(storage, "'storage' is required"); |
|
|
|
this.storage = storage; |
|
|
|
this.storage = storage; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Flux<DataBuffer> content() { |
|
|
|
public Flux<DataBuffer> content() { |
|
|
|
return DataBufferUtils.readInputStream(this.storage::getInputStream, getBufferFactory(), |
|
|
|
return DataBufferUtils.readInputStream(getStorage()::getInputStream, getBufferFactory(), 4096); |
|
|
|
4096); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected StreamStorage getStorage() { |
|
|
|
protected StreamStorage getStorage() { |
|
|
|
@ -278,20 +288,23 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part> |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class SynchronossFilePart extends DefaultSynchronossPart implements FilePart { |
|
|
|
private static class SynchronossFilePart extends SynchronossPart implements FilePart { |
|
|
|
|
|
|
|
|
|
|
|
private static final OpenOption[] FILE_CHANNEL_OPTIONS = { |
|
|
|
private static final OpenOption[] FILE_CHANNEL_OPTIONS = { |
|
|
|
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE }; |
|
|
|
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String filename; |
|
|
|
private final String filename; |
|
|
|
|
|
|
|
|
|
|
|
public SynchronossFilePart( |
|
|
|
|
|
|
|
HttpHeaders headers, StreamStorage storage, DataBufferFactory factory, String filename) { |
|
|
|
SynchronossFilePart(HttpHeaders headers, String filename, StreamStorage storage, |
|
|
|
|
|
|
|
DataBufferFactory factory) { |
|
|
|
|
|
|
|
|
|
|
|
super(headers, storage, factory); |
|
|
|
super(headers, storage, factory); |
|
|
|
this.filename = filename; |
|
|
|
this.filename = filename; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public String filename() { |
|
|
|
public String filename() { |
|
|
|
return this.filename; |
|
|
|
return this.filename; |
|
|
|
@ -342,11 +355,13 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part> |
|
|
|
|
|
|
|
|
|
|
|
private final String content; |
|
|
|
private final String content; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SynchronossFormFieldPart(HttpHeaders headers, DataBufferFactory bufferFactory, String content) { |
|
|
|
SynchronossFormFieldPart(HttpHeaders headers, DataBufferFactory bufferFactory, String content) { |
|
|
|
super(headers, bufferFactory); |
|
|
|
super(headers, bufferFactory); |
|
|
|
this.content = content; |
|
|
|
this.content = content; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public String value() { |
|
|
|
public String value() { |
|
|
|
return this.content; |
|
|
|
return this.content; |
|
|
|
@ -361,8 +376,8 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part> |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Charset getCharset() { |
|
|
|
private Charset getCharset() { |
|
|
|
return Optional.ofNullable(MultipartUtils.getCharEncoding(headers())) |
|
|
|
String name = MultipartUtils.getCharEncoding(headers()); |
|
|
|
.map(Charset::forName).orElse(StandardCharsets.UTF_8); |
|
|
|
return (name != null ? Charset.forName(name) : StandardCharsets.UTF_8); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|