--- title: Reactor NettyでHTTP/3対応サーバーを作る tags: ["Reactor", "HTTP/3", "Java"] categories: ["Programming", "Java", "reactor", "netty", "http"] date: 2024-05-16T04:16:07Z updated: 2024-05-16T04:20:45Z --- [Reactor Netty 1.2.0-M2](https://github.com/reactor/reactor-netty/releases/tag/v1.2.0-M2) でHTTP/3が対応されたので"Hello World!"を試してみます。 `pom.xml`に以下の依存ライブラリを追加します。 ```xml io.projectreactor.netty reactor-netty-http io.netty.incubator netty-incubator-codec-http3 0.0.28.Final io.projectreactor reactor-bom 2024.0.0-M2 pom import ``` [ドキュメント](https://projectreactor.io/docs/netty/milestone/reference/http-server.html#HTTP3)に従って次のようなコードを記述します。 ```java package com.example; import io.netty.handler.ssl.util.SelfSignedCertificate; import reactor.core.publisher.Mono; import reactor.netty.DisposableServer; import reactor.netty.http.Http3SslContextSpec; import reactor.netty.http.HttpProtocol; import reactor.netty.http.server.HttpServer; import java.time.Duration; public class Application { public static void main(String[] args) throws Exception { SelfSignedCertificate cert = new SelfSignedCertificate(); Http3SslContextSpec serverCtx = Http3SslContextSpec.forServer(cert.privateKey(), null, cert.certificate()); DisposableServer server = HttpServer.create() .port(8443) .protocol(HttpProtocol.HTTP3) .secure(spec -> spec.sslContext(serverCtx)) .idleTimeout(Duration.ofSeconds(5)) .http3Settings(spec -> spec.maxData(10000000) .maxStreamDataBidirectionalLocal(1000000) .maxStreamDataBidirectionalRemote(1000000) .maxStreamsBidirectional(100)) .handle((request, response) -> response.header("server", "reactor-netty") .sendString(Mono.just("Hello HTTP/3!"))) .bindNow(); server.onDispose().block(); } } ``` HTTP/3はTLSの設定が必要です。自己署名証明書を自動生成するため、依存ライブラリとして[`org.bouncycastle:bcpkix-jdk18on`](https://central.sonatype.com/artifact/org.bouncycastle/bcpkix-jdk18on)を追加しています。 次のコマンドでアプリケーションを起動します。 ``` $ ./mvnw -q compile exec:java -Dexec.mainClass=com.example.Application 2024-05-16 12:56:09.034 DEBUG --- [lication.main()] reactor.netty.tcp.TcpResources : [http] resources will use the default LoopResources: DefaultLoopResources {prefix=reactor-http, daemon=true, selectCount=12, workerCount=12} 2024-05-16 12:56:09.035 DEBUG --- [lication.main()] reactor.netty.tcp.TcpResources : [http] resources will use the default ConnectionProvider: reactor.netty.resources.DefaultPooledConnectionProvider@7cca24c4 2024-05-16 12:56:09.036 DEBUG --- [lication.main()] r.netty.resources.DefaultLoopIOUring : Default io_uring support : false 2024-05-16 12:56:09.039 DEBUG --- [lication.main()] r.netty.resources.DefaultLoopEpoll : Default Epoll support : false 2024-05-16 12:56:09.040 DEBUG --- [lication.main()] r.netty.resources.DefaultLoopKQueue : Default KQueue support : false 2024-05-16 12:56:09.096 DEBUG --- [ctor-http-nio-1] r.netty.transport.ServerTransport : [e56a5924, L:/[0:0:0:0:0:0:0:0]:8443] Bound new server ``` HTTP/3に対応した`curl`でアクセスします。 > [!NOTE] > HTTP/3に対応した`curl` をHomebrewでインストールする方法は[こちらの記事](/entries/792)を参照してください。 ``` $ curl -kv --http3 https://localhost:8443 * Host localhost:8443 was resolved. * IPv6: ::1 * IPv4: 127.0.0.1 * Trying [::1]:8443... * Server certificate: * subject: CN=localhost * start date: May 17 03:56:08 2023 GMT * expire date: Dec 31 23:59:59 9999 GMT * issuer: CN=localhost * SSL certificate verify result: self signed certificate (18), continuing anyway. * Connected to localhost (::1) port 8443 * using HTTP/3 * [HTTP/3] [0] OPENED stream for https://localhost:8443/ * [HTTP/3] [0] [:method: GET] * [HTTP/3] [0] [:scheme: https] * [HTTP/3] [0] [:authority: localhost:8443] * [HTTP/3] [0] [:path: /] * [HTTP/3] [0] [user-agent: curl/8.8.0-DEV] * [HTTP/3] [0] [accept: */*] > GET / HTTP/3 > Host: localhost:8443 > User-Agent: curl/8.8.0-DEV > Accept: */* > * Request completely sent off < HTTP/3 200 < server: reactor-netty < content-length: 13 < * Connection #0 to host localhost left intact Hello HTTP/3! ``` `HTTP/3 200`でレスポンスが返りました。 HTTP/3しか対応していないためか、ブラウザでアクセスしてもアクセスはできませんでした。