下面列出了 io.netty.handler.codec.http.multipart.InterfaceHttpData # getHttpDataType ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private static Map<String,String> getAttribs(FullHttpRequest request) {
String header = HttpHeaders.getHeader(request, HttpHeaders.Names.CONTENT_TYPE);
if (HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED.equalsIgnoreCase(header)) {
Map<String,String> attribs = new HashMap<>();
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), request);
List<InterfaceHttpData> data = decoder.getBodyHttpDatas();
if (data != null) {
for (InterfaceHttpData datum : data) {
if (datum.getHttpDataType() == HttpDataType.Attribute) {
Attribute attribute = (Attribute)datum;
try {
attribs.put(attribute.getName(), attribute.getString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
return attribs;
}
}
return null;
}
private Map<String, List<String>> parsePostFormParameters(FullHttpRequest request) {
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), request);
Map<String, List<String>> attributes = new HashMap<String, List<String>>();
List<InterfaceHttpData> datas = decoder.getBodyHttpDatas();
for (InterfaceHttpData data : datas) {
if (data.getHttpDataType() == HttpDataType.Attribute) {
try {
String name = data.getName();
String value = ((Attribute) data).getString();
attributes.putIfAbsent(name, new ArrayList<String>());
attributes.get(name).add(value);
} catch (IOException e) {
LOGGER.error("Error getting HTTP attribute from POST request");
}
}
}
decoder.destroy();
return attributes;
}
@Nullable
public static String extractFormParam(HttpPostRequestDecoder decoder, String name, boolean required) throws HttpException {
InterfaceHttpData data = decoder.getBodyHttpData(name);
try {
String value = null;
if(data != null && data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
Attribute attribute = (Attribute) data;
value = attribute.getValue();
}
if(value == null && required) {
throw new HttpException(HttpResponseStatus.BAD_REQUEST.code());
}
return value;
} catch(IOException ioe) {
throw new HttpException(HttpResponseStatus.INTERNAL_SERVER_ERROR.code());
}
}
protected DFHttpMultiData(HttpPostRequestDecoder reqDecoder) {
this.reqDecoder = reqDecoder;
List<InterfaceHttpData> lsReqData = reqDecoder.getBodyHttpDatas();
if(lsReqData.isEmpty()){
lsData = null;
partNum = 0;
}else{
int tmpNum = 0;
lsData = new ArrayList<>(lsReqData.size());
for(InterfaceHttpData reqData : lsReqData){
if(reqData.getHttpDataType() == HttpDataType.FileUpload){
FileUpload fUp = (FileUpload) reqData;
String tmpFile = fUp.getFilename();
if(tmpFile == null || tmpFile.equals("")){
continue;
}
DFHttpData data = new DFHttpData(fUp);
lsData.add(data);
++tmpNum;
}
}
partNum = tmpNum;
}
}
private void parseHttpPostRequest(FullHttpRequest request) {
HttpPostRequestDecoder decoder = null;
try {
decoder = new HttpPostRequestDecoder(request);
for (InterfaceHttpData httpData : decoder.getBodyHttpDatas()) {
HttpDataType _type = httpData.getHttpDataType();
if (_type == HttpDataType.Attribute) {
Attribute attribute = (Attribute) httpData;
parseAttribute(attribute);
} else if (_type == HttpDataType.FileUpload) {
FileUpload upload = (FileUpload) httpData;
multipartFiles.add(MultipartFileFactory.create(upload));
}
}
} catch (Exception ex) {
LogUtils.warn(ex.getMessage());
} finally {
// 注意这个地方,一定要调用destroy方法,如果不调用会导致内存泄漏
if (decoder != null)
decoder.destroy();
}
}
@Override
public Object get(ChannelHandlerContext ctx, URIDecoder uriDecoder) {
List<InterfaceHttpData> bodyHttpDatas = uriDecoder.getBodyHttpDatas();
if (bodyHttpDatas == null || bodyHttpDatas.size() == 0) {
return null;
}
for (InterfaceHttpData data : bodyHttpDatas) {
if (name.equals(data.getName())) {
if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
Attribute attribute = (Attribute) data;
try {
return ReflectionUtil.castTo(type, attribute.getValue());
} catch (IOException e) {
log.error("Error getting form params. Reason : {}", e.getMessage(), e);
}
}
}
}
return null;
}
void copyHttpBodyData(FullHttpRequest fullHttpReq, MockHttpServletRequest servletRequest){
ByteBuf bbContent = fullHttpReq.content();
if(bbContent.hasArray()) {
servletRequest.setContent(bbContent.array());
} else {
if(fullHttpReq.getMethod().equals(HttpMethod.POST)){
HttpPostRequestDecoder decoderPostData = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), fullHttpReq);
String bbContentStr = bbContent.toString(Charset.forName(UTF_8));
servletRequest.setContent(bbContentStr.getBytes());
if( ! decoderPostData.isMultipart() ){
List<InterfaceHttpData> postDatas = decoderPostData.getBodyHttpDatas();
for (InterfaceHttpData postData : postDatas) {
if (postData.getHttpDataType() == HttpDataType.Attribute) {
Attribute attribute = (Attribute) postData;
try {
servletRequest.addParameter(attribute.getName(),attribute.getValue());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
}
public void init(Channel channel, FullHttpRequest request, RouteResult<RouteAction> routeResult, boolean enableCookies) {
this.channel = channel;
this.request = request;
this.routeResult = routeResult;
this.enableCookies = enableCookies;
if (this.method() == HttpMethod.POST) {
try {
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(request);
decoder.offer(request);
List<InterfaceHttpData> paramsList = decoder.getBodyHttpDatas();
for (InterfaceHttpData httpData : paramsList) {
if (httpData.getHttpDataType() == HttpDataType.Attribute) {
Attribute data = (Attribute) httpData;
postMaps.put(data.getName(), data.getValue());
} else if (httpData.getHttpDataType() == HttpDataType.FileUpload) {
MixedFileUpload fileUpload = (MixedFileUpload) httpData;
this.fileUpload = fileUpload;
} else {
LOGGER.error("not support http data type. type={}", httpData.getHttpDataType());
}
}
} catch (Exception ex) {
LOGGER.error("{}", ex);
}
}
if (enableCookies) {
List<String> cookiesList = request.headers().getAll(HttpHeaderNames.COOKIE);
cookiesList.forEach(h -> ServerCookieDecoder.STRICT.decode(h).forEach(c -> cookieMaps.put(c.name(), c)));
}
}
@Override
public void sendResponse(FullHttpRequest req, ChannelHandlerContext ctx) throws Exception {
long startTime = System.nanoTime();
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(req);
try {
String place = null;
int num = 0;
while(decoder.hasNext()) {
num++;
InterfaceHttpData httpData = decoder.next();
if(httpData.getHttpDataType() == HttpDataType.Attribute && httpData.getName().equalsIgnoreCase("place")) {
place = ((Attribute) httpData).getValue();
} else if(httpData.getHttpDataType() == HttpDataType.FileUpload) {
String camProtAddr = URLDecoder.decode(httpData.getName(), "UTF-8");
Device d = findCamera(camProtAddr);
if(d == null) {
UPLOAD_UNKNOWN.inc();
logger.warn("ignoring preview upload for non-existent camera {}", camProtAddr);
continue;
}
write(place, d, (FileUpload) httpData);
}
}
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
ChannelFuture future = ctx.writeAndFlush(response);
if(!HttpHeaders.isKeepAlive(req)) {
future.addListener(ChannelFutureListener.CLOSE);
}
UPLOAD_NUM.update(num);
UPLOAD_SUCCESS.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
} catch (Exception ex) {
UPLOAD_FAIL.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
} finally {
decoder.cleanFiles();
}
}
private static String formatContent(FullHttpRequest request) {
String header = HttpHeaders.getHeader(request, HttpHeaders.Names.CONTENT_TYPE);
StringBuffer bf = new StringBuffer();
if (HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED.equalsIgnoreCase(header)) {
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), request);
List<InterfaceHttpData> data = decoder.getBodyHttpDatas();
if (data != null) {
for (InterfaceHttpData datum : data) {
if (datum.getHttpDataType() == HttpDataType.Attribute) {
Attribute attribute = (Attribute)datum;
try {
bf.append(attribute.getName()).append(" -> ").append(attribute.getString()).append("\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
else {
bf.append("[No Data]\n");
}
}
else if ("application/json".equalsIgnoreCase(header)) {
ByteBuf byteBuf = request.content();
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
String s = new String(bytes, StandardCharsets.UTF_8);
bf.append(s);
}
else {
bf.append("[Unknown Data Type ").append(header).append("]");
}
return bf.toString();
}
public static String extractFormParam(HttpPostRequestDecoder decoder, String name, boolean required) throws IOException {
InterfaceHttpData data = decoder.getBodyHttpData(name);
if(data != null && data.getHttpDataType() == HttpDataType.Attribute) {
Attribute attribute = (Attribute) data;
return attribute.getValue();
}
if(required) {
throw new MissingParameterException(name);
}
return null;
}
private void doPost(ChannelHandlerContext ctx, SessionContext sctx) {
WebRequest webRequest = getWebRequest();
JSONObject data = webRequest.getData();
try {
while (postRequestDecoder.hasNext()) {
InterfaceHttpData httpData = postRequestDecoder.next();
try {
if (httpData.getHttpDataType() == HttpDataType.Attribute ||
httpData.getHttpDataType() == HttpDataType.InternalAttribute) {
Attribute attribute = (Attribute) httpData;
data.put(attribute.getName(), attribute.getValue());
} else if (httpData.getHttpDataType() == HttpDataType.FileUpload) {
FileUpload fileUpload = (FileUpload) httpData;
if (fileUpload.isCompleted()) {
webRequest.getFileUploadMap().put(fileUpload.getName(), new WebFileUpload(fileUpload));
} else {
log.error("fileUpload not complete name[{}]", fileUpload.getName());
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
postRequestDecoder.removeHttpDataFromClean(httpData);
httpData.release();
}
}
} catch (EndOfDataDecoderException ignored) {
}
if (webRequest.isDynamic()) {
doWork(ctx, sctx, webRequest);
} else {
doFile(ctx, sctx, webRequest);
}
}
@Override
public @NotNull CompletableFuture<ResponseInfo<String>> execute(
@NotNull RequestInfo<String> request,
@NotNull Executor longRunningTaskExecutor,
@NotNull ChannelHandlerContext ctx
) {
List<String> hashesFound = new ArrayList<>();
for (InterfaceHttpData multipartData : request.getMultipartParts()) {
String name = multipartData.getName();
byte[] payloadBytes;
try {
payloadBytes = ((HttpData)multipartData).get();
} catch (IOException e) {
throw new RuntimeException(e);
}
String filename = null;
switch (multipartData.getHttpDataType()) {
case Attribute:
// Do nothing - filename stays null
break;
case FileUpload:
filename = ((FileUpload)multipartData).getFilename();
break;
default:
throw new RuntimeException("Unsupported multipart type: " + multipartData.getHttpDataType().name());
}
hashesFound.add(getHashForMultipartPayload(name, filename, payloadBytes));
}
return CompletableFuture.completedFuture(ResponseInfo.newBuilder(StringUtils.join(hashesFound, ",")).build());
}
private HttpResponseStatus readFileUploadData() throws IOException {
while (this.decoder.hasNext()) {
final InterfaceHttpData data = this.decoder.next();
if (data != null) {
try {
logger.info("BODY FileUpload: " + data.getHttpDataType().name() + ": " + data);
if (data.getHttpDataType() == HttpDataType.FileUpload) {
final FileUpload fileUpload = (FileUpload) data;
if (fileUpload.isCompleted()) {
this.requestProcessed = true;
final String format = ImageStoreUtil.checkTemplateFormat(fileUpload.getFile().getAbsolutePath(), fileUpload.getFilename());
if (StringUtils.isNotBlank(format)) {
final String errorString = "File type mismatch between the sent file and the actual content. Received: " + format;
logger.error(errorString);
this.responseContent.append(errorString);
this.storageResource.updateStateMapWithError(this.uuid, errorString);
return HttpResponseStatus.BAD_REQUEST;
}
final String status = this.storageResource.postUpload(this.uuid, fileUpload.getFile().getName());
if (status != null) {
this.responseContent.append(status);
this.storageResource.updateStateMapWithError(this.uuid, status);
return HttpResponseStatus.INTERNAL_SERVER_ERROR;
} else {
this.responseContent.append("upload successful.");
return HttpResponseStatus.OK;
}
}
}
} finally {
data.release();
}
}
}
this.responseContent.append("received entity is not a file");
return HttpResponseStatus.UNPROCESSABLE_ENTITY;
}
private void handleUploadFile(InterfaceHttpData data, Message uploadMessage) throws IOException{
FileForm fileForm = (FileForm)uploadMessage.getBody();
if(fileForm == null){
fileForm = new FileForm();
uploadMessage.setBody(fileForm);
}
if (data.getHttpDataType() == HttpDataType.Attribute) {
Attribute attribute = (Attribute) data;
fileForm.attributes.put(attribute.getName(), attribute.getValue());
return;
}
if (data.getHttpDataType() == HttpDataType.FileUpload) {
FileUpload fileUpload = (FileUpload) data;
Http.FileUpload file = new Http.FileUpload();
file.fileName = fileUpload.getFilename();
file.contentType = fileUpload.getContentType();
file.data = fileUpload.get();
List<Http.FileUpload> uploads = fileForm.files.get(data.getName());
if(uploads == null){
uploads = new ArrayList<Http.FileUpload>();
fileForm.files.put(data.getName(), uploads);
}
uploads.add(file);
}
}
private void writeHttpData(InterfaceHttpData data) {
try {
InterfaceHttpData.HttpDataType dataType = data.getHttpDataType();
if (dataType == InterfaceHttpData.HttpDataType.Attribute) {
parseAttribute((Attribute) data);
} else if (dataType == InterfaceHttpData.HttpDataType.FileUpload) {
parseFileUpload((FileUpload) data);
}
} catch (IOException e) {
log.error("Parse request parameter error", e);
}
}
private HttpResponseStatus readFileUploadData() throws IOException {
while (decoder.hasNext()) {
InterfaceHttpData data = decoder.next();
if (data != null) {
try {
logger.info("BODY FileUpload: " + data.getHttpDataType().name() + ": " + data);
if (data.getHttpDataType() == HttpDataType.FileUpload) {
FileUpload fileUpload = (FileUpload) data;
if (fileUpload.isCompleted()) {
requestProcessed = true;
String format = ImageStoreUtil.checkTemplateFormat(fileUpload.getFile().getAbsolutePath(), fileUpload.getFilename());
if(StringUtils.isNotBlank(format)) {
String errorString = "File type mismatch between the sent file and the actual content. Received: " + format;
logger.error(errorString);
responseContent.append(errorString);
storageResource.updateStateMapWithError(uuid, errorString);
return HttpResponseStatus.BAD_REQUEST;
}
String status = storageResource.postUpload(uuid, fileUpload.getFile().getName(), processTimeout);
if (status != null) {
responseContent.append(status);
storageResource.updateStateMapWithError(uuid, status);
return HttpResponseStatus.INTERNAL_SERVER_ERROR;
} else {
responseContent.append("upload successful.");
return HttpResponseStatus.OK;
}
}
}
} finally {
data.release();
}
}
}
responseContent.append("received entity is not a file");
return HttpResponseStatus.UNPROCESSABLE_ENTITY;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
DecoderResult decoderResult = msg.decoderResult();
if (!decoderResult.isSuccess()) {
ctx.writeAndFlush(HttpResponseHelper.newBadRequestResponse())
.addListener(ChannelFutureListener.CLOSE);
logger.warn("decode failed.", decoderResult.cause());
return;
}
HttpMethod method = msg.method();
// 仅限get和post请求
if (method != HttpMethod.GET && method != HttpMethod.POST) {
ctx.writeAndFlush(HttpResponseHelper.newBadRequestResponse())
.addListener(ChannelFutureListener.CLOSE);
logger.info("unsupported method {}", method.name());
return;
}
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(msg.uri());
String path = queryStringDecoder.path();
Map<String, String> paramsMap = new LinkedHashMap<>();
if (method == HttpMethod.GET) {
for (Map.Entry<String, List<String>> entry : queryStringDecoder.parameters().entrySet()) {
paramsMap.put(entry.getKey(), entry.getValue().get(0));
}
} else {
// You <strong>MUST</strong> call {@link #destroy()} after completion to release all resources.
HttpPostRequestDecoder postRequestDecoder = new HttpPostRequestDecoder(msg);
try {
for (InterfaceHttpData httpData : postRequestDecoder.getBodyHttpDatas()) {
if (httpData.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
Attribute attribute = (Attribute) httpData;
paramsMap.put(attribute.getName(), attribute.getValue());
}
}
} finally {
postRequestDecoder.destroy();
}
}
final HttpRequestParam httpRequestParam = new HttpRequestParam(method, paramsMap);
publish(new HttpRequestEvent(ctx.channel(), path, httpRequestParam, portExtraInfo));
}
/**
* Processes a single decoded part in a multipart request. Exposes the data in the part either through the channel
* itself (if it is the blob part) or via {@link #getArgs()}.
* @param part the {@link InterfaceHttpData} that needs to be processed.
* @throws RestServiceException if the request channel is closed, if there is more than one part of the same name, if
* the size obtained from the headers does not match the actual size of the blob part or
* if {@code part} is not of the expected type ({@link FileUpload}).
*/
private void processPart(InterfaceHttpData part) throws RestServiceException {
if (part.getHttpDataType() == InterfaceHttpData.HttpDataType.FileUpload) {
FileUpload fileUpload = (FileUpload) part;
if (fileUpload.getName().equals(RestUtils.MultipartPost.BLOB_PART)) {
// this is actual data.
if (hasBlob) {
nettyMetrics.repeatedPartsError.inc();
throw new RestServiceException("Request has more than one " + RestUtils.MultipartPost.BLOB_PART,
RestServiceErrorCode.BadRequest);
} else {
hasBlob = true;
if (getSize() != -1 && fileUpload.length() != getSize()) {
nettyMetrics.multipartRequestSizeMismatchError.inc();
throw new RestServiceException(
"Request size [" + fileUpload.length() + "] does not match Content-Length [" + getSize() + "]",
RestServiceErrorCode.BadRequest);
} else {
contentLock.lock();
try {
if (isOpen()) {
requestContents.add(new DefaultHttpContent(ReferenceCountUtil.retain(fileUpload.content())));
blobBytesReceived.set(fileUpload.content().capacity());
} else {
nettyMetrics.multipartRequestAlreadyClosedError.inc();
throw new RestServiceException("Request is closed", RestServiceErrorCode.RequestChannelClosed);
}
} finally {
contentLock.unlock();
}
}
}
} else {
// this is any kind of data. (For ambry, this will be user metadata).
// TODO: find a configurable way of rejecting unexpected file parts.
String name = fileUpload.getName();
if (allArgs.containsKey(name)) {
nettyMetrics.repeatedPartsError.inc();
throw new RestServiceException("Request already has a component named " + name,
RestServiceErrorCode.BadRequest);
} else {
ByteBuffer buffer = ByteBuffer.allocate(fileUpload.content().readableBytes());
// TODO: Possible optimization - Upgrade ByteBufferReadableStreamChannel to take a list of ByteBuffer. This
// TODO: will avoid the copy.
fileUpload.content().readBytes(buffer);
buffer.flip();
allArgs.put(name, buffer);
}
}
} else {
nettyMetrics.unsupportedPartError.inc();
throw new RestServiceException("Unexpected HTTP data", RestServiceErrorCode.BadRequest);
}
}