11package main
22
33import (
4- "crypto/rand"
5- "crypto/rsa"
6- "crypto/tls"
7- "crypto/x509"
8- "crypto/x509/pkix"
9- "encoding/pem"
104 "errors"
115 "flag"
126 "fmt"
137 "io"
14- "math/big"
158 "net/http"
169 "os"
1710 "strings"
18- "time"
1911
2012 "golang.org/x/net/http2"
2113 "golang.org/x/net/http2/h2c"
@@ -25,8 +17,7 @@ import (
2517
2618// serverMain starts a minimal HTTP/2 WebSocket echo server.
2719// - By default it serves h2c (cleartext HTTP/2): ws://
28- // - With -tls it serves TLS+HTTP/2: wss://
29- // - If -cert and -key are not provided, a self-signed certificate is generated.
20+ // - With -tls it serves TLS+HTTP/2: wss:// (requires -cert and -key)
3021func serverMain (prog string , args []string ) error {
3122 fs := flag .NewFlagSet ("server" , flag .ExitOnError )
3223 addr := fs .String ("addr" , ":8080" , "address to listen on (host:port)" )
@@ -43,8 +34,7 @@ Options:
4334 fmt .Fprintf (fs .Output (), `
4435Examples:
4536 GODEBUG=http2xconnect=1 %[1]s server -addr :8080
46- GODEBUG=http2xconnect=1 %[1]s server -tls -addr :8443
47- GODEBUG=http2xconnect=1 %[1]s server -tls -cert cert.pem -key key.pem
37+ GODEBUG=http2xconnect=1 %[1]s server -tls -cert cert.pem -key key.pem -addr :8443
4838` , prog )
4939 }
5040 if err := fs .Parse (args ); err != nil {
@@ -60,7 +50,7 @@ Examples:
6050 ctx := r .Context ()
6151
6252 c , err := websocket .Accept (w , r , & websocket.AcceptOptions {
63- Protocol : websocket .ProtocolHTTP2 ,
53+ HTTPProtocol : websocket .HTTPProtocol2 ,
6454 })
6555 if err != nil {
6656 // Accept already wrote an error response.
@@ -97,24 +87,16 @@ Examples:
9787 }
9888
9989 if * useTLS {
90+ if * certFile == "" || * keyFile == "" {
91+ return errors .New ("-cert and -key are required when using -tls" )
92+ }
93+
10094 // Enable HTTP/2 over TLS.
10195 if err := http2 .ConfigureServer (srv , & http2.Server {}); err != nil {
10296 return err
10397 }
10498
105- selfSigned := ""
106- if * certFile == "" && * keyFile == "" {
107- // No certificate provided, generate an
108- // ephemeral self-signed certificate.
109- cert , err := selfSignedRSA2048 ()
110- if err != nil {
111- return fmt .Errorf ("generate self-signed certificate failed: %w" , err )
112- }
113- srv .TLSConfig .Certificates = []tls.Certificate {cert }
114- selfSigned = " (self-signed)"
115- }
116-
117- fmt .Printf ("listening on wss://%s%s\n " , visibleAddr (* addr ), selfSigned )
99+ fmt .Printf ("listening on wss://%s\n " , visibleAddr (* addr ))
118100 return srv .ListenAndServeTLS (* certFile , * keyFile )
119101 }
120102
@@ -131,42 +113,3 @@ func visibleAddr(addr string) string {
131113 }
132114 return addr
133115}
134-
135- // selfSignedRSA2048 returns an ephemeral self-signed certificate
136- // suitable for TLS servers.
137- //
138- // DO NOT USE IN PRODUCTION.
139- func selfSignedRSA2048 () (tls.Certificate , error ) {
140- priv , err := rsa .GenerateKey (rand .Reader , 2048 )
141- if err != nil {
142- return tls.Certificate {}, fmt .Errorf ("generate private key failed: %w" , err )
143- }
144-
145- serial , err := rand .Int (rand .Reader , new (big.Int ).Lsh (big .NewInt (1 ), 128 ))
146- if err != nil {
147- return tls.Certificate {}, fmt .Errorf ("generate serial number failed: %w" , err )
148- }
149-
150- tpl := x509.Certificate {
151- SerialNumber : serial ,
152- Subject : pkix.Name {
153- CommonName : "websocket-example" ,
154- Organization : []string {"websocket-example" },
155- },
156- DNSNames : []string {"localhost" },
157- NotBefore : time .Now ().Add (- time .Hour ),
158- NotAfter : time .Now ().Add (365 * 24 * time .Hour ),
159- KeyUsage : x509 .KeyUsageDigitalSignature | x509 .KeyUsageKeyEncipherment ,
160- ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageServerAuth },
161- BasicConstraintsValid : true ,
162- }
163-
164- der , err := x509 .CreateCertificate (rand .Reader , & tpl , & tpl , & priv .PublicKey , priv )
165- if err != nil {
166- return tls.Certificate {}, fmt .Errorf ("create certificate failed: %w" , err )
167- }
168-
169- certPEM := pem .EncodeToMemory (& pem.Block {Type : "CERTIFICATE" , Bytes : der })
170- keyPEM := pem .EncodeToMemory (& pem.Block {Type : "RSA PRIVATE KEY" , Bytes : x509 .MarshalPKCS1PrivateKey (priv )})
171- return tls .X509KeyPair (certPEM , keyPEM )
172- }
0 commit comments