【发布时间】:2020-04-27 02:39:03
【问题描述】:
Tomcat(托管我的 java 后端 API)有这个过滤器:
<filter>
<filter-name>ApiOriginFilter</filter-name>
<filter-class>io.swagger.api.ApiOriginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ApiOriginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这是这个java代码(我添加了 System.out.println("Test"); 部分):
package io.swagger.api;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
@javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.JavaJerseyServerCodegen", date = "2020-01-07T08:47:08.031Z[GMT]")public class ApiOriginFilter implements javax.servlet.Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type");
chain.doFilter(request, response);
System.out.println("Test");
}
public void destroy() {}
public void init(FilterConfig filterConfig) throws ServletException {}
}
我正在构建一个 Ionic/React/Typescript 应用程序,它执行以下 API 调用 Java API:
const apiClient = axios.create({
baseURL: 'http://10.0.29.1:8080/swagger-jaxrs-server.1.0.0/v1/',
responseType: 'json',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin' : '*'
}
});
const createUser = async (newUser: NewUser) => {
try {
const response = await apiClient.post<User>('/users', newUser);
const user = response.data;
return user;
} catch (err) {
if (err && err.response) {
const axiosError = err as AxiosError<ServerError>
if (axiosError.response)
{
return axiosError.response.data;
}
else
{
return 0;
}
}
它只是发布到“http://10.0.29.1:8080/swagger-jaxrs-server.1.0.0/v1/users”。在 Chrome 和 Firefox 中执行此调用时,我收到以下响应:
Chrome OPTIONS 响应: Firefox 选项响应:
两个浏览器当然都抱怨 CORS(OPTIONS 响应标头中没有 Access-Control-Allow-Origin):
Firefox CORS 警告: Chrome CORS 警告
当我在 POSTMAN 中做同样的事情时:
它有效。
转到/opt/tomcat/logs/catalina.out 我明白了:
“测试”行来自我从邮递员发帖时。它是 System.out.println("Test");我在 ApiOriginFilter.java 函数中添加的代码。表示当 Postman 发送 OPTIONS 时会触发过滤器。浏览器发生了什么?这个响应来自哪里,为什么没有触发过滤器?
更新:如果我复制并粘贴 Firefox/Chrome 与 OPTIONS 请求一起发送给 Postman 的标头,Postman 仍然可以工作。如果我将 Postman 标头复制到 headers.txt 文件中:
User-Agent: PostmanRuntime/7.21.0
Accept: */*
Cache-Control: no-cache
Postman-Token: b3b6ae69-58fe-44dc-bdf0-7280679f0f32
Host: 10.0.29.1:8080
Accept-Encoding: gzip, deflate
Content-Length: 0
Connection: keep-alive
然后执行 curl -H @headers.txt -i -X OPTIONS http://10.0.29.1:8080/swagger-jaxrs-server.1.0.0/v1/users 它响应
HTTP/1.1 200
Allow: OPTIONS, GET, HEAD, POST
Content-Length: 0
Date: Fri, 10 Jan 2020 06:47:45 GMT
Keep-Alive: timeout=20
Connection: keep-alive
这意味着过滤器没有被调用。如果我只是 curl -i -X OPTIONS http://10.0.29.1:8080/swagger-jaxrs-server.1.0.0/v1/users 它会响应
HTTP/1.1 200
Allow: OPTIONS, GET, HEAD, POST
Content-Length: 0
Date: Fri, 10 Jan 2020 06:51:37 GMT
仍然没有调用过滤器。
【问题讨论】:
-
与浏览器发送的内容相比,您的 Postman 请求是否在属性方面有所不同?一般建议是保持它们完全相同。
-
我同意,但我不控制浏览器的 OPTIONS 调用,它由浏览器自动完成
-
但你确实控制着你的邮递员。
-
我将 Firefox/Chrome 的所有标题复制并粘贴到 Postman 并发送了请求,但 Postman 仍然可以使用
-
不确定是否相关,但您的 Typescript 是否在 URL 中添加了两个斜杠?像“//用户”。另外,尝试将
@WebFilter(urlPatterns = {"/*"})添加到您的过滤器中。