Skip to content

Commit ddb664d

Browse files
Merge pull request #784 from micronaut-projects/andriy/poja-improve
Minor improvements for POJA
2 parents fb02e95 + 9e9a23c commit ddb664d

File tree

8 files changed

+160
-105
lines changed

8 files changed

+160
-105
lines changed

http-poja-apache/src/main/java/io/micronaut/http/poja/llhttp/ApacheServerlessApplication.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import io.micronaut.context.ApplicationContext;
1919
import io.micronaut.core.convert.ConversionService;
20+
import io.micronaut.core.io.buffer.ByteBufferFactory;
2021
import io.micronaut.http.HttpStatus;
2122
import io.micronaut.http.MediaType;
2223
import io.micronaut.http.codec.MediaTypeCodecRegistry;
@@ -26,6 +27,7 @@
2627
import io.micronaut.inject.qualifiers.Qualifiers;
2728
import io.micronaut.runtime.ApplicationConfiguration;
2829
import io.micronaut.scheduling.TaskExecutors;
30+
import io.micronaut.servlet.http.ByteArrayBufferFactory;
2931
import io.micronaut.servlet.http.ServletHttpHandler;
3032
import jakarta.inject.Singleton;
3133
import org.apache.hc.core5.http.ClassicHttpResponse;
@@ -53,6 +55,7 @@ public class ApacheServerlessApplication
5355
private final ConversionService conversionService;
5456
private final MediaTypeCodecRegistry codecRegistry;
5557
private final ExecutorService ioExecutor;
58+
private final ByteBufferFactory<?, ?> byteBufferFactory;
5659
private final ApacheServletConfiguration configuration;
5760

5861
/**
@@ -68,6 +71,7 @@ public ApacheServerlessApplication(ApplicationContext applicationContext,
6871
codecRegistry = applicationContext.getBean(MediaTypeCodecRegistry.class);
6972
ioExecutor = applicationContext.getBean(ExecutorService.class, Qualifiers.byName(TaskExecutors.BLOCKING));
7073
configuration = applicationContext.getBean(ApacheServletConfiguration.class);
74+
byteBufferFactory = ByteArrayBufferFactory.INSTANCE;
7175
}
7276

7377
@Override
@@ -79,7 +83,7 @@ protected void handleSingleRequest(
7983
ApacheServletHttpResponse<?> response = new ApacheServletHttpResponse<>(conversionService);
8084
try {
8185
ApacheServletHttpRequest exchange = new ApacheServletHttpRequest<>(
82-
in, conversionService, codecRegistry, ioExecutor, response, configuration
86+
in, conversionService, codecRegistry, ioExecutor, byteBufferFactory, response, configuration
8387
);
8488
servletHttpHandler.service(exchange);
8589
} catch (ApacheServletBadRequestException e) {

http-poja-apache/src/main/java/io/micronaut/http/poja/llhttp/ApacheServletHttpRequest.java

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,34 @@
1818
import io.micronaut.core.annotation.Internal;
1919
import io.micronaut.core.annotation.NonNull;
2020
import io.micronaut.core.convert.ConversionService;
21+
import io.micronaut.core.io.buffer.ByteBufferFactory;
2122
import io.micronaut.http.HttpHeaders;
2223
import io.micronaut.http.HttpMethod;
2324
import io.micronaut.http.MutableHttpHeaders;
2425
import io.micronaut.http.MutableHttpParameters;
2526
import io.micronaut.http.MutableHttpRequest;
2627
import io.micronaut.http.body.ByteBody;
28+
import io.micronaut.http.body.stream.InputStreamByteBody;
2729
import io.micronaut.http.codec.MediaTypeCodecRegistry;
2830
import io.micronaut.http.cookie.Cookie;
2931
import io.micronaut.http.cookie.Cookies;
3032
import io.micronaut.http.poja.PojaHttpRequest;
3133
import io.micronaut.http.poja.llhttp.exception.ApacheServletBadRequestException;
32-
import io.micronaut.http.poja.util.LimitingInputStream;
3334
import io.micronaut.http.poja.util.MultiValueHeaders;
3435
import io.micronaut.http.poja.util.MultiValuesQueryParameters;
3536
import io.micronaut.http.simple.cookies.SimpleCookies;
36-
import io.micronaut.servlet.http.body.InputStreamByteBody;
3737
import org.apache.hc.core5.http.ClassicHttpRequest;
3838
import org.apache.hc.core5.http.ClassicHttpResponse;
3939
import org.apache.hc.core5.http.Header;
4040
import org.apache.hc.core5.http.HttpException;
4141
import org.apache.hc.core5.http.NameValuePair;
42+
import org.apache.hc.core5.http.impl.io.ChunkedInputStream;
43+
import org.apache.hc.core5.http.impl.io.ContentLengthInputStream;
4244
import org.apache.hc.core5.http.impl.io.DefaultHttpRequestParser;
4345
import org.apache.hc.core5.http.impl.io.SessionInputBufferImpl;
46+
import org.apache.hc.core5.http.io.entity.EmptyInputStream;
4447
import org.apache.hc.core5.net.URIBuilder;
4548

46-
import java.io.ByteArrayInputStream;
4749
import java.io.IOException;
4850
import java.io.InputStream;
4951
import java.net.URI;
@@ -67,6 +69,8 @@
6769
@Internal
6870
public final class ApacheServletHttpRequest<B> extends PojaHttpRequest<B, ClassicHttpRequest, ClassicHttpResponse> {
6971

72+
private static final String TRANSFER_ENCODING_CHUNKED = "chunked";
73+
7074
private final ClassicHttpRequest request;
7175

7276
private final HttpMethod method;
@@ -92,6 +96,7 @@ public ApacheServletHttpRequest(
9296
ConversionService conversionService,
9397
MediaTypeCodecRegistry codecRegistry,
9498
ExecutorService ioExecutor,
99+
ByteBufferFactory<?, ?> byteBufferFactory,
95100
ApacheServletHttpResponse<?> response,
96101
ApacheServletConfiguration configuration
97102
) {
@@ -119,29 +124,33 @@ public ApacheServletHttpRequest(
119124

120125
long contentLength = getContentLength();
121126
OptionalLong optionalContentLength = contentLength >= 0 ? OptionalLong.of(contentLength) : OptionalLong.empty();
122-
try {
123-
InputStream bodyStream = inputStream;
124-
if (sessionInputBuffer.length() > 0) {
125-
byte[] data = new byte[sessionInputBuffer.length()];
126-
sessionInputBuffer.read(data, inputStream);
127-
128-
bodyStream = new CombinedInputStream(
129-
new ByteArrayInputStream(data),
130-
inputStream
131-
);
132-
}
133-
if (contentLength > 0) {
134-
bodyStream = new LimitingInputStream(bodyStream, contentLength);
135-
} else {
136-
// Empty
137-
bodyStream = new ByteArrayInputStream(new byte[0]);
138-
}
139-
byteBody = InputStreamByteBody.create(
140-
bodyStream, optionalContentLength, ioExecutor
141-
);
142-
} catch (IOException e) {
143-
throw new ApacheServletBadRequestException("Could not parse request body", e);
127+
InputStream bodyStream = createBodyStream(inputStream, contentLength, sessionInputBuffer);
128+
byteBody = InputStreamByteBody.create(
129+
bodyStream, optionalContentLength, ioExecutor, byteBufferFactory
130+
);
131+
}
132+
133+
/**
134+
* Create body stream.
135+
* Based on org.apache.hc.core5.http.impl.io.BHttpConnectionBase#createContentOutputStream.
136+
*
137+
* @param inputStream The input stream
138+
* @param contentLength The content length
139+
* @param sessionInputBuffer The input buffer
140+
* @return The body stream
141+
*/
142+
private InputStream createBodyStream(InputStream inputStream, long contentLength, SessionInputBufferImpl sessionInputBuffer) {
143+
InputStream bodyStream;
144+
if (contentLength > 0) {
145+
bodyStream = new ContentLengthInputStream(sessionInputBuffer, inputStream, contentLength);
146+
} else if (contentLength == 0) {
147+
bodyStream = EmptyInputStream.INSTANCE;
148+
} else if (TRANSFER_ENCODING_CHUNKED.equalsIgnoreCase(headers.get(HttpHeaders.TRANSFER_ENCODING))) {
149+
bodyStream = new ChunkedInputStream(sessionInputBuffer, inputStream);
150+
} else {
151+
bodyStream = EmptyInputStream.INSTANCE;
144152
}
153+
return bodyStream;
145154
}
146155

147156
@Override

http-server-undertow/src/main/java/io/micronaut/servlet/undertow/UndertowFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ protected Undertow undertowServer(Undertow.Builder builder) {
263263
*
264264
* @param servletConfiguration The servlet configuration.
265265
* @return The deployment info
266-
* @deprecated Use {@link ##deploymentInfo(MicronautServletConfiguration, Collection)}
266+
* @deprecated Use {@link #deploymentInfo(MicronautServletConfiguration, Collection)}
267267
*/
268268
@Deprecated(forRemoval = true, since = "4.8.0")
269269
protected DeploymentInfo deploymentInfo(MicronautServletConfiguration servletConfiguration) {

test-sample-poja/build.gradle

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,38 @@
1616
plugins {
1717
id("io.micronaut.build.internal.servlet.base")
1818
id("application")
19-
id("groovy")
19+
id 'org.graalvm.buildtools.native'
2020
}
2121

2222
dependencies {
2323
implementation(projects.micronautHttpPojaApache)
2424
implementation(mnLogging.slf4j.simple)
25-
implementation(mn.micronaut.jackson.databind)
25+
implementation(mnSerde.micronaut.serde.jackson)
2626
annotationProcessor(mn.micronaut.inject.java)
2727

2828
testImplementation(projects.micronautHttpPojaTest)
29-
testImplementation(mn.micronaut.jackson.databind)
30-
testImplementation(mnTest.micronaut.test.spock)
29+
testImplementation(mnTest.micronaut.test.junit5)
3130

32-
testImplementation(mn.micronaut.inject.groovy.test)
31+
testAnnotationProcessor(mn.micronaut.inject.java.test)
3332
testImplementation(mn.micronaut.inject.java)
34-
testImplementation(mn.micronaut.inject.groovy)
3533
}
3634

37-
run {
35+
application {
3836
mainClass.set("io.micronaut.http.poja.sample.Application")
37+
}
38+
39+
run {
3940
standardInput = System.in
4041
standardOutput = System.out
4142
}
4243

44+
graalvmNative {
45+
binaries.all {
46+
buildArgs.add("--gc=serial")
47+
buildArgs.add("--install-exit-handlers")
48+
}
49+
}
50+
4351
test {
4452
useJUnitPlatform()
4553
}

test-sample-poja/src/main/java/io/micronaut/http/poja/sample/TestController.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
import io.micronaut.http.annotation.Delete;
2424
import io.micronaut.http.annotation.Get;
2525
import io.micronaut.http.annotation.Post;
26+
import io.micronaut.http.annotation.Produces;
2627
import io.micronaut.http.annotation.Put;
2728
import io.micronaut.http.annotation.Status;
29+
import io.micronaut.http.poja.sample.model.Cactus;
2830

2931
/**
3032
* A controller for testing.
@@ -56,5 +58,11 @@ public final String update(@NonNull String name) {
5658
return "Hello, " + name + "!\n";
5759
}
5860

61+
@Get("/cactus")
62+
@Produces(MediaType.APPLICATION_JSON)
63+
public final Cactus getCactus() {
64+
return new Cactus("green", 1);
65+
}
66+
5967
}
6068

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.micronaut.http.poja.sample.model;
2+
3+
import io.micronaut.serde.annotation.Serdeable;
4+
5+
@Serdeable
6+
public record Cactus(
7+
String color,
8+
int spikeSize
9+
) {
10+
}

test-sample-poja/src/test/groovy/io/micronaut/http/poja/sample/SimpleServerSpec.groovy

Lines changed: 0 additions & 71 deletions
This file was deleted.

0 commit comments

Comments
 (0)