Skip to content

Commit

Permalink
Merge branch '4.3.x' into 4.4.x
Browse files Browse the repository at this point in the history
  • Loading branch information
sdelamo committed Apr 18, 2024
2 parents 114606a + 0d6af33 commit 2a9f53a
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2020 original authors
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -562,7 +562,7 @@ <T> NettyBodyWriter<T> wrap(MessageBodyWriter<T> closure) {
*/
<T> NettyBodyWriter<T> specialize(NettyBodyWriter<T> original, Argument<T> bodyType, MediaType mediaType, T body) {
if (original instanceof CompatNettyWriteClosure<T> cnwc && cnwc.delegate instanceof DynamicMessageBodyWriter dyn) {
return (NettyBodyWriter<T>) new CompatNettyWriteClosure<>(dyn.find((Argument<Object>) bodyType, mediaType, body));
return (NettyBodyWriter<T>) wrap(dyn.find((Argument<Object>) bodyType, mediaType, body));
} else {
return original;
}
Expand All @@ -572,6 +572,7 @@ private final class CompatNettyWriteClosure<T> implements NettyBodyWriter<T> {
private final MessageBodyWriter<T> delegate;

CompatNettyWriteClosure(MessageBodyWriter<T> delegate) {
assert !(delegate instanceof NettyBodyWriter) : "please create using wrap()";
this.delegate = delegate;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
/*
* Copyright 2017-2019 original 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 io.micronaut.http.server.netty.types


import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.databind.node.JsonNodeFactory
import com.fasterxml.jackson.databind.node.ObjectNode
Expand All @@ -28,15 +12,19 @@ import io.micronaut.http.MediaType
import io.micronaut.http.MutableHttpRequest
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.QueryValue
import io.micronaut.http.client.exceptions.HttpClientResponseException
import io.micronaut.http.server.netty.AbstractMicronautSpec
import io.micronaut.http.server.types.files.FileCustomizableResponseType
import io.micronaut.http.server.types.files.StreamedFile
import io.micronaut.http.server.types.files.SystemFile
import jakarta.inject.Inject
import jakarta.inject.Named
import reactor.core.publisher.Mono
import spock.lang.IgnoreIf

import java.nio.file.Files
import java.nio.file.Path
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
Expand Down Expand Up @@ -219,6 +207,40 @@ class FileTypeHandlerSpec extends AbstractMicronautSpec {
response.body() == tempFileContents
}

void "test when an reactive attached streamed file is returned"() {
when:
def response = httpClient.toBlocking().exchange('/test-stream/reactive-stream', byte[].class)

then:
response.code() == HttpStatus.OK.code
response.header(CONTENT_TYPE) == MediaType.TEXT_PLAIN
Integer.parseInt(response.header(CONTENT_LENGTH)) > 0
response.headers.getDate(DATE) < response.headers.getDate(EXPIRES)
response.header(CACHE_CONTROL) == "private, max-age=60"
response.body() == "My file content".bytes
}

void "test when an reactive attached system file is returned"() {
given:
def file = Files.createTempFile("test", ".txt").toFile().tap {
it << "System file!"
}

when:
def response = httpClient.toBlocking().exchange("/test-stream/reactive-system?path=$file.absolutePath", byte[].class)

then:
response.code() == HttpStatus.OK.code
response.header(CONTENT_TYPE) == MediaType.TEXT_PLAIN
Integer.parseInt(response.header(CONTENT_LENGTH)) > 0
response.headers.getDate(DATE) < response.headers.getDate(EXPIRES)
response.header(CACHE_CONTROL) == "private, max-age=60"
response.body() == "System file!".bytes

cleanup:
file.delete()
}

void "test when an attached file is returned with a name"() {
when:
def response = httpClient.toBlocking().exchange('/test/different-name', String)
Expand Down Expand Up @@ -393,6 +415,16 @@ class FileTypeHandlerSpec extends AbstractMicronautSpec {
return new StreamedFile(input, MediaType.TEXT_PLAIN_TYPE)
}

@Get('/reactive-stream')
Mono<FileCustomizableResponseType> reactiveStream() {
def stream = new ByteArrayInputStream("My file content".bytes)
Mono.just(new StreamedFile(stream, MediaType.TEXT_PLAIN_TYPE))
}

@Get('/reactive-system')
Mono<FileCustomizableResponseType> reactiveStream(@QueryValue Path path) {
Mono.just(new SystemFile(path.toFile(), MediaType.TEXT_PLAIN_TYPE))
}
}

@CompileStatic
Expand Down

0 comments on commit 2a9f53a

Please sign in to comment.