1 /* 2 * Copyright 2012 The Netty Project 3 * 4 * The Netty Project licenses this file to you under the Apache License, 5 * version 2.0 (the "License"); you may not use this file except in compliance 6 * with the License. You may obtain a copy of the License at: 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 package io.netty5.example.http.cors; 17 18 import io.netty5.bootstrap.ServerBootstrap; 19 import io.netty5.channel.EventLoopGroup; 20 import io.netty5.channel.MultithreadEventLoopGroup; 21 import io.netty5.channel.nio.NioHandler; 22 import io.netty5.channel.socket.nio.NioServerSocketChannel; 23 import io.netty5.handler.logging.LogLevel; 24 import io.netty5.handler.logging.LoggingHandler; 25 import io.netty5.handler.ssl.SslContext; 26 import io.netty5.handler.ssl.SslContextBuilder; 27 import io.netty5.handler.ssl.util.SelfSignedCertificate; 28 29 /** 30 * This example server aims to demonstrate 31 * <a href="https://www.w3.org/TR/cors/">Cross Origin Resource Sharing</a> (CORS) in Netty. 32 * It does not have a client like most of the other examples, but instead has 33 * a html page that is loaded to try out CORS support in a web browser. 34 * <p> 35 * 36 * CORS is configured in {@link HttpCorsServerInitializer} and by updating the config you can 37 * try out various combinations, like using a specific origin instead of a 38 * wildcard origin ('*'). 39 * <p> 40 * 41 * The file {@code src/main/resources/cors/cors.html} contains a very basic example client 42 * which can be used to try out different configurations. For example, you can add 43 * custom headers to force a CORS preflight request to make the request fail. Then 44 * to enable a successful request, configure the CorsHandler to allow that/those 45 * request headers. 46 * 47 * <h2>Testing CORS</h2> 48 * You can either load the file {@code src/main/resources/cors/cors.html} using a web server 49 * or load it from the file system using a web browser. 50 * 51 * <h3>Using a web server</h3> 52 * To test CORS support you can serve the file {@code src/main/resources/cors/cors.html} 53 * using a web server. You can then add a new host name to your systems hosts file, for 54 * example if you are on Linux you may update /etc/hosts to add an additional name 55 * for you local system: 56 * <pre> 57 * 127.0.0.1 localhost domain1.com 58 * </pre> 59 * Now, you should be able to access {@code http://domain1.com/cors.html} depending on how you 60 * have configured you local web server the exact url may differ. 61 * 62 * <h3>Using a web browser</h3> 63 * Open the file {@code src/main/resources/cors/cors.html} in a web browser. You should see 64 * loaded page and in the text area the following message: 65 * <pre> 66 * 'CORS is not working' 67 * </pre> 68 * 69 * If you inspect the headers being sent using your browser you'll see that the 'Origin' 70 * request header is {@code 'null'}. This is expected and happens when you load a file from the 71 * local file system. Netty can handle this by configuring the CorsHandler which is done 72 * in the {@link HttpCorsServerInitializer}. 73 * 74 */ 75 public final class HttpCorsServer { 76 77 static final boolean SSL = System.getProperty("ssl") != null; 78 static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080")); 79 80 public static void main(String[] args) throws Exception { 81 // Configure SSL. 82 final SslContext sslCtx; 83 if (SSL) { 84 SelfSignedCertificate ssc = new SelfSignedCertificate(); 85 sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); 86 } else { 87 sslCtx = null; 88 } 89 90 EventLoopGroup bossGroup = new MultithreadEventLoopGroup(1, NioHandler.newFactory()); 91 EventLoopGroup workerGroup = new MultithreadEventLoopGroup(NioHandler.newFactory()); 92 try { 93 ServerBootstrap b = new ServerBootstrap(); 94 b.group(bossGroup, workerGroup) 95 .channel(NioServerSocketChannel.class) 96 .handler(new LoggingHandler(LogLevel.INFO)) 97 .childHandler(new HttpCorsServerInitializer(sslCtx)); 98 99 b.bind(PORT).asStage().get().closeFuture().asStage().sync(); 100 } finally { 101 bossGroup.shutdownGracefully(); 102 workerGroup.shutdownGracefully(); 103 } 104 } 105 }