From aaeeea37e568544dcd78806bec7eaa4d5d7c9eb0 Mon Sep 17 00:00:00 2001 From: jason Date: Fri, 12 Apr 2019 09:19:07 +0800 Subject: [PATCH] Feature: Make transport-netty-http/transport-simple-http support posting --- .../command/netty/HttpServerHandler.java | 32 ++++++++++ .../transport/command/http/HttpEventTask.java | 63 ++++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/netty/HttpServerHandler.java b/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/netty/HttpServerHandler.java index 31a70fc9..956ecad3 100755 --- a/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/netty/HttpServerHandler.java +++ b/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/netty/HttpServerHandler.java @@ -15,6 +15,7 @@ */ package com.alibaba.csp.sentinel.transport.command.netty; +import java.io.IOException; import java.nio.charset.Charset; import java.util.List; import java.util.Map; @@ -39,10 +40,15 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaderValues; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpUtil; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.QueryStringDecoder; +import io.netty.handler.codec.http.multipart.HttpData; +import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import io.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType; import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST; import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR; @@ -171,6 +177,32 @@ public class HttpServerHandler extends SimpleChannelInboundHandler { } } } + // Deal with post method, parameter in post has more privilege compared to that in querystring + if (request.method().equals(HttpMethod.POST)) { + // support multi-part and form-urlencoded + HttpPostRequestDecoder postRequestDecoder = null; + try { + postRequestDecoder = new HttpPostRequestDecoder(request); + for (InterfaceHttpData data : postRequestDecoder.getBodyHttpDatas()) { + data.retain(); // must retain each attr before destroy + if (data.getHttpDataType() == HttpDataType.Attribute) { + if (data instanceof HttpData) { + HttpData httpData = (HttpData) data; + try { + String name = httpData.getName(); + String value = httpData.getString(); + serverRequest.addParam(name, value); + } catch (IOException e) { + } + } + } + } + } finally { + if (postRequestDecoder != null) { + postRequestDecoder.destroy(); + } + } + } // Parse command name. String target = parseTarget(queryStringDecoder.rawPath()); serverRequest.addMetadata(HttpCommandUtils.REQUEST_TARGET, target); diff --git a/sentinel-transport/sentinel-transport-simple-http/src/main/java/com/alibaba/csp/sentinel/transport/command/http/HttpEventTask.java b/sentinel-transport/sentinel-transport-simple-http/src/main/java/com/alibaba/csp/sentinel/transport/command/http/HttpEventTask.java index 957d44ad..80df0955 100755 --- a/sentinel-transport/sentinel-transport-simple-http/src/main/java/com/alibaba/csp/sentinel/transport/command/http/HttpEventTask.java +++ b/sentinel-transport/sentinel-transport-simple-http/src/main/java/com/alibaba/csp/sentinel/transport/command/http/HttpEventTask.java @@ -75,6 +75,61 @@ public class HttpEventTask implements Runnable { CommandCenterLog.info("[SimpleHttpCommandCenter] socket income: " + line + "," + socket.getInetAddress()); CommandRequest request = parseRequest(line); + + if (line.length() > 4 && StringUtil.equalsIgnoreCase("POST", line.substring(0, 4))) { + // Deal with post method + // Now simple-http only support form-encoded post request. + String bodyLine = null; + boolean bodyNext = false; + boolean supported = false; + int maxLength = 8192; + while (true) { + // Body processing + if (bodyNext) { + if (!supported) { + break; + } + char[] bodyBytes = new char[maxLength]; + int read = in.read(bodyBytes); + String postData = new String(bodyBytes, 0, read); + parseParams(postData, request); + break; + } + + bodyLine = in.readLine(); + if (bodyLine == null) { + break; + } + // Body seperator + if (StringUtil.isEmpty(bodyLine)) { + bodyNext = true; + continue; + } + // Header processing + int index = bodyLine.indexOf(":"); + if (index < 1) { + continue; + } + String headerName = bodyLine.substring(0, index); + String header = bodyLine.substring(index + 1).trim(); + if (StringUtil.equalsIgnoreCase("content-type", headerName)) { + if (StringUtil.equals("application/x-www-form-urlencoded", header)) { + supported = true; + } else { + // not support request + break; + } + } else if (StringUtil.equalsIgnoreCase("content-length", headerName)) { + try { + int len = new Integer(header); + if (len > 0) { + maxLength = len; + } + } catch (Exception e) { + } + } + } + } // Validate the target command. String commandName = HttpCommandUtils.getTarget(request); @@ -203,7 +258,12 @@ public class HttpEventTask implements Runnable { return request; } String parameterStr = line.substring(ask != -1 ? ask + 1 : 0, space != -1 ? space : line.length()); - for (String parameter : parameterStr.split("&")) { + parseParams(parameterStr, request); + return request; + } + + private void parseParams(String queryString, CommandRequest request) { + for (String parameter : queryString.split("&")) { if (StringUtil.isBlank(parameter)) { continue; } @@ -221,7 +281,6 @@ public class HttpEventTask implements Runnable { request.addParam(StringUtil.trim(keyValue[0]), value); } - return request; } private static final String SERVER_ERROR_MESSAGE = "Command server error";