diff --git a/example/app.lua b/example/app.lua index 10a11c0..ac05909 100644 --- a/example/app.lua +++ b/example/app.lua @@ -3,11 +3,18 @@ package.path = './src/?.lua;./src/?/init.lua;' .. package.path local Pegasus = require 'pegasus' local Compress = require 'pegasus.plugins.compress' +local Downloads = require 'pegasus.plugins.downloads' local server = Pegasus:new({ - port='9090', - location='/example/root/', - plugins = { Compress:new() } + port = '9090', + location = '/example/root/', + plugins = { + Downloads:new { + prefix = "downloads", + stripPrefix = true, + }, + Compress:new(), + } }) server:start(function(req) diff --git a/example/copas.lua b/example/copas.lua index 6af5cbf..f468fc4 100644 --- a/example/copas.lua +++ b/example/copas.lua @@ -11,6 +11,7 @@ package.path = "./src/?.lua;./src/?/init.lua;"..package.path local Handler = require 'pegasus.handler' local copas = require('copas') local socket = require('socket') +local Downloads = require 'pegasus.plugins.downloads' --- Creates a new server within the Copas scheduler. -- @tparam table opts options table. @@ -81,7 +82,12 @@ assert(newPegasusServer{ }, location = '/example/root/', callback = nil, - plugins = {}, + plugins = { + Downloads:new { + prefix = "downloads", + stripPrefix = true, + }, + }, }) -- Start diff --git a/example/root/index.html b/example/root/index.html index 74297ac..f890903 100644 --- a/example/root/index.html +++ b/example/root/index.html @@ -9,7 +9,9 @@ - + + +

Click the image to download it!

Name: Age: diff --git a/rockspecs/pegasus-dev-1.rockspec b/rockspecs/pegasus-dev-1.rockspec index fde6e65..0c423e0 100644 --- a/rockspecs/pegasus-dev-1.rockspec +++ b/rockspecs/pegasus-dev-1.rockspec @@ -38,5 +38,6 @@ build = { ['pegasus.response'] = 'src/pegasus/response.lua', ['pegasus.compress'] = 'src/pegasus/compress.lua', ['pegasus.plugins.compress'] = 'src/pegasus/plugins/compress.lua', + ['pegasus.plugins.downloads'] = 'src/pegasus/plugins/downloads.lua' } } diff --git a/src/pegasus/plugins/downloads.lua b/src/pegasus/plugins/downloads.lua new file mode 100644 index 0000000..373ba0f --- /dev/null +++ b/src/pegasus/plugins/downloads.lua @@ -0,0 +1,63 @@ +--- A plugin that allows to download files via a browser. +local Downloads = {} +Downloads.__index = Downloads + +--- Creates a new plugin instance. +-- The plugin will only respond to `GET` requests. The files will be served from the +-- same `location` setting as defined in the `Handler`. The `prefix` is a virtual folder +-- that triggers the plugin, but will be removed from the filepath if `stripPrefix` is truthy. +-- If `stripPrefix` is falsy, then it should be a real folder. +-- @tparam options table the options table with the following fields; +-- @tparam[opt="downloads/"] options.prefix string the path prefix that triggers the plugin +-- @tparam options.stripPrefix bool whether to strip the prefix from the file path when looking +-- for the file in the filesystem. Defaults to `false`, unless `options.prefix` is omitted, +-- then it defaults to `true`. +function Downloads:new(options) + options = options or {} + self = {} + + if not options.prefix then + self.prefix = "downloads/" + if options.stripPrefix == nil then + self.stripPrefix = true + else + self.stripPrefix = not not options.stripPrefix + end + else + self.prefix = options.prefix + self.stripPrefix = not not options.stripPrefix + end + + self.prefix = "/" .. self.prefix .. "/" + while self.prefix:find("//") do + self.prefix = self.prefix:gsub("//", "/") + end + + setmetatable(self, Downloads) + + return self +end + +function Downloads:newRequestResponse(request, response) + local stop = false + if request:method() ~= "GET" then + return stop -- we only handle GET requests + end + + local path = request:path() + if path:find(self.prefix, nil, true) ~= 1 then + return stop -- doesn't match our prefix + end + + local location = response._writeHandler.location or "" + local filename = path + if self.stripPrefix then + filename = path:sub(#self.prefix + 1, -1) + end + + stop = not response:sendFile('.' .. location .. filename) + return stop +end + + +return Downloads