Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 35 additions & 14 deletions lib/create-app.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ function createApp (argv = {}) {
}

// Options handler
app.options('/*', options)
app.options(/.*/, options)

// Set up API
if (argv.apiApps) {
Expand All @@ -138,20 +138,11 @@ function createApp (argv = {}) {

// https://stackoverflow.com/questions/51741383/nodejs-express-return-405-for-un-supported-method
app.use(function (req, res, next) {
const AllLayers = app._router.stack
const Layers = AllLayers.filter(x => x.name === 'bound dispatch' && x.regexp.test(req.path))
const router = app._router || app.router
const Methods = allowedMethodsForPath(router?.stack || [], req.path)

const Methods = []
Layers.forEach(layer => {
for (const method in layer.route.methods) {
if (layer.route.methods[method] === true) {
Methods.push(method.toUpperCase())
}
}
})

if (Layers.length !== 0 && !Methods.includes(req.method)) {
// res.setHeader('Allow', Methods.join(','))
if (Methods.length !== 0 && !Methods.includes(req.method)) {
res.setHeader('Allow', Methods.join(', '))

if (req.method === 'OPTIONS') {
return res.send(Methods.join(', '))
Expand Down Expand Up @@ -369,4 +360,34 @@ function sessionSettings (secureCookies, host) {
return sessionSettings
}

function allowedMethodsForPath (layers, path, methods = new Set()) {
for (const layer of layers) {
if (layer.route && layerMatchesPath(layer, path)) {
for (const method in layer.route.methods) {
if (layer.route.methods[method] === true) {
methods.add(method.toUpperCase())
if (method === 'get') methods.add('HEAD')
}
}
} else if (layer.handle?.stack && layerMatchesPath(layer, path)) {
allowedMethodsForPath(layer.handle.stack, path, methods)
}
}

return orderMethods([...methods])
}

function layerMatchesPath (layer, path) {
if (typeof layer.match === 'function') {
return layer.match(path)
}

return layer.regexp?.test(path)
}

function orderMethods (methods) {
const methodOrder = ['OPTIONS', 'HEAD', 'GET', 'PATCH', 'POST', 'PUT', 'DELETE']
return methodOrder.filter(method => methods.includes(method))
}

export default createApp
15 changes: 13 additions & 2 deletions lib/create-server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function createServer (argv, app) {
redirectHttpFroms.forEach(redirectHttpFrom => {
debug.settings('will redirect from port ' + redirectHttpFrom + ' to port ' + argv.port)
const redirectingServer = express()
redirectingServer.get('*', function (req, res) {
redirectingServer.get(/.*/, function (req, res) {
const host = req.headers.host.split(':') // ignore port
debug.server(host, '=> https://' + host + portStr + req.url)
res.redirect('https://' + host + portStr + req.url)
Expand All @@ -96,7 +96,7 @@ function createServer (argv, app) {

// Setup Express app
if (ldp.live) {
const solidWs = SolidWs(server, ldpApp)
const solidWs = SolidWs(server, express5WildcardCompat(ldpApp))
ldpApp.locals.ldp.live = solidWs.publish.bind(solidWs)
}

Expand Down Expand Up @@ -125,4 +125,15 @@ function createServer (argv, app) {
return server
}

function express5WildcardCompat (app) {
const wrappedApp = Object.create(app)
for (const method of ['post', 'patch', 'put', 'delete']) {
wrappedApp[method] = function (path, ...handlers) {
const route = path === '/*' ? /.*/ : path
return app[method](route, ...handlers)
}
}
return wrappedApp
}

export default createServer
8 changes: 7 additions & 1 deletion lib/handlers/auth-proxy.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,18 @@ function addAuthProxyHandler (app, sourcePath, target) {

// Activate the proxy
const proxy = createProxyMiddleware(settings)
const route = sourcePathRoute(sourcePath)
for (const action in REQUIRED_PERMISSIONS) {
const permissions = REQUIRED_PERMISSIONS[action]
app[action](`${sourcePath}*`, setOriginalUrl, ...permissions.map(allow), proxy)
app[action](route, setOriginalUrl, ...permissions.map(allow), proxy)
}
}

function sourcePathRoute (sourcePath) {
const escapedPath = sourcePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
return new RegExp(`^${escapedPath}(?:/.*)?$`)
}

// Adds a headers with authentication information
function addAuthHeaders (proxyReq, req) {
const { session = {}, headers = {} } = req
Expand Down
21 changes: 11 additions & 10 deletions lib/ldp-middleware.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import notify from './handlers/notify.mjs'

export default function LdpMiddleware (corsSettings, prep) {
const router = express.Router('/')
const allResources = /.*/

// Add Link headers
router.use(linksHandler)
Expand All @@ -20,18 +21,18 @@ export default function LdpMiddleware (corsSettings, prep) {
router.use(corsSettings)
}

router.copy('/*', allow('Write'), copy)
router.get('/*', index, allow('Read'), addPermissions, get)
router.post('/*', allow('Append'), post)
router.patch('/*', allow('Append'), patch)
router.put('/*', allow('Append'), put)
router.delete('/*', allow('Write'), del)
router.copy(allResources, allow('Write'), copy)
router.get(allResources, index, allow('Read'), addPermissions, get)
router.post(allResources, allow('Append'), post)
router.patch(allResources, allow('Append'), patch)
router.put(allResources, allow('Append'), put)
router.delete(allResources, allow('Write'), del)

if (prep) {
router.post('/*', notify)
router.patch('/*', notify)
router.put('/*', notify)
router.delete('/*', notify)
router.post(allResources, notify)
router.patch(allResources, notify)
router.put(allResources, notify)
router.delete(allResources, notify)
}

return router
Expand Down
Loading