|
15 | 15 | */ |
16 | 16 | package io.fusionauth.http.server; |
17 | 17 |
|
| 18 | +import java.io.ByteArrayOutputStream; |
18 | 19 | import java.nio.ByteBuffer; |
| 20 | +import java.nio.charset.StandardCharsets; |
19 | 21 |
|
20 | 22 | import io.fusionauth.http.HTTPMethod; |
21 | 23 | import io.fusionauth.http.HTTPValues.Headers; |
|
34 | 36 | public class HTTPRequestProcessor { |
35 | 37 | private final int bufferSize; |
36 | 38 |
|
37 | | - // TODO : Should this be sized with a configuration parameter? |
38 | | - private final StringBuilder builder = new StringBuilder(); |
| 39 | + // Allocate a 4k buffer for starters, it will grow as needed. |
| 40 | + private final ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(4096); |
39 | 41 |
|
40 | 42 | private final HTTPServerConfiguration configuration; |
41 | 43 |
|
@@ -78,28 +80,27 @@ public RequestState processBodyBytes() { |
78 | 80 |
|
79 | 81 | public RequestState processPreambleBytes(ByteBuffer buffer) { |
80 | 82 | while (buffer.hasRemaining()) { |
81 | | - // TODO : Can we get some performance using ByteBuffer rather than StringBuilder here? |
82 | 83 |
|
83 | 84 | // If there is a state transition, store the value properly and reset the builder (if needed) |
84 | 85 | byte ch = buffer.get(); |
85 | 86 | RequestPreambleState nextState = preambleState.next(ch); |
86 | 87 | if (nextState != preambleState) { |
87 | 88 | switch (preambleState) { |
88 | | - case RequestMethod -> request.setMethod(HTTPMethod.of(builder.toString())); |
89 | | - case RequestPath -> request.setPath(builder.toString()); |
90 | | - case RequestProtocol -> request.setProtocol(builder.toString()); |
91 | | - case HeaderName -> headerName = builder.toString(); |
92 | | - case HeaderValue -> request.addHeader(headerName, builder.toString()); |
| 89 | + case RequestMethod -> request.setMethod(HTTPMethod.of(byteBuffer.toString(StandardCharsets.UTF_8))); |
| 90 | + case RequestPath -> request.setPath(byteBuffer.toString(StandardCharsets.UTF_8)); |
| 91 | + case RequestProtocol -> request.setProtocol(byteBuffer.toString(StandardCharsets.UTF_8)); |
| 92 | + case HeaderName -> headerName = byteBuffer.toString(StandardCharsets.UTF_8); |
| 93 | + case HeaderValue -> request.addHeader(headerName, byteBuffer.toString(StandardCharsets.UTF_8)); |
93 | 94 | } |
94 | 95 |
|
95 | 96 | // If the next state is storing, reset the builder |
96 | 97 | if (nextState.store()) { |
97 | | - builder.delete(0, builder.length()); |
98 | | - builder.appendCodePoint(ch); |
| 98 | + byteBuffer.reset(); |
| 99 | + byteBuffer.write(ch); |
99 | 100 | } |
100 | 101 | } else if (preambleState.store()) { |
101 | 102 | // If the current state is storing, store the character |
102 | | - builder.appendCodePoint(ch); |
| 103 | + byteBuffer.write(ch); |
103 | 104 | } |
104 | 105 |
|
105 | 106 | preambleState = nextState; |
|
0 commit comments