diff --git a/feat-core/src/main/java/tech/smartboot/feat/core/client/impl/AbstractOutputStream.java b/feat-core/src/main/java/tech/smartboot/feat/core/client/impl/AbstractOutputStream.java index e9b05ec79eb6eb15b37cf3d133b9f0e800ea9971..ca533e132cf61d83c826734a87a0b1ad788f5106 100644 --- a/feat-core/src/main/java/tech/smartboot/feat/core/client/impl/AbstractOutputStream.java +++ b/feat-core/src/main/java/tech/smartboot/feat/core/client/impl/AbstractOutputStream.java @@ -55,6 +55,7 @@ abstract class AbstractOutputStream extends FeatOutputStream { if (request.getContentType() != null) { writeString(HeaderName.CONTENT_TYPE.getName()); writeBuffer.writeByte((byte) ':'); + writeBuffer.writeByte((byte) ' '); writeBuffer.write(getBytes(String.valueOf(request.getContentType()))); writeBuffer.write(FeatUtils.CRLF_BYTES); } @@ -62,6 +63,7 @@ abstract class AbstractOutputStream extends FeatOutputStream { if (request.getContentLength() >= 0) { writeString(HeaderName.CONTENT_LENGTH.getName()); writeBuffer.writeByte((byte) ':'); + writeBuffer.writeByte((byte) ' '); writeBuffer.write(getBytes(String.valueOf(request.getContentLength()))); writeBuffer.write(FeatUtils.CRLF_BYTES); } else if (chunkedSupport) { @@ -75,6 +77,7 @@ abstract class AbstractOutputStream extends FeatOutputStream { while (headerValue != null) { writeString(entry.getKey()); writeBuffer.writeByte((byte) ':'); + writeBuffer.writeByte((byte) ' '); writeString(headerValue.getValue()); writeBuffer.write(FeatUtils.CRLF_BYTES); headerValue = headerValue.getNextValue(); diff --git a/feat-core/src/main/java/tech/smartboot/feat/core/common/io/FeatOutputStream.java b/feat-core/src/main/java/tech/smartboot/feat/core/common/io/FeatOutputStream.java index 3d86912ac400e0335f0400069348c55ef65166e9..9fb877ba0e1f40fa9f55e1339850a518eb9b8493 100644 --- a/feat-core/src/main/java/tech/smartboot/feat/core/common/io/FeatOutputStream.java +++ b/feat-core/src/main/java/tech/smartboot/feat/core/common/io/FeatOutputStream.java @@ -149,7 +149,7 @@ public abstract class FeatOutputStream extends OutputStream implements Reset { writeBuffer.write("0\r\n".getBytes()); Map map = trailerSupplier.get(); for (String key : map.keySet()) { - writeBuffer.write((key + ":" + map.get(key) + "\r\n").getBytes()); + writeBuffer.write((key + ": " + map.get(key) + "\r\n").getBytes()); } writeBuffer.write(FeatUtils.CRLF_BYTES); } else { diff --git a/feat-core/src/main/java/tech/smartboot/feat/core/server/impl/HttpOutputStream.java b/feat-core/src/main/java/tech/smartboot/feat/core/server/impl/HttpOutputStream.java index 999a1e32d845ef02ce7e6b0e67ba2d192d9ac0f6..bd02af5c9ae3051be64a5858126b5e6c2de63848 100644 --- a/feat-core/src/main/java/tech/smartboot/feat/core/server/impl/HttpOutputStream.java +++ b/feat-core/src/main/java/tech/smartboot/feat/core/server/impl/HttpOutputStream.java @@ -29,7 +29,9 @@ import java.util.concurrent.TimeUnit; * @version v1.0.0 */ final class HttpOutputStream extends FeatOutputStream { - private static final String TEXT_PLAIN_FAST_WRITE = HttpProtocol.HTTP_11.getProtocol() + " 200 OK\r\n" + HeaderName.SERVER.getName() + ":feat/" + Feat.VERSION + "\r\nDate:" + FeatUtils.formatRFC1123(FeatUtils.currentTime()) + "\r\nContent-Type:" + HeaderValue.ContentType.TEXT_PLAIN_UTF8 + "\r\nContent-Length:"; + private static final String TEXT_PLAIN_FAST_WRITE = HttpProtocol.HTTP_11.getProtocol() + " 200 OK\r\n" + HeaderName.SERVER.getName() + ": feat/" + Feat.VERSION + "\r\nDate: " + FeatUtils.formatRFC1123(FeatUtils.currentTime()) + "\r\nContent-Type: " + HeaderValue.ContentType.TEXT_PLAIN_UTF8 + "\r\nContent-Length: "; + // 以下索引/长度全部从 TEXT_PLAIN_FAST_WRITE 的文本中推导,改动上面常量里的 + // 头名前缀(例如冒号后补空格)时必须同步核对。 private static final int SERVER_INDEX = TEXT_PLAIN_FAST_WRITE.indexOf(HeaderName.SERVER.getName()); private static final int DATE_INDEX = TEXT_PLAIN_FAST_WRITE.indexOf("Date:"); private static final int SERVER_INDEX_LENGTH = TEXT_PLAIN_FAST_WRITE.indexOf(HeaderName.DATE.getName()) - SERVER_INDEX; @@ -37,7 +39,7 @@ final class HttpOutputStream extends FeatOutputStream { private static final int PLAIN_CONTENT_LENGTH_INDEX = TEXT_PLAIN_FAST_WRITE.indexOf(HeaderName.CONTENT_LENGTH.getName()) - 2; private static final byte[] TEXT_PLAIN_FAST_WRITE_BYTES = TEXT_PLAIN_FAST_WRITE.getBytes(); - private static final String APPLICATION_JSON = HttpProtocol.HTTP_11.getProtocol() + " 200 OK\r\n" + HeaderName.SERVER.getName() + ":feat/" + Feat.VERSION + "\r\nDate:" + FeatUtils.formatRFC1123(FeatUtils.currentTime()) + "\r\nContent-Type:" + HeaderValue.ContentType.APPLICATION_JSON + "\r\nContent-Length:"; + private static final String APPLICATION_JSON = HttpProtocol.HTTP_11.getProtocol() + " 200 OK\r\n" + HeaderName.SERVER.getName() + ": feat/" + Feat.VERSION + "\r\nDate: " + FeatUtils.formatRFC1123(FeatUtils.currentTime()) + "\r\nContent-Type: " + HeaderValue.ContentType.APPLICATION_JSON + "\r\nContent-Length: "; private static final int JSON_CONTENT_LENGTH_INDEX = APPLICATION_JSON.indexOf(HeaderName.CONTENT_LENGTH.getName()) - 2; private static final byte[] APPLICATION_JSON_FAST_WRITE_BYTES = APPLICATION_JSON.getBytes(); private static final byte[] CHUNKED = "\r\nTransfer-Encoding: chunked\r\n\r\n".getBytes(); @@ -48,8 +50,8 @@ final class HttpOutputStream extends FeatOutputStream { HashedWheelTimer.DEFAULT_TIMER.scheduleWithFixedDelay(() -> { byte[] bytes = FeatUtils.formatRFC1123(FeatUtils.currentTime()).getBytes(); - System.arraycopy(bytes, 0, TEXT_PLAIN_FAST_WRITE_BYTES, DATE_INDEX + 5, bytes.length); - System.arraycopy(bytes, 0, APPLICATION_JSON_FAST_WRITE_BYTES, DATE_INDEX + 5, bytes.length); + System.arraycopy(bytes, 0, TEXT_PLAIN_FAST_WRITE_BYTES, DATE_INDEX + 6, bytes.length); + System.arraycopy(bytes, 0, APPLICATION_JSON_FAST_WRITE_BYTES, DATE_INDEX + 6, bytes.length); }, 800, TimeUnit.MILLISECONDS); } @@ -96,6 +98,7 @@ final class HttpOutputStream extends FeatOutputStream { while (headerValue != null) { writeString(entry.getKey()); writeBuffer.writeByte((byte) ':'); + writeBuffer.writeByte((byte) ' '); writeString(headerValue.getValue()); writeBuffer.write(FeatUtils.CRLF_BYTES); headerValue = headerValue.getNextValue(); @@ -129,15 +132,15 @@ final class HttpOutputStream extends FeatOutputStream { writeBuffer.write(TEXT_PLAIN_FAST_WRITE_BYTES, SERVER_INDEX, SERVER_INDEX_LENGTH); } // Date - writeBuffer.write(TEXT_PLAIN_FAST_WRITE_BYTES, DATE_INDEX, 34); + writeBuffer.write(TEXT_PLAIN_FAST_WRITE_BYTES, DATE_INDEX, 35); if (contentType != null) { - writeBuffer.write(TEXT_PLAIN_FAST_WRITE_BYTES, PLAIN_CONTENT_TYPE_INDEX, 15); + writeBuffer.write(TEXT_PLAIN_FAST_WRITE_BYTES, PLAIN_CONTENT_TYPE_INDEX, 16); writeString(contentType); } if (contentLength >= 0) { - writeBuffer.write(TEXT_PLAIN_FAST_WRITE_BYTES, PLAIN_CONTENT_LENGTH_INDEX, 17); + writeBuffer.write(TEXT_PLAIN_FAST_WRITE_BYTES, PLAIN_CONTENT_LENGTH_INDEX, 18); writeLongString(contentLength); if (hasHeader) { writeBuffer.write(FeatUtils.CRLF_BYTES);