v/examples/ssl_server/server_sni.v

71 lines
2.4 KiB
V

import io
import os
import net.mbedtls
// This example shows a very minimal HTTP server, that supports SNI.
// Server Name Indication (SNI) is defined in RFC 6066.
// See https://mbed-tls.readthedocs.io/en/latest/kb/how-to/use-sni/
// Use the following commands, in separate shells, to test that it works,
// after you start the server:
// curl -ik --resolve 1x.dk:8443:0.0.0.0 https://1x.dk:8443/abcd
// curl -ik --resolve example.com:8443:0.0.0.0 https://example.com:8443/xyz
// Both of them should work, and the server should show that it tried to load
// certificates, responding to the given domain name in each of the requests.
// callback to return the certificates to use for the connection
fn get_cert(mut l mbedtls.SSLListener, host string) !&mbedtls.SSLCerts {
println('reading certificates for ${host} ...')
// For our example, just always use the same certificates. In a real server,
// that should be dependent on the host parameter, and perhaps there should
// be some caching, so that they are not read each time for each request from
// the filesystem.
cert := os.read_file('cert/server.crt') or {
return error('Failed to read certificate ${host}: ${err}')
}
key := os.read_file('cert/server.key') or { return error('Failed to read key ${host}: ${err}') }
println('read certs for ${host}')
if mut c := mbedtls.new_sslcerts_in_memory('', cert, key) {
return c
} else {
return error('mbedtls.new_sslcerts_in_memory err: ${err}')
}
}
fn main() {
mut server := mbedtls.new_ssl_listener('0.0.0.0:8443', mbedtls.SSLConnectConfig{
verify: os.resource_abs_path('cert/ca.crt')
cert: os.resource_abs_path('cert/server.crt')
cert_key: os.resource_abs_path('cert/server.key')
validate: false
get_certificate: get_cert // set the SNI callback to enable this feature
})!
println('Listening on https://0.0.0.0:8443/ ...')
for {
mut client := server.accept() or {
println('accept error: ${err}')
continue
}
mut reader := io.new_buffered_reader(reader: client)
for {
line := reader.read_line() or { break }
if line.len == 0 {
break
}
println(line)
}
client.write_string('HTTP/1.1 200 OK\r\n') or { continue }
client.write_string('Content-Type: text/html\r\n') or { continue }
client.write_string('Connection: close\r\n') or { continue }
client.write_string('\r\n') or { continue }
client.write_string('Hello\n') or { continue }
client.shutdown()!
}
server.shutdown()!
}