SPDY example app
This commit is contained in:
parent
b1392050f7
commit
9a9f98ffcd
@ -69,6 +69,10 @@
|
||||
<artifactId>javassist</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.npn</groupId>
|
||||
<artifactId>npn-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- see https://github.com/netty/netty/issues/874 -->
|
||||
<dependency>
|
||||
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.example.spdy;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import io.netty.channel.ChannelInboundHandler;
|
||||
import org.eclipse.jetty.npn.NextProtoNego;
|
||||
|
||||
import io.netty.handler.codec.spdy.SpdyOrHttpChooser;
|
||||
|
||||
/**
|
||||
* Negotiates with the browser if SPDY or HTTP is going to be used. Once decided, the Netty pipeline is setup with
|
||||
* the correct handlers for the selected protocol.
|
||||
*/
|
||||
public class SpdyOrHttpHandler extends SpdyOrHttpChooser {
|
||||
private static final int MAX_CONTENT_LENGTH = 1024 * 100;
|
||||
|
||||
public SpdyOrHttpHandler() {
|
||||
this(MAX_CONTENT_LENGTH, MAX_CONTENT_LENGTH);
|
||||
}
|
||||
|
||||
public SpdyOrHttpHandler(int maxSpdyContentLength, int maxHttpContentLength) {
|
||||
super(maxSpdyContentLength, maxHttpContentLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SelectedProtocol getProtocol(SSLEngine engine) {
|
||||
SpdyServerProvider provider = (SpdyServerProvider) NextProtoNego.get(engine);
|
||||
String selectedProtocol = provider.getSelectedProtocol();
|
||||
|
||||
System.out.println("Selected Protocol is " + (selectedProtocol == null ? "Unknown" : selectedProtocol));
|
||||
|
||||
if (selectedProtocol == null) {
|
||||
return SpdyOrHttpChooser.SelectedProtocol.UNKNOWN;
|
||||
} else if (selectedProtocol.equalsIgnoreCase("spdy/3.1")) {
|
||||
return SpdyOrHttpChooser.SelectedProtocol.SPDY_3_1;
|
||||
} else if (selectedProtocol.equalsIgnoreCase("spdy/3")) {
|
||||
return SpdyOrHttpChooser.SelectedProtocol.SPDY_3;
|
||||
} else if (selectedProtocol.equalsIgnoreCase("http/1.1")) {
|
||||
return SpdyOrHttpChooser.SelectedProtocol.HTTP_1_1;
|
||||
} else if (selectedProtocol.equalsIgnoreCase("http/1.0")) {
|
||||
return SpdyOrHttpChooser.SelectedProtocol.HTTP_1_0;
|
||||
} else {
|
||||
return SpdyOrHttpChooser.SelectedProtocol.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChannelInboundHandler createHttpRequestHandlerForHttp() {
|
||||
return new SpdyServerHandler();
|
||||
}
|
||||
|
||||
}
|
77
example/src/main/java/io/netty/example/spdy/SpdyServer.java
Normal file
77
example/src/main/java/io/netty/example/spdy/SpdyServer.java
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.example.spdy;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
|
||||
/**
|
||||
* A SPDY Server that responds to a GET request with a Hello World.
|
||||
* <p>
|
||||
* This class must be run with the JVM parameter: {@code java -Xbootclasspath/p:<path_to_npn_boot_jar> ...}.
|
||||
* The "path_to_npn_boot_jar" is the path on the file system for the NPN Boot Jar file which can be downloaded from
|
||||
* Maven at coordinates org.mortbay.jetty.npn:npn-boot. Different versions applies to different OpenJDK versions.
|
||||
* See {@link http://www.eclipse.org/jetty/documentation/current/npn-chapter.html Jetty docs} for more information.
|
||||
* <p>
|
||||
* Once started, you can test the server with your
|
||||
* {@link http://en.wikipedia.org/wiki/SPDY#Browser_support_and_usage SPDY enabled web browser} by navigating
|
||||
* to https://localhost:8443/.
|
||||
*/
|
||||
public class SpdyServer {
|
||||
|
||||
private final int port;
|
||||
|
||||
public SpdyServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
// Configure the server.
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup();
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
b.option(ChannelOption.SO_BACKLOG, 1024);
|
||||
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
|
||||
.childHandler(new SpdyServerInitializer());
|
||||
|
||||
Channel ch = b.bind(port).sync().channel();
|
||||
ch.closeFuture().sync();
|
||||
} finally {
|
||||
bossGroup.shutdownGracefully();
|
||||
workerGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8443;
|
||||
}
|
||||
|
||||
System.out.println("SPDY web server started at port " + port + '.');
|
||||
System.out.println("Open your SPDY enabled browser and navigate to https://localhost:" + port + '/');
|
||||
System.out.println("If using Chrome browser, check your SPDY sessions at chrome://net-internals/#spdy");
|
||||
|
||||
new SpdyServer(port).run();
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.example.spdy;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpResponse;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpHeaders.Names.*;
|
||||
import static io.netty.handler.codec.http.HttpHeaders.*;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
||||
import static io.netty.handler.codec.http.HttpVersion.*;
|
||||
|
||||
/**
|
||||
* HTTP handler that responds with a "Hello World"
|
||||
*/
|
||||
public class SpdyServerHandler extends SimpleChannelInboundHandler<Object> {
|
||||
@Override
|
||||
public void channelReadComplete(ChannelHandlerContext ctx) {
|
||||
ctx.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
if (msg instanceof HttpRequest) {
|
||||
HttpRequest req = (HttpRequest) msg;
|
||||
|
||||
if (is100ContinueExpected(req)) {
|
||||
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
|
||||
}
|
||||
boolean keepAlive = isKeepAlive(req);
|
||||
|
||||
ByteBuf content = Unpooled.copiedBuffer("Hello World " + (new Date()).toString(), CharsetUtil.UTF_8);
|
||||
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, content);
|
||||
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
|
||||
response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
|
||||
|
||||
if (!keepAlive) {
|
||||
ctx.write(response).addListener(ChannelFutureListener.CLOSE);
|
||||
} else {
|
||||
response.headers().set(CONNECTION, Values.KEEP_ALIVE);
|
||||
ctx.write(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.example.spdy;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.eclipse.jetty.npn.NextProtoNego;
|
||||
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.example.securechat.SecureChatSslContextFactory;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
|
||||
/**
|
||||
* Sets up the Netty pipeline
|
||||
*/
|
||||
public class SpdyServerInitializer extends ChannelInitializer<SocketChannel> {
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
|
||||
SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
|
||||
engine.setUseClientMode(false);
|
||||
p.addLast("ssl", new SslHandler(engine));
|
||||
|
||||
// Setup NextProtoNego with our server provider
|
||||
NextProtoNego.put(engine, new SpdyServerProvider());
|
||||
NextProtoNego.debug = true;
|
||||
|
||||
// Negotiates with the browser if SPDY or HTTP is going to be used
|
||||
p.addLast("handler", new SpdyOrHttpHandler());
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.example.spdy;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.npn.NextProtoNego.ServerProvider;
|
||||
|
||||
/**
|
||||
* The Jetty project provides an implementation of the Transport Layer Security (TLS) extension for Next
|
||||
* Protocol Negotiation (NPN) for OpenJDK 7 or greater. NPN allows the application layer to negotiate which
|
||||
* protocol to use over the secure connection.
|
||||
* <p>
|
||||
* This NPN service provider negotiates using SPDY.
|
||||
* <p>
|
||||
* To enable NPN support, start the JVM with: {@code java -Xbootclasspath/p:<path_to_npn_boot_jar> ...}. The
|
||||
* "path_to_npn_boot_jar" is the path on the file system for the NPN Boot Jar file which can be downloaded from
|
||||
* Maven at coordinates org.mortbay.jetty.npn:npn-boot. Different versions applies to different OpenJDK versions.
|
||||
*
|
||||
* @see http://www.eclipse.org/jetty/documentation/current/npn-chapter.html
|
||||
*/
|
||||
public class SpdyServerProvider implements ServerProvider {
|
||||
|
||||
private String selectedProtocol;
|
||||
|
||||
@Override
|
||||
public void unsupported() {
|
||||
// if unsupported, default to http/1.1
|
||||
selectedProtocol = "http/1.1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> protocols() {
|
||||
return Arrays.asList("spdy/3.1", "spdy/3", "http/1.1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void protocolSelected(String protocol) {
|
||||
selectedProtocol = protocol;
|
||||
}
|
||||
|
||||
public String getSelectedProtocol() {
|
||||
return selectedProtocol;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains an example SPDY HTTP web server.
|
||||
* <p>
|
||||
* This package relies on the Jetty project's implementation of the Transport Layer Security (TLS) extension for Next
|
||||
* Protocol Negotiation (NPN) for OpenJDK 7 is required. NPN allows the application layer to negotiate which
|
||||
* protocol, SPDY or HTTP, to use.
|
||||
* <p>
|
||||
* To start, run {@link SpdyServer} with the JVM parameter: {@code java -Xbootclasspath/p:<path_to_npn_boot_jar> ...}.
|
||||
* The "path_to_npn_boot_jar" is the path on the file system for the NPN Boot Jar file which can be downloaded from
|
||||
* Maven at coordinates org.mortbay.jetty.npn:npn-boot. Different versions applies to different OpenJDK versions.
|
||||
* See {@link http://www.eclipse.org/jetty/documentation/current/npn-chapter.html Jetty docs} for more information.
|
||||
* <p>
|
||||
* Once started, you can test the server with your
|
||||
* {@link http://en.wikipedia.org/wiki/SPDY#Browser_support_and_usage SPDY enabled web browser} by navigating
|
||||
* to https://localhost:8443/.
|
||||
*/
|
||||
package io.netty.example.spdy;
|
7
pom.xml
7
pom.xml
@ -142,6 +142,13 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- SPDY Example - completely optional -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.npn</groupId>
|
||||
<artifactId>npn-api</artifactId>
|
||||
<version>1.1.0.v20120525</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
|
Loading…
Reference in New Issue
Block a user