11-- http.server
22
33local lib = require (' http.lib' )
4+ local sslsocket_supported , sslsocket = pcall (require , ' http.sslsocket' )
45
56local fio = require (' fio' )
67local require = require
@@ -1295,6 +1296,54 @@ local function url_for_httpd(httpd, name, args, query)
12951296 end
12961297end
12971298
1299+ local function create_ssl_ctx (host , port , opts )
1300+ local ok , ctx = pcall (sslsocket .ctx , sslsocket .tls_server_method ())
1301+ if ok ~= true then
1302+ error (ctx )
1303+ end
1304+
1305+ local rc = sslsocket .ctx_use_private_key_file (ctx , opts .ssl_key_file ,
1306+ opts .ssl_password , opts .ssl_password_file )
1307+ if rc == false then
1308+ errorf (
1309+ " Can't start server on %s:%s: %s %s" ,
1310+ host , port , ' Private key is invalid or password mismatch' , opts .ssl_key_file
1311+ )
1312+ end
1313+
1314+ rc = sslsocket .ctx_use_certificate_file (ctx , opts .ssl_cert_file )
1315+ if rc == false then
1316+ errorf (
1317+ " Can't start server on %s:%s: %s %s" ,
1318+ host , port , ' Certificate is invalid' , opts .ssl_cert_file
1319+ )
1320+ end
1321+
1322+ if opts .ssl_ca_file ~= nil then
1323+ rc = sslsocket .ctx_load_verify_locations (ctx , opts .ssl_ca_file )
1324+ if rc == false then
1325+ errorf (
1326+ " Can't start server on %s:%s: %s" ,
1327+ host , port , ' CA file is invalid'
1328+ )
1329+ end
1330+
1331+ sslsocket .ctx_set_verify (ctx , 0x01 + 0x02 )
1332+ end
1333+
1334+ if opts .ssl_ciphers ~= nil then
1335+ rc = sslsocket .ctx_set_cipher_list (ctx , opts .ssl_ciphers )
1336+ if rc == false then
1337+ errorf (
1338+ " Can't start server on %s:%s: %s" ,
1339+ host , port , ' Ciphers are invalid'
1340+ )
1341+ end
1342+ end
1343+
1344+ return ctx
1345+ end
1346+
12981347local function httpd_start (self )
12991348 if type (self ) ~= ' table' then
13001349 error (" httpd: usage: httpd:start()" )
@@ -1321,6 +1370,36 @@ local function httpd_start(self)
13211370 return self
13221371end
13231372
1373+ -- validate_ssl_opts validates ssl_opts and returns true if at least ssl_cert_file
1374+ -- and ssl_key_file parameters are not nil.
1375+ local function validate_ssl_opts (opts )
1376+ local is_tls_enabled = false
1377+
1378+ for key , value in pairs (opts ) do
1379+ if value ~= nil then
1380+ is_tls_enabled = true
1381+
1382+ if type (value ) ~= ' string' then
1383+ errorf (" %s option must be a string" , key )
1384+ end
1385+
1386+ if string.find (key , ' file' ) ~= nil and fio .path .exists (value ) ~= true then
1387+ errorf (" file %q not exists" , value )
1388+ end
1389+ end
1390+ end
1391+
1392+ if is_tls_enabled and (opts .ssl_key_file == nil or opts .ssl_cert_file == nil ) then
1393+ error (" ssl_key_file and ssl_cert_file must be set to enable TLS" )
1394+ end
1395+
1396+ if not sslsocket_supported then
1397+ error (" ssl socket is not supported" )
1398+ end
1399+
1400+ return is_tls_enabled
1401+ end
1402+
13241403local exports = {
13251404 _VERSION = require (' http.version' ),
13261405 DETACHED = DETACHED ,
@@ -1341,6 +1420,15 @@ local exports = {
13411420 error (' Option idle_timeout must be a number.' )
13421421 end
13431422
1423+ local is_tls_enabled = validate_ssl_opts ({
1424+ ssl_cert_file = options .ssl_cert_file ,
1425+ ssl_key_file = options .ssl_key_file ,
1426+ ssl_password = options .ssl_password ,
1427+ ssl_password_file = options .ssl_password_file ,
1428+ ssl_ca_file = options .ssl_ca_file ,
1429+ ssl_ciphers = options .ssl_ciphers ,
1430+ })
1431+
13441432 local default = {
13451433 max_header_size = 4096 ,
13461434 header_timeout = 100 ,
@@ -1363,7 +1451,8 @@ local exports = {
13631451 is_run = false ,
13641452 stop = httpd_stop ,
13651453 start = httpd_start ,
1366- options = extend (default , options , true ),
1454+ use_tls = is_tls_enabled ,
1455+ options = extend (default , options , false ),
13671456
13681457 routes = { },
13691458 iroutes = { },
@@ -1399,6 +1488,20 @@ local exports = {
13991488 }
14001489 }
14011490
1491+ if self .use_tls then
1492+ self .tcp_server_f = function (host , port , handler , timeout )
1493+ local ssl_ctx = create_ssl_ctx (host , port , {
1494+ ssl_cert_file = self .options .ssl_cert_file ,
1495+ ssl_key_file = self .options .ssl_key_file ,
1496+ ssl_password = self .options .ssl_password ,
1497+ ssl_password_file = self .options .ssl_password_file ,
1498+ ssl_ca_file = self .options .ssl_ca_file ,
1499+ ssl_ciphers = self .options .ssl_ciphers ,
1500+ })
1501+ return sslsocket .tcp_server (host , port , handler , timeout , ssl_ctx )
1502+ end
1503+ end
1504+
14021505 return self
14031506 end ,
14041507
0 commit comments