Skip to content
Merged
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
6 changes: 5 additions & 1 deletion lib/create-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ function createApp (argv = {}) {
rootUrl: argv.serverUri,
rootPath: path.resolve(argv.root || process.cwd()),
includeHost: argv.multiuser,
defaultContentType: argv.defaultContentType
defaultContentType: argv.defaultContentType,
fileSuffixes: [
argv.suffixAcl || '.acl',
argv.suffixMeta || '.meta'
]
})

const configPath = config.initConfigDir(argv)
Expand Down
19 changes: 15 additions & 4 deletions lib/resource-mapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class ResourceMapper {
includeHost = false,
defaultContentType = 'application/octet-stream',
indexFilename = 'index',
overrideTypes = { acl: 'text/turtle', meta: 'text/turtle' }
overrideTypes = { acl: 'text/turtle', meta: 'text/turtle' },
fileSuffixes = ['.acl', '.meta']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unclear variable name. I would name it something like controlExtensions.

}) {
this._rootUrl = this._removeTrailingSlash(rootUrl)
this._rootPath = this._removeTrailingSlash(rootPath)
Expand All @@ -24,6 +25,7 @@ class ResourceMapper {
this._defaultContentType = defaultContentType
this._indexFilename = indexFilename
this._types = { ...types, ...overrideTypes }
this._isControlFile = new RegExp(`(?:${fileSuffixes.map(fs => fs.replace('.', '\\.')).join('|')})$`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fs.replace(/\./g, '\\.') strictly, but good enough 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regex is so difficult =P


// If the host needs to be replaced on every call, pre-split the root URL
if (includeHost) {
Expand Down Expand Up @@ -68,11 +70,9 @@ class ResourceMapper {
// Read all files in the corresponding folder
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outdated comment

const filename = fullPath.substr(fullPath.lastIndexOf('/') + 1)
const folder = fullPath.substr(0, fullPath.length - filename.length)
const files = await this._readdir(folder)

// Find a file with the same name (minus the dollar extension)
let match = !searchIndex ? '' : (files.find(f => this._removeDollarExtension(f) === filename ||
(isIndex && f.startsWith(this._indexFilename + '.'))))
let match = searchIndex ? await this._getMatchingFile(folder, filename, isIndex) : ''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I would move this specific bit to a new function. Is there potential for reuse?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking was to make it more readable by giving it a name. Don't know of any potential reuse, no.

if (match === undefined) {
// Error if no match was found,
// unless the URL ends with a '/',
Expand All @@ -90,6 +90,17 @@ class ResourceMapper {
return { path, contentType: contentType || this._defaultContentType }
}

async _getMatchingFile (folder, filename, isIndex) {
const files = await this._readdir(folder)
const hasSameName = (f) => {
return this._removeDollarExtension(f) === filename
}
const isIndexFile = (f) => {
return isIndex && f.startsWith(this._indexFilename + '.') && !this._isControlFile.test(f)
}
return files.find(f => hasSameName(f) || isIndexFile(f))
}

async getRepresentationUrlForResource (resourceUrl) {
let fullPath = this.getFullPath(resourceUrl)
let isIndex = fullPath.endsWith('/')
Expand Down
26 changes: 26 additions & 0 deletions test/unit/resource-mapper-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,18 @@ describe('ResourceMapper', () => {
contentType: 'application/octet-stream'
})

itMapsUrl(mapper, 'a URL of that has an accompanying acl file, but no actual file',
{
url: 'http://localhost/space/'
},
[
`${rootPath}space/index.acl`
],
{
path: `${rootPath}space/`,
contentType: 'application/octet-stream'
})

itMapsUrl(mapper, 'a URL ending with a slash to an index file for text/html when index.html not is available',
{
url: 'http://localhost/space/',
Expand All @@ -297,6 +309,20 @@ describe('ResourceMapper', () => {
contentType: 'text/html'
})

itMapsUrl(mapper, 'a URL of that has an accompanying meta file, but no actual file',
{
url: 'http://localhost/space/',
contentType: 'text/html',
createIfNotExists: true
},
[
`${rootPath}space/index.meta`
],
{
path: `${rootPath}space/index.html`,
contentType: 'text/html'
})

itMapsUrl(mapper, 'a URL ending with a slash to a folder when index is skipped',
{
url: 'http://localhost/space/',
Expand Down