项目微服务改造,增加gateway后发现出现神奇问题: postman可以访问,vue浏览器访问不了。不通过gateway直接访问原项目就可以。
原项目跨域是通过webmvc 解决的 ,但是gateway 有个包和这个冲突。所以开始在网上找通过gateway解决的办法。
原来通过浏览器看到一个请求会有两个记录,都报错,如下图。
后来通过网上搜到下面代码加上后,其中xhr的请求返回200 但是没有响应内容。在xhr.js请求中能看到返回值,好神奇。
CORS Allow Origin Not Matching Origin
access-control-allow-origin
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;
import com.idealeye.gateway.filter.CorsResponseHeaderFilter;
@Configuration
public class CrosFilter {
@Bean
public CorsWebFilter corsFilter(){
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", buildConfig());
return new CorsWebFilter(source);
}
private CorsConfiguration buildConfig(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}
}
继续搜,然后又找到下面代码:
import java.util.ArrayList;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class CorsResponseHeaderFilter implements GlobalFilter, Ordered {
@Override
public int getOrder() {
// 指定此过滤器位于NettyWriteResponseFilter之后
// 即待处理完响应体后接着处理响应头
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1;
}
@Override
@SuppressWarnings("serial")
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange).then(Mono.defer(() -> {
exchange.getResponse().getHeaders().entrySet().stream()
.filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))
.filter(kv -> (kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
|| kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)))
.forEach(kv ->
{
kv.setValue(new ArrayList<String>() {{
add(kv.getValue().get(0));
}});
});
return chain.filter(exchange);
}));
}
}
然后再crosConfig中加入如下代码:
@Bean
public CorsResponseHeaderFilter corsResponseHeaderFilter() {
return new CorsResponseHeaderFilter();
}
这回没问题了。还有的是不需要加后面 CorsResponseHeaderFilter的,在配置里增加filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin也能用。
spring:
cloud:
gateway:
routes:
- id: xxx_route
uri: lb://xxx
predicates:
- Path=/**
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
- StripPrefix=1
由于是后来记录的,参考文章没找到,真的抱歉。希望对遇到相同问题的小伙伴有用。