diff --git a/core/src/main/java/com/taobao/arthas/core/shell/session/SessionManager.java b/core/src/main/java/com/taobao/arthas/core/shell/session/SessionManager.java
new file mode 100644
index 000000000..011888fef
--- /dev/null
+++ b/core/src/main/java/com/taobao/arthas/core/shell/session/SessionManager.java
@@ -0,0 +1,9 @@
+package com.taobao.arthas.core.shell.session;
+
+/**
+ * Arthas Session Manager
+ * @author gongdewei 2020-03-20
+ */
+public interface SessionManager {
+
+}
diff --git a/core/src/main/java/com/taobao/arthas/core/shell/session/impl/SessionManagerImpl.java b/core/src/main/java/com/taobao/arthas/core/shell/session/impl/SessionManagerImpl.java
new file mode 100644
index 000000000..9ba2ed8e6
--- /dev/null
+++ b/core/src/main/java/com/taobao/arthas/core/shell/session/impl/SessionManagerImpl.java
@@ -0,0 +1,9 @@
+package com.taobao.arthas.core.shell.session.impl;
+
+/**
+ * Arthas Session Manager
+ * @author gongdewei 2020-03-20
+ */
+public interface SessionManagerImpl {
+
+}
diff --git a/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/HttpRequestHandler.java b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/HttpRequestHandler.java
index d241fe400..8276ecf4d 100644
--- a/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/HttpRequestHandler.java
+++ b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/HttpRequestHandler.java
@@ -7,6 +7,7 @@ import java.net.URI;
import java.net.URL;
import com.taobao.arthas.common.IOUtils;
+import com.taobao.arthas.core.shell.term.impl.http.api.HttpApiHandler;
import com.taobao.arthas.core.util.LogUtil;
import com.taobao.middleware.logger.Logger;
@@ -30,6 +31,7 @@ import io.termd.core.util.Logging;
/**
* @author Julien Viet
* @author hengyunabc 2019-11-06
+ * @author gongdewei 2020-03-18
*/
public class HttpRequestHandler extends SimpleChannelInboundHandler {
private static final Logger logger = LogUtil.getArthasLogger();
@@ -38,10 +40,13 @@ public class HttpRequestHandler extends SimpleChannelInboundHandler options;
+
+ @Override
+ public String toString() {
+ return "ApiRequest{" +
+ "action='" + action + '\'' +
+ ", sync=" + sync +
+ ", command='" + command + '\'' +
+ ", options=" + options +
+ '}';
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public boolean isSync() {
+ return sync;
+ }
+
+ public void setSync(boolean sync) {
+ this.sync = sync;
+ }
+
+ public String getCommand() {
+ return command;
+ }
+
+ public void setCommand(String command) {
+ this.command = command;
+ }
+
+ public Map getOptions() {
+ return options;
+ }
+
+ public void setOptions(Map options) {
+ this.options = options;
+ }
+}
diff --git a/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/ApiResponse.java b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/ApiResponse.java
new file mode 100644
index 000000000..5382aedff
--- /dev/null
+++ b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/ApiResponse.java
@@ -0,0 +1,72 @@
+package com.taobao.arthas.core.shell.term.impl.http.api;
+
+/**
+ * Http Api exception
+ * @author gongdewei 2020-03-19
+ */
+public class ApiResponse {
+ private String requestId;
+ private ApiState state;
+ private String message;
+ private String sessionId;
+ private String consumerId;
+ private String jobId;
+ private T body;
+
+ public String getRequestId() {
+ return requestId;
+ }
+
+ public void setRequestId(String requestId) {
+ this.requestId = requestId;
+ }
+
+ public ApiState getState() {
+ return state;
+ }
+
+ public void setState(ApiState state) {
+ this.state = state;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSessionId() {
+ return sessionId;
+ }
+
+ public void setSessionId(String sessionId) {
+ this.sessionId = sessionId;
+ }
+
+ public String getConsumerId() {
+ return consumerId;
+ }
+
+ public void setConsumerId(String consumerId) {
+ this.consumerId = consumerId;
+ }
+
+ public String getJobId() {
+ return jobId;
+ }
+
+ public void setJobId(String jobId) {
+ this.jobId = jobId;
+ }
+
+ public T getBody() {
+ return body;
+ }
+
+ public void setBody(T body) {
+ this.body = body;
+ }
+
+}
diff --git a/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/ApiState.java b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/ApiState.java
new file mode 100644
index 000000000..ec3cfce0d
--- /dev/null
+++ b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/ApiState.java
@@ -0,0 +1,14 @@
+package com.taobao.arthas.core.shell.term.impl.http.api;
+
+/**
+ * Http API response state
+ * @author gongdewei 2020-03-19
+ */
+public enum ApiState {
+ /** accepted */
+ SCHEDULED,
+ RUNNING,
+ SUCCEEDED,
+ FAILED,
+ REFUSED
+}
diff --git a/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/HttpApiHandler.java b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/HttpApiHandler.java
new file mode 100644
index 000000000..f4662c3c9
--- /dev/null
+++ b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/HttpApiHandler.java
@@ -0,0 +1,111 @@
+package com.taobao.arthas.core.shell.term.impl.http.api;
+
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.taobao.arthas.core.server.ArthasBootstrap;
+import com.taobao.arthas.core.shell.ShellServer;
+import com.taobao.arthas.core.util.LogUtil;
+import com.taobao.arthas.core.util.StringUtils;
+import com.taobao.middleware.logger.Logger;
+import io.netty.buffer.ByteBuf;
+import io.netty.handler.codec.http.*;
+import io.netty.util.CharsetUtil;
+
+
+/**
+ * Http Restful Api Handler
+ * @author gongdewei 2020-03-18
+ */
+public class HttpApiHandler {
+
+ private static final Logger logger = LogUtil.getArthasLogger();
+
+ public HttpResponse handle(FullHttpRequest request) throws Exception {
+ DefaultFullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(),
+ HttpResponseStatus.OK);
+
+ ApiResponse result = null;
+ String requestBody = null;
+ try {
+ HttpMethod method = request.method();
+ if (HttpMethod.POST.equals(method)){
+ requestBody = getBody(request);
+ ApiRequest apiRequest = parseRequest(requestBody);
+ result = processRequest(apiRequest);
+ } else {
+ result = createResponse(ApiState.REFUSED, "Unsupported http method: "+method.name());
+ }
+ } catch (Throwable e) {
+ result = createResponse(ApiState.FAILED, "Process request error: "+e.getMessage());
+ logger.error("arthas", "arthas process http api request error: " + request.uri()+", request body: "+requestBody, e);
+ }
+ if (result == null) {
+ result = createResponse(ApiState.FAILED, "The request was not processed");
+ }
+
+ String jsonResult = JSON.toJSONString(result);
+ response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=utf-8");
+ response.content().writeBytes(jsonResult.getBytes("UTF-8"));
+ return response;
+ }
+
+ private ApiRequest parseRequest(String requestBody) throws ApiException {
+ if (StringUtils.isBlank(requestBody)){
+ throw new ApiException("parse request failed: request body is empty");
+ }
+ try {
+ //Object jsonRequest = JSON.parse(requestBody);
+ ObjectMapper objectMapper = new ObjectMapper();
+ return objectMapper.readValue(requestBody, ApiRequest.class);
+ } catch (Exception e) {
+ throw new ApiException("parse request failed: "+e.getMessage(), e);
+ }
+ }
+
+ private ApiResponse processRequest(ApiRequest apiRequest) {
+
+ String action = apiRequest.getAction();
+ if ("exec".equalsIgnoreCase(action)){
+ return processExecRequest(apiRequest);
+ } else if("init_session".equalsIgnoreCase(action)){
+ return processInitSessionRequest(apiRequest);
+ } else if("close_session".equalsIgnoreCase(action)){
+ return processCloseSessionRequest(apiRequest);
+ }
+
+ return createResponse(ApiState.REFUSED, "Unsupported action: "+action);
+ }
+
+ private ApiResponse processInitSessionRequest(ApiRequest apiRequest) {
+// ShellServer shellServer = getShellServer();
+// shellServer.createShell()
+
+ return null;
+ }
+
+ private ApiResponse processCloseSessionRequest(ApiRequest apiRequest) {
+ return null;
+ }
+
+ private ApiResponse processExecRequest(ApiRequest apiRequest) {
+ String command = apiRequest.getCommand();
+ //TODO
+ return null;
+ }
+
+ private ApiResponse createResponse(ApiState apiState, String message) {
+ ApiResponse apiResponse = new ApiResponse();
+ apiResponse.setState(apiState);
+ apiResponse.setMessage(message);
+ return apiResponse;
+ }
+
+ private String getBody(FullHttpRequest request){
+ ByteBuf buf = request.content();
+ return buf.toString(CharsetUtil.UTF_8);
+ }
+
+// private ShellServer getShellServer() {
+// return ArthasBootstrap.getInstance().getShellServer();
+// }
+}