HTTP 多部分响应 Netty
HTTP Multipart Response Netty
这是这个 question and I understand the accepted answer for that. But I wonder is there some inbuilt capability to send back multipart response message in Netty. I came across this class HttpPostRequestEncoder 的副本,它似乎可以完成创建多部分 POST 请求的工作。 Response 是否也有类似的东西?
创建类似于 HttpPostRequestEncoder 的等效逻辑并使其也适用于响应会很容易,但我想知道 Netty 中是否已经存在一些我不知道的东西。
我相信你是对的,没有这样的代码来进行多部分响应。
但我认为通过添加与 finalizeRequest() 类似的方法来完成 HttpResponse 来扩展 HttpPostRequestEncoder 可以很容易地实现它。
例如(未测试),添加以下方法至少是一个好的开始:
/**
* Finalize the response by preparing the Header in the response and returns the response ready to be sent.<br>
* Once finalized, no data must be added.<br>
* If the response does not need chunk (isChunked() == false), this response is the only object to send to the remote
* server.
*
* @return the response object (chunked or not according to size of body)
* @throws ErrorDataEncoderException
* if the encoding is in error or if the finalize were already done
*/
public HttpResponse finalizeResponse(HttpResponseStatus status) throws ErrorDataEncoderException {
// Finalize the multipartHttpDatas
if (!headerFinalized) {
if (isMultipart) {
InternalAttribute internal = new InternalAttribute(charset);
if (duringMixedMode) {
internal.addValue("\r\n--" + multipartMixedBoundary + "--");
}
internal.addValue("\r\n--" + multipartDataBoundary + "--\r\n");
multipartHttpDatas.add(internal);
multipartMixedBoundary = null;
currentFileUpload = null;
duringMixedMode = false;
globalBodySize += internal.size();
}
headerFinalized = true;
} else {
throw new ErrorDataEncoderException("Header already encoded");
}
HttpHeaders headers = request.headers();
List<String> contentTypes = headers.getAll(HttpHeaderNames.CONTENT_TYPE);
List<String> transferEncoding = headers.getAll(HttpHeaderNames.TRANSFER_ENCODING);
if (contentTypes != null) {
headers.remove(HttpHeaderNames.CONTENT_TYPE);
for (String contentType : contentTypes) {
// "multipart/form-data; boundary=--89421926422648"
String lowercased = contentType.toLowerCase();
if (lowercased.startsWith(HttpHeaderValues.MULTIPART_FORM_DATA.toString()) ||
lowercased.startsWith(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED.toString())) {
// ignore
} else {
headers.add(HttpHeaderNames.CONTENT_TYPE, contentType);
}
}
}
if (isMultipart) {
String value = HttpHeaderValues.MULTIPART_FORM_DATA + "; " + HttpHeaderValues.BOUNDARY + '='
+ multipartDataBoundary;
headers.add(HttpHeaderNames.CONTENT_TYPE, value);
} else {
// Not multipart
headers.add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED);
}
// Now consider size for chunk or not
long realSize = globalBodySize;
if (!isMultipart) {
realSize -= 1; // last '&' removed
}
iterator = multipartHttpDatas.listIterator();
headers.set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(realSize));
if (realSize > HttpPostBodyUtil.chunkSize || isMultipart) {
HttpResponse response = new DefaultHttpResponse(request.protocolVersion(), status);
response.headers().add(headers);
isChunked = true;
if (transferEncoding != null) {
headers.remove(HttpHeaderNames.TRANSFER_ENCODING);
for (CharSequence v : transferEncoding) {
if (HttpHeaderValues.CHUNKED.contentEqualsIgnoreCase(v)) {
// ignore
} else {
headers.add(HttpHeaderNames.TRANSFER_ENCODING, v);
}
}
}
HttpUtil.setTransferEncodingChunked(response, true);
return response;
} else {
// get the only one body and set it to the request
HttpContent chunk = nextChunk();
DefaultFullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), status, chunk.content());
response.headers().add(headers);
return response;
}
}
或者更简单:
public HttpResponse finalizeResponse(HttpResponseStatus status) throws ErrorDataEncoderException {
// Finalize the multipartHttpDatas
HttpRequest request = finalizeRequest();
if (request instanceof WrappedFullHttpRequest) {
DefaultFullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), status,
((WrappedFullHttpRequest) request).content());
response.headers().add(request.headers());
return response;
} else {
HttpResponse response = new DefaultHttpResponse(request.protocolVersion(), status);
response.headers().add(request.headers());
return response;
}
}
这是这个 question and I understand the accepted answer for that. But I wonder is there some inbuilt capability to send back multipart response message in Netty. I came across this class HttpPostRequestEncoder 的副本,它似乎可以完成创建多部分 POST 请求的工作。 Response 是否也有类似的东西?
创建类似于 HttpPostRequestEncoder 的等效逻辑并使其也适用于响应会很容易,但我想知道 Netty 中是否已经存在一些我不知道的东西。
我相信你是对的,没有这样的代码来进行多部分响应。 但我认为通过添加与 finalizeRequest() 类似的方法来完成 HttpResponse 来扩展 HttpPostRequestEncoder 可以很容易地实现它。
例如(未测试),添加以下方法至少是一个好的开始:
/**
* Finalize the response by preparing the Header in the response and returns the response ready to be sent.<br>
* Once finalized, no data must be added.<br>
* If the response does not need chunk (isChunked() == false), this response is the only object to send to the remote
* server.
*
* @return the response object (chunked or not according to size of body)
* @throws ErrorDataEncoderException
* if the encoding is in error or if the finalize were already done
*/
public HttpResponse finalizeResponse(HttpResponseStatus status) throws ErrorDataEncoderException {
// Finalize the multipartHttpDatas
if (!headerFinalized) {
if (isMultipart) {
InternalAttribute internal = new InternalAttribute(charset);
if (duringMixedMode) {
internal.addValue("\r\n--" + multipartMixedBoundary + "--");
}
internal.addValue("\r\n--" + multipartDataBoundary + "--\r\n");
multipartHttpDatas.add(internal);
multipartMixedBoundary = null;
currentFileUpload = null;
duringMixedMode = false;
globalBodySize += internal.size();
}
headerFinalized = true;
} else {
throw new ErrorDataEncoderException("Header already encoded");
}
HttpHeaders headers = request.headers();
List<String> contentTypes = headers.getAll(HttpHeaderNames.CONTENT_TYPE);
List<String> transferEncoding = headers.getAll(HttpHeaderNames.TRANSFER_ENCODING);
if (contentTypes != null) {
headers.remove(HttpHeaderNames.CONTENT_TYPE);
for (String contentType : contentTypes) {
// "multipart/form-data; boundary=--89421926422648"
String lowercased = contentType.toLowerCase();
if (lowercased.startsWith(HttpHeaderValues.MULTIPART_FORM_DATA.toString()) ||
lowercased.startsWith(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED.toString())) {
// ignore
} else {
headers.add(HttpHeaderNames.CONTENT_TYPE, contentType);
}
}
}
if (isMultipart) {
String value = HttpHeaderValues.MULTIPART_FORM_DATA + "; " + HttpHeaderValues.BOUNDARY + '='
+ multipartDataBoundary;
headers.add(HttpHeaderNames.CONTENT_TYPE, value);
} else {
// Not multipart
headers.add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED);
}
// Now consider size for chunk or not
long realSize = globalBodySize;
if (!isMultipart) {
realSize -= 1; // last '&' removed
}
iterator = multipartHttpDatas.listIterator();
headers.set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(realSize));
if (realSize > HttpPostBodyUtil.chunkSize || isMultipart) {
HttpResponse response = new DefaultHttpResponse(request.protocolVersion(), status);
response.headers().add(headers);
isChunked = true;
if (transferEncoding != null) {
headers.remove(HttpHeaderNames.TRANSFER_ENCODING);
for (CharSequence v : transferEncoding) {
if (HttpHeaderValues.CHUNKED.contentEqualsIgnoreCase(v)) {
// ignore
} else {
headers.add(HttpHeaderNames.TRANSFER_ENCODING, v);
}
}
}
HttpUtil.setTransferEncodingChunked(response, true);
return response;
} else {
// get the only one body and set it to the request
HttpContent chunk = nextChunk();
DefaultFullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), status, chunk.content());
response.headers().add(headers);
return response;
}
}
或者更简单:
public HttpResponse finalizeResponse(HttpResponseStatus status) throws ErrorDataEncoderException {
// Finalize the multipartHttpDatas
HttpRequest request = finalizeRequest();
if (request instanceof WrappedFullHttpRequest) {
DefaultFullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), status,
((WrappedFullHttpRequest) request).content());
response.headers().add(request.headers());
return response;
} else {
HttpResponse response = new DefaultHttpResponse(request.protocolVersion(), status);
response.headers().add(request.headers());
return response;
}
}