选项 Http 请求失败并出现 404 异常,而 Post 请求工作正常
OPTIONS Http request is failing with 404 exception while Post request is working fine
我在 spring 框架中有一个带有可选 PathVariable 的休息端点。
@PostMapping("/API_PATH/{param1}/{param2}")
public Result getResult(@PathVariable Integer param1,
@PathVariable(required = false) Integer param2, @RequestBody Data data) {
// SOME LOGIC HERE
}
我已将 param2
路径变量标记为不需要。所以它是一个可选值。当我不向 param2
发送任何值时,此 POST API 工作正常。但是当浏览器尝试访问此 API 时,它会在发送实际 POST
请求之前发送 OPTIONS
类型的请求。现在,如果 OPTIONS
请求不包含 URL 中的第二个路径变量 (param2
),它将失败并出现 404 异常。有没有办法解决这个问题?
OPTIONS 请求就是我们在 Cross-origin 资源共享 (CORS) 中所说的 pre-flight 请求,它检查安全措施。同样,您可能需要添加 CORS 配置
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class WebConfig implements Filter,WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
System.out.println("WebConfig; "+request.getRequestURI());
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With,observe");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Expose-Headers", "Authorization");
response.addHeader("Access-Control-Expose-Headers", "responseType");
response.addHeader("Access-Control-Expose-Headers", "observe");
System.out.println("Request Method: "+request.getMethod());
if (!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
try {
chain.doFilter(req, res);
} catch(Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Pre-flight");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Expose-Headers"+"Authorization, content-type," +
"USERID"+"ROLE"+
"access-control-request-headers,access-control-request-method,accept,origin,authorization,x-requested-with,responseType,observe");
response.setStatus(HttpServletResponse.SC_OK);
}
}
}
其他一些CORS配置方式
使用 CorsRegistry
:
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain1.com","http://domain2.com");
}
使用@CrossOrigin
:
@CrossOrigin(origins = {"http://domain1.com","http://domain2.com"})
使用application.properties
management.endpoints.web.cors.allowed-origins=http://domain1.com,http://domain2.com
您的代码专门针对 POST
,因此没有针对 OPTIONS
的处理程序。 Spring 提供了一个实现 pre-flight CORS 处理程序的 CrossOrigin
注释,请阅读 here。
试试这个:
@CrossOrigin
@PostMapping("/API_PATH/{param1}/{param2}")
public Result getResult(@PathVariable Integer param1,
@PathVariable(required = false) Integer param2, @RequestBody Data data) {
// SOME LOGIC HERE
}
我在 spring 框架中有一个带有可选 PathVariable 的休息端点。
@PostMapping("/API_PATH/{param1}/{param2}")
public Result getResult(@PathVariable Integer param1,
@PathVariable(required = false) Integer param2, @RequestBody Data data) {
// SOME LOGIC HERE
}
我已将 param2
路径变量标记为不需要。所以它是一个可选值。当我不向 param2
发送任何值时,此 POST API 工作正常。但是当浏览器尝试访问此 API 时,它会在发送实际 POST
请求之前发送 OPTIONS
类型的请求。现在,如果 OPTIONS
请求不包含 URL 中的第二个路径变量 (param2
),它将失败并出现 404 异常。有没有办法解决这个问题?
OPTIONS 请求就是我们在 Cross-origin 资源共享 (CORS) 中所说的 pre-flight 请求,它检查安全措施。同样,您可能需要添加 CORS 配置
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class WebConfig implements Filter,WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
System.out.println("WebConfig; "+request.getRequestURI());
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With,observe");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Expose-Headers", "Authorization");
response.addHeader("Access-Control-Expose-Headers", "responseType");
response.addHeader("Access-Control-Expose-Headers", "observe");
System.out.println("Request Method: "+request.getMethod());
if (!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
try {
chain.doFilter(req, res);
} catch(Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Pre-flight");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Expose-Headers"+"Authorization, content-type," +
"USERID"+"ROLE"+
"access-control-request-headers,access-control-request-method,accept,origin,authorization,x-requested-with,responseType,observe");
response.setStatus(HttpServletResponse.SC_OK);
}
}
}
其他一些CORS配置方式
使用 CorsRegistry
:
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain1.com","http://domain2.com");
}
使用@CrossOrigin
:
@CrossOrigin(origins = {"http://domain1.com","http://domain2.com"})
使用application.properties
management.endpoints.web.cors.allowed-origins=http://domain1.com,http://domain2.com
您的代码专门针对 POST
,因此没有针对 OPTIONS
的处理程序。 Spring 提供了一个实现 pre-flight CORS 处理程序的 CrossOrigin
注释,请阅读 here。
试试这个:
@CrossOrigin
@PostMapping("/API_PATH/{param1}/{param2}")
public Result getResult(@PathVariable Integer param1,
@PathVariable(required = false) Integer param2, @RequestBody Data data) {
// SOME LOGIC HERE
}