View Javadoc
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    *   http://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.netty.example.http.cors;
17  
18  import io.netty.bootstrap.ServerBootstrap;
19  import io.netty.channel.EventLoopGroup;
20  import io.netty.channel.nio.NioEventLoopGroup;
21  import io.netty.channel.socket.nio.NioServerSocketChannel;
22  import io.netty.handler.logging.LogLevel;
23  import io.netty.handler.logging.LoggingHandler;
24  import io.netty.handler.ssl.SslContext;
25  import io.netty.handler.ssl.util.SelfSignedCertificate;
26  
27  /**
28   * This example server aims to demonstrate
29   * <a href="http://www.w3.org/TR/cors/">Cross Origin Resource Sharing</a> (CORS) in Netty.
30   * It does not have a client like most of the other examples, but instead has
31   * a html page that is loaded to try out CORS support in a web brower.
32   * <p>
33   *
34   * CORS is configured in {@link HttpCorsServerInitializer} and by updating the config you can
35   * try out various combinations, like using a specific origin instead of a
36   * wildcard origin ('*').
37   * <p>
38   *
39   * The file {@code src/main/resources/cors/cors.html} contains a very basic example client
40   * which can be used to try out different configurations. For example, you can add
41   * custom headers to force a CORS preflight request to make the request fail. Then
42   * to enable a successful request, configure the CorsHandler to allow that/those
43   * request headers.
44   *
45   * <h2>Testing CORS</h2>
46   * You can either load the file {@code src/main/resources/cors/cors.html} using a web server
47   * or load it from the file system using a web browser.
48   *
49   * <h3>Using a web server</h3>
50   * To test CORS support you can serve the file {@code src/main/resources/cors/cors.html}
51   * using a web server. You can then add a new host name to your systems hosts file, for
52   * example if you are on Linux you may update /etc/hosts to add an addtional name
53   * for you local system:
54   * <pre>
55   * 127.0.0.1   localhost domain1.com
56   * </pre>
57   * Now, you should be able to access {@code http://domain1.com/cors.html} depending on how you
58   * have configured you local web server the exact url may differ.
59   *
60   * <h3>Using a web browser</h3>
61   * Open the file {@code src/main/resources/cors/cors.html} in a web browser. You should see
62   * loaded page and in the text area the following message:
63   * <pre>
64   * 'CORS is not working'
65   * </pre>
66   *
67   * If you inspect the headers being sent using your browser you'll see that the 'Origin'
68   * request header is {@code 'null'}. This is expected and happens when you load a file from the
69   * local file system. Netty can handle this by configuring the CorsHandler which is done
70   * in the {@link HttpCorsServerInitializer}.
71   *
72   */
73  public final class HttpCorsServer {
74  
75      static final boolean SSL = System.getProperty("ssl") != null;
76      static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
77  
78      public static void main(String[] args) throws Exception {
79          // Configure SSL.
80          final SslContext sslCtx;
81          if (SSL) {
82              SelfSignedCertificate ssc = new SelfSignedCertificate();
83              sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
84          } else {
85              sslCtx = null;
86          }
87  
88          EventLoopGroup bossGroup = new NioEventLoopGroup(1);
89          EventLoopGroup workerGroup = new NioEventLoopGroup();
90          try {
91              ServerBootstrap b = new ServerBootstrap();
92              b.group(bossGroup, workerGroup)
93               .channel(NioServerSocketChannel.class)
94               .handler(new LoggingHandler(LogLevel.INFO))
95               .childHandler(new HttpCorsServerInitializer(sslCtx));
96  
97              b.bind(PORT).sync().channel().closeFuture().sync();
98          } finally {
99              bossGroup.shutdownGracefully();
100             workerGroup.shutdownGracefully();
101         }
102     }
103 }