Cross-Origin Resource Sharing (CORS)
COSR(跨站点资源分享)通俗的讲是跨域问题,严格来说它是跨域问题的解决方案之一,而且是官方解决方案。
在CORS成为标准之前,是没有办法请求不同域名的后端API的,因为安全原因。请求会被同源策略阻止,现在也是。
参考 HTTP CORS
实例代码
例子说明
28 /**
29 * This example server aims to demonstrate
30 * <a href="http://www.w3.org/TR/cors/">Cross Origin Resource Sharing</a> (CORS) in Netty.
31 * It does not have a client like most of the other examples, but instead has
32 * a html page that is loaded to try out CORS support in a web browser.
33 * <p>
34 *
35 * CORS is configured in {@link HttpCorsServerInitializer} and by updating the config you can
36 * try out various combinations, like using a specific origin instead of a
37 * wildcard origin ('*').
38 * <p>
39 *
40 * The file {@code src/main/resources/cors/cors.html} contains a very basic example client
41 * which can be used to try out different configurations. For example, you can add
42 * custom headers to force a CORS preflight request to make the request fail. Then
43 * to enable a successful request, configure the CorsHandler to allow that/those
44 * request headers.
45 *
46 * <h2>Testing CORS</h2>
47 * You can either load the file {@code src/main/resources/cors/cors.html} using a web server
48 * or load it from the file system using a web browser.
49 *
50 * <h3>Using a web server</h3>
51 * To test CORS support you can serve the file {@code src/main/resources/cors/cors.html}
52 * using a web server. You can then add a new host name to your systems hosts file, for
53 * example if you are on Linux you may update /etc/hosts to add an additional name
54 * for you local system:
55 * <pre>
56 * 127.0.0.1 localhost domain1.com
57 * </pre>
58 * Now, you should be able to access {@code http://domain1.com/cors.html} depending on how you
59 * have configured you local web server the exact url may differ.
60 *
61 * <h3>Using a web browser</h3>
62 * Open the file {@code src/main/resources/cors/cors.html} in a web browser. You should see
63 * loaded page and in the text area the following message:
64 * <pre>
65 * 'CORS is not working'
66 * </pre>
67 *
68 * If you inspect the headers being sent using your browser you'll see that the 'Origin'
69 * request header is {@code 'null'}. This is expected and happens when you load a file from the
70 * local file system. Netty can handle this by configuring the CorsHandler which is done
71 * in the {@link HttpCorsServerInitializer}.
72 *
73 */
验证浏览器是否支持 cors
访问验证
修改 hosts 文件:
127.0.0.1 localhost domain1.com
访问:http://domain1.com/cors.html 直接指到对应的文件位置。
此处不再演示。
直接看下代码吧。
代码
服务端
- HttpCorsServer.java
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.http.cors.CorsConfig;
import io.netty.handler.codec.http.cors.CorsConfigBuilder;
import io.netty.handler.codec.http.cors.CorsHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
/**
* <p> </p>
*
* <pre> Created: 2019/9/22 10:20 AM </pre>
* <pre> Project: netty-learn </pre>
*
* @author houbinbin
*/
public class HttpCorsServer {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
CorsConfig corsConfig = CorsConfigBuilder
.forAnyOrigin()
.allowNullOrigin()
.allowCredentials()
.build();
//http 响应编码
ch.pipeline().addLast(new HttpResponseEncoder())
//http 请求解码
.addLast(new HttpRequestDecoder())
// 将 http 消息和内容聚合成一个完成的 http 请求信息
.addLast(new HttpObjectAggregator(65536))
// 较大的内容写处理
.addLast(new ChunkedWriteHandler())
// cors 处理器
.addLast(new CorsHandler(corsConfig))
// 为请求返回 ok 响应
.addLast(new OkResponseHandler());
}
})
.bind(8889)
.syncUninterruptibly();
channelFuture.channel().closeFuture().syncUninterruptibly();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
- OkResponseHandler.java
为请求返回 ok 响应
public class OkResponseHandler extends SimpleChannelInboundHandler<Object> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
final FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.EMPTY_BUFFER);
response.headers().set("custom-response-header", "Some value");
ctx.writeAndFlush(response)
.addListener(ChannelFutureListener.CLOSE);
}
}