This is an automated email from the ASF dual-hosted git repository.
dockerzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git
The following commit(s) were added to refs/heads/master by this push:
new 2da89aa15 [INLONG-8068][Manager] Support repeatable read for http
request (#8075)
2da89aa15 is described below
commit 2da89aa157dae5b59417587f04c73fda394e4dd2
Author: vernedeng <[email protected]>
AuthorDate: Thu May 25 16:18:02 2023 +0800
[INLONG-8068][Manager] Support repeatable read for http request (#8075)
Co-authored-by: vernedeng <[email protected]>
---
.../inlong/manager/web/auth/InlongShiroImpl.java | 4 +
.../manager/web/auth/web/AuthenticationFilter.java | 1 -
.../web/filter/HttpServletRequestFilter.java | 54 ++++++++
.../inlong/manager/web/utils/HttpContextUtils.java | 111 ++++++++++++++++
.../manager/web/utils/InlongRequestWrapper.java | 144 +++++++++++++++++++++
.../web/filter/HttpServletRequestFilterTest.java | 77 +++++++++++
6 files changed, 390 insertions(+), 1 deletion(-)
diff --git
a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/InlongShiroImpl.java
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/InlongShiroImpl.java
index 5954a367b..178323cc8 100644
---
a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/InlongShiroImpl.java
+++
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/InlongShiroImpl.java
@@ -94,9 +94,13 @@ public class InlongShiroImpl implements InlongShiro {
shiroFilterFactoryBean.setSecurityManager(securityManager);
// anon: can be accessed by anyone, authc: only authentication is
successful can be accessed
Map<String, Filter> filters = new LinkedHashMap<>();
+
+ // request filter
filters.put(FILTER_NAME_WEB, new AuthenticationFilter());
+
shiroFilterFactoryBean.setFilters(filters);
Map<String, String> pathDefinitions = new LinkedHashMap<>();
+
// login, register request
pathDefinitions.put("/api/anno/**/*", "anon");
diff --git
a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/web/AuthenticationFilter.java
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/web/AuthenticationFilter.java
index d40acb7c1..60f11b772 100644
---
a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/web/AuthenticationFilter.java
+++
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/web/AuthenticationFilter.java
@@ -59,7 +59,6 @@ public class AuthenticationFilter implements Filter {
public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)
servletRequest;
-
Subject subject = SecurityUtils.getSubject();
if (subject.isAuthenticated()) {
UserInfo loginUserInfo = (UserInfo) subject.getPrincipal();
diff --git
a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/filter/HttpServletRequestFilter.java
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/filter/HttpServletRequestFilter.java
new file mode 100644
index 000000000..387095324
--- /dev/null
+++
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/filter/HttpServletRequestFilter.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.manager.web.filter;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.inlong.manager.web.utils.InlongRequestWrapper;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/**
+ * HttpServletRequestFilter
+ * Make All
+ */
+@Slf4j
+@Component
+@WebFilter
+@Order(0)
+public class HttpServletRequestFilter implements Filter {
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ if (servletRequest instanceof HttpServletRequest) {
+ ServletRequest requestWrapper = new
InlongRequestWrapper((HttpServletRequest) servletRequest);
+ filterChain.doFilter(requestWrapper, servletResponse);
+ } else {
+ filterChain.doFilter(servletRequest, servletResponse);
+ }
+ }
+}
diff --git
a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/utils/HttpContextUtils.java
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/utils/HttpContextUtils.java
new file mode 100644
index 000000000..b82ab07d0
--- /dev/null
+++
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/utils/HttpContextUtils.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.manager.web.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * HttpContextUtils
+ */
+@Slf4j
+public class HttpContextUtils {
+
+ /**
+ * Get request params
+ * @param request
+ * @return
+ */
+ public static Map<String, String> getParameterMapAll(HttpServletRequest
request) {
+ Enumeration<String> parameters = request.getParameterNames();
+
+ Map<String, String> params = new HashMap<>();
+ while (parameters.hasMoreElements()) {
+ String parameter = parameters.nextElement();
+ String value = request.getParameter(parameter);
+ params.put(parameter, value);
+ }
+ return params;
+ }
+
+ public static Map<String, String[]> getParameterMap(HttpServletRequest
request) {
+ Map<String, String[]> paramMap = new HashMap<>();
+ String queryString = request.getQueryString();
+ if (StringUtils.isNotBlank(queryString)) {
+ String[] params = queryString.split("&");
+ for (int i = 0; i < params.length; i++) {
+ int splitIndex = params[i].indexOf("=");
+ if (splitIndex == -1) {
+ continue;
+ }
+ String key = params[i].substring(0, splitIndex);
+ if (!paramMap.containsKey(key)) {
+ if (splitIndex < params[i].length()) {
+ String value = params[i].substring(splitIndex + 1);
+ paramMap.put(key, new String[]{value});
+ }
+ }
+ }
+ }
+ return paramMap;
+ }
+
+ public static Map<String, String> getHeaderMapAll(HttpServletRequest
request) {
+ Enumeration<String> headerNames = request.getHeaderNames();
+ Map<String, String> headers = new HashMap<>();
+ while (headerNames.hasMoreElements()) {
+ String parameter = headerNames.nextElement();
+ String value = request.getHeader(parameter);
+ headers.put(parameter, value);
+ }
+ return headers;
+ }
+
+ /**
+ * Get request body
+ * @param request
+ * @return
+ */
+ public static String getBodyString(ServletRequest request) {
+ StringBuilder sb = new StringBuilder();
+ try (InputStream inputStream = request.getInputStream()) {
+ try (BufferedReader reader =
+ new BufferedReader(new InputStreamReader(inputStream,
StandardCharsets.UTF_8))) {
+ String line = "";
+ while ((line = reader.readLine()) != null) {
+ sb.append(line);
+ }
+ }
+ } catch (IOException e) {
+ log.error("failed to get body string of request={}", request);
+ }
+ return sb.toString();
+ }
+
+}
\ No newline at end of file
diff --git
a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/utils/InlongRequestWrapper.java
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/utils/InlongRequestWrapper.java
new file mode 100644
index 000000000..a3f0d4b3b
--- /dev/null
+++
b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/utils/InlongRequestWrapper.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.manager.web.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+/**
+ * Inlong http request wrapper
+ */
+@Slf4j
+public class InlongRequestWrapper extends HttpServletRequestWrapper {
+
+ private static final ObjectMapper mapper = new ObjectMapper();
+
+ private String bodyParams;
+
+ private Map<String, String[]> params;
+
+ private Map<String, String> headers;
+
+ public InlongRequestWrapper(HttpServletRequest request) {
+ super(request);
+ this.bodyParams = HttpContextUtils.getBodyString(request);
+ this.params = HttpContextUtils.getParameterMap(request);
+ this.headers = HttpContextUtils.getHeaderMapAll(request);
+ }
+
+ @Override
+ public String getParameter(String name) {
+ String result;
+ Object v = params.get(name);
+ if (v == null) {
+ result = null;
+ } else if (v instanceof String[]) {
+ String[] strArr = (String[]) v;
+ if (strArr.length > 0) {
+ result = strArr[0];
+ } else {
+ result = null;
+ }
+ } else if (v instanceof String) {
+ result = (String) v;
+ } else {
+ result = v.toString();
+ }
+ return result;
+ }
+
+ @Override
+ public Map<String, String[]> getParameterMap() {
+ return params;
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+ String[] result;
+ Object v = params.get(name);
+ if (v == null) {
+ result = null;
+ } else if (v instanceof String[]) {
+ result = (String[]) v;
+ } else if (v instanceof String) {
+ result = new String[]{(String) v};
+ } else {
+ result = new String[]{v.toString()};
+ }
+ return result;
+ }
+
+ @Override
+ public ServletInputStream getInputStream() {
+ final ByteArrayInputStream inputStream = new
ByteArrayInputStream(bodyParams.getBytes(StandardCharsets.UTF_8));
+ return new ServletInputStream() {
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ // no op
+ }
+
+ @Override
+ public int read() {
+ return inputStream.read();
+ }
+ };
+ }
+
+ @Override
+ public BufferedReader getReader() {
+ return new BufferedReader(new
InputStreamReader(this.getInputStream()));
+ }
+
+ public void addHeader(String name, String value) {
+ headers.put(name, value);
+ }
+
+ public void addBodyParam(String key, String value) throws
JsonProcessingException {
+ ObjectNode objectNode = (ObjectNode) mapper.readTree(bodyParams);
+ objectNode.put(key, value);
+ bodyParams = objectNode.toString();
+ }
+
+ public void addParameter(String name, String value) {
+ params.put(name, new String[]{value});
+ }
+
+}
diff --git
a/inlong-manager/manager-web/src/test/java/org/apache/inlong/manager/web/filter/HttpServletRequestFilterTest.java
b/inlong-manager/manager-web/src/test/java/org/apache/inlong/manager/web/filter/HttpServletRequestFilterTest.java
new file mode 100644
index 000000000..62d7a1b24
--- /dev/null
+++
b/inlong-manager/manager-web/src/test/java/org/apache/inlong/manager/web/filter/HttpServletRequestFilterTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.manager.web.filter;
+
+import org.apache.inlong.manager.web.WebBaseTest;
+import org.apache.inlong.manager.web.utils.InlongRequestWrapper;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.mock.web.MockFilterChain;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+public class HttpServletRequestFilterTest extends WebBaseTest {
+
+ @Test
+ public void testRepeatableRead() {
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ String bodyStr = "test body str";
+ req.setContent(bodyStr.getBytes());
+ Servlet servlet = new HttpServlet() {
+ };
+ MockHttpServletResponse res = new MockHttpServletResponse();
+ HttpServletRequestFilter filter = new HttpServletRequestFilter();
+ FilterChecker checker = new FilterChecker();
+ MockFilterChain filterChain = new MockFilterChain(servlet, filter,
checker);
+ Assertions.assertDoesNotThrow(() -> filterChain.doFilter(req, res));
+ }
+
+ class FilterChecker implements Filter {
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
+ throws IOException, ServletException {
+ Assertions.assertInstanceOf(InlongRequestWrapper.class, request);
+ String first = "";
+ String line;
+ BufferedReader reader = request.getReader();
+ while ((line = reader.readLine()) != null) {
+ first += line;
+ }
+
+ String second = "";
+ BufferedReader reader2 = request.getReader();
+ while ((line = reader2.readLine()) != null) {
+ second += line;
+ }
+
+ Assertions.assertEquals(first, second);
+ }
+ }
+
+}
\ No newline at end of file