v / examples / ssl_server / server_sni.v
70 lines · 61 sloc · 2.45 KB · efc8f7fb3ef7e90a088db64ad2c68dd0698b90d5
Raw
1import io
2import os
3import net.mbedtls
4
5// This example shows a very minimal HTTP server, that supports SNI.
6// Server Name Indication (SNI) is defined in RFC 6066.
7// See https://mbed-tls.readthedocs.io/en/latest/kb/how-to/use-sni/
8
9// Use the following commands, in separate shells, to test that it works,
10// after you start the server:
11// curl -ik --resolve 1x.dk:8443:0.0.0.0 https://1x.dk:8443/abcd
12// curl -ik --resolve example.com:8443:0.0.0.0 https://example.com:8443/xyz
13// Both of them should work, and the server should show that it tried to load
14// certificates, responding to the given domain name in each of the requests.
15
16// callback to return the certificates to use for the connection
17fn get_cert(mut _listener mbedtls.SSLListener, host string) !&mbedtls.SSLCerts {
18 println('reading certificates for ${host} ...')
19
20 // For our example, just always use the same certificates. In a real server,
21 // that should be dependent on the host parameter, and perhaps there should
22 // be some caching, so that they are not read each time for each request from
23 // the filesystem.
24
25 cert := os.read_file('cert/server.crt') or {
26 return error('Failed to read certificate ${host}: ${err}')
27 }
28 key := os.read_file('cert/server.key') or { return error('Failed to read key ${host}: ${err}') }
29 println('read certs for ${host}')
30
31 if mut c := mbedtls.new_sslcerts_in_memory('', cert, key) {
32 return c
33 } else {
34 return error('mbedtls.new_sslcerts_in_memory err: ${err}')
35 }
36}
37
38fn main() {
39 mut server := mbedtls.new_ssl_listener('0.0.0.0:8443', mbedtls.SSLConnectConfig{
40 verify: os.resource_abs_path('cert/ca.crt')
41 cert: os.resource_abs_path('cert/server.crt')
42 cert_key: os.resource_abs_path('cert/server.key')
43 validate: false
44 get_certificate: get_cert // set the SNI callback to enable this feature
45 })!
46 println('Listening on https://0.0.0.0:8443/ ...')
47 for {
48 mut client := server.accept() or {
49 println('accept error: ${err}')
50 continue
51 }
52 mut reader := io.new_buffered_reader(reader: client)
53 for {
54 line := reader.read_line() or { break }
55 if line.len == 0 {
56 break
57 }
58 println(line)
59 }
60 client.write_string('HTTP/1.1 200 OK\r\n') or { continue }
61
62 client.write_string('Content-Type: text/html\r\n') or { continue }
63 client.write_string('Connection: close\r\n') or { continue }
64 client.write_string('\r\n') or { continue }
65
66 client.write_string('Hello\n') or { continue }
67 client.shutdown()!
68 }
69 server.shutdown()!
70}
71