Skip to content

Commit c322392

Browse files
committed
feat(tls) adds a new plugin for TLS/https support
1 parent 9c6e38c commit c322392

File tree

6 files changed

+97
-3
lines changed

6 files changed

+97
-3
lines changed

example/app.lua

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11
-- setup path to find the project source files of Pegasus
22
package.path = './src/?.lua;./src/?/init.lua;' .. package.path
33

4+
-- For this example to work with the https version, you need LuaSec
5+
-- to be installed, and you need to generate the test certificates from
6+
-- its examples. Copy the 'A' certificates into this example directory
7+
-- to make it work.
8+
-- Then uncomment the TLS plugin section below.
9+
410
local Pegasus = require 'pegasus'
511
local Compress = require 'pegasus.plugins.compress'
612
local Downloads = require 'pegasus.plugins.downloads'
13+
-- local TLS = require 'pegasus.plugins.tls'
714

815
local server = Pegasus:new({
916
port = '9090',
1017
location = '/example/root/',
1118
plugins = {
19+
-- TLS:new { -- the tls specific configuration
20+
-- wrap = {
21+
-- mode = "server",
22+
-- protocol = "any",
23+
-- key = "./example/serverAkey.pem",
24+
-- certificate = "./example/serverA.pem",
25+
-- cafile = "./example/rootA.pem",
26+
-- verify = {"none"},
27+
-- options = {"all", "no_sslv2", "no_sslv3", "no_tlsv1"},
28+
-- },
29+
-- sni = nil,
30+
-- },
31+
1232
Downloads:new {
1333
prefix = "downloads",
1434
stripPrefix = true,
1535
},
36+
1637
Compress:new(),
1738
}
1839
})

rockspecs/pegasus-dev-1.rockspec

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ build = {
3838
['pegasus.response'] = 'src/pegasus/response.lua',
3939
['pegasus.compress'] = 'src/pegasus/compress.lua',
4040
['pegasus.plugins.compress'] = 'src/pegasus/plugins/compress.lua',
41-
['pegasus.plugins.downloads'] = 'src/pegasus/plugins/downloads.lua'
41+
['pegasus.plugins.downloads'] = 'src/pegasus/plugins/downloads.lua',
42+
['pegasus.plugins.tls'] = 'src/pegasus/plugins/tls.lua',
4243
}
4344
}

src/pegasus/handler.lua

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ function Handler:pluginsAlterRequestResponseMetatable()
2929
end
3030
end
3131

32+
function Handler:pluginsNewConnection(client)
33+
for _, plugin in ipairs(self.plugins) do
34+
if plugin.newConnection then
35+
client = plugin:newConnection(client)
36+
if not client then
37+
return false
38+
end
39+
end
40+
end
41+
return client
42+
end
43+
3244
function Handler:pluginsNewRequestResponse(request, response)
3345
for _, plugin in ipairs(self.plugins) do
3446
if plugin.newRequestResponse then
@@ -92,8 +104,12 @@ function Handler:processBodyData(data, stayOpen, response)
92104
end
93105

94106
function Handler:processRequest(port, client, server)
95-
local request = Request:new(port, client, server)
107+
client = self:pluginsNewConnection(client)
108+
if not client then
109+
return false
110+
end
96111

112+
local request = Request:new(port, client, server)
97113
if not request:method() then
98114
client:close()
99115
return

src/pegasus/plugins/downloads.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Downloads.__index = Downloads
1212
-- @tparam options.stripPrefix bool whether to strip the prefix from the file path when looking
1313
-- for the file in the filesystem. Defaults to `false`, unless `options.prefix` is omitted,
1414
-- then it defaults to `true`.
15+
-- @return the new plugin
1516
function Downloads:new(options)
1617
options = options or {}
1718
local plugin = {}

src/pegasus/plugins/tls.lua

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--- A plugin that enables TLS (https).
2+
-- This plugin should not be used with Copas. Since Copas has native TLS support
3+
-- and can handle simultaneous `http` and `https` connections. See the Copas example
4+
-- to learn how to set that up.
5+
local ssl = require("ssl")
6+
7+
8+
local TLS = {}
9+
TLS.__index = TLS
10+
11+
12+
--- Creates a new plugin instance.
13+
-- IMPORTANT: this must be the first plugin to execute before the client-socket is accessed!
14+
-- @tparam sslparams table the data-structure that contains the properties for the luasec functions.
15+
-- The structure is set up to mimic the LuaSec functions for the handshake.
16+
-- @return the new plugin
17+
-- @usage
18+
-- local sslparams = {
19+
-- wrap = table | context, -- parameter to LuaSec 'wrap()'
20+
-- sni = { -- parameters to LuaSec 'sni()'
21+
-- names = string | table -- 1st parameter
22+
-- strict = bool -- 2nd parameter
23+
-- }
24+
-- }
25+
-- local tls_plugin = require("pegasus.plugins.tls"):new(sslparams)
26+
function TLS:new(sslparams)
27+
sslparams = sslparams or {}
28+
assert(sslparams.wrap, "'sslparam.wrap' is a required option")
29+
30+
return setmetatable({
31+
sslparams = sslparams
32+
}, TLS)
33+
end
34+
35+
function TLS:newConnection(client)
36+
local params = self.sslparams
37+
38+
-- wrap the client socket and replace it
39+
client = assert(ssl.wrap(client, params.wrap))
40+
41+
if params.sni then
42+
assert(client:sni(params.sni.names, params.sni.strict))
43+
end
44+
45+
if not client:dohandshake() then
46+
print"handshake failed"
47+
return false
48+
end
49+
print"running TLS"
50+
51+
return client
52+
end
53+
54+
55+
return TLS

src/pegasus/request.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function Request:new(port, client, server)
4141
obj.client = client
4242
obj.server = server
4343
obj.port = port
44-
obj.ip = client:getpeername()
44+
obj.ip = (client.getpeername or function() end)(client) -- luasec doesn't support this method
4545
obj.querystring = {}
4646
obj._firstLine = nil
4747
obj._method = nil

0 commit comments

Comments
 (0)