Skip to content

Commit e0b3a64

Browse files
author
jaxoncreed
committed
Merge fix/1324 with dev
2 parents a7db6af + 0a958f2 commit e0b3a64

File tree

4 files changed

+54
-8
lines changed

4 files changed

+54
-8
lines changed

lib/ldp.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class LDP {
158158

159159
// HACK: the middleware in webid-oidc.js uses body-parser, thus ending the stream of data
160160
// for JSON bodies. So, the stream needs to be reset
161-
if (contentType.includes('application/json')) {
161+
if (contentType && contentType.includes('application/json')) {
162162
stream = intoStream(JSON.stringify(stream.body))
163163
}
164164

lib/resource-mapper.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class ResourceMapper {
3434
this._defaultContentType = defaultContentType
3535
this._types = { ...types, ...overrideTypes }
3636
this._indexFilename = indexFilename
37-
this._indexContentType = this._getContentTypeByExtension(indexFilename)
37+
this._indexContentType = this._getContentTypeFromExtension(indexFilename)
3838

3939
// If the host needs to be replaced on every call, pre-split the root URL
4040
if (includeHost) {
@@ -82,7 +82,7 @@ class ResourceMapper {
8282
const url = `${this.resolveUrl(hostname)}${
8383
pathname.split(pathUtil.sep).map((component) => encodeURIComponent(component)).join('/')
8484
}`
85-
return { url, contentType: this._getContentTypeByExtension(path) }
85+
return { url, contentType: this._getContentTypeFromExtension(path) }
8686
}
8787

8888
// Maps the request for a given resource and representation format to a server file
@@ -97,7 +97,7 @@ class ResourceMapper {
9797
let isFolder = filePath.endsWith('/')
9898
let isIndex = searchIndex && filePath.endsWith('/')
9999

100-
// Create the path for a new ressource
100+
// Create the path for a new resource
101101
let path
102102
if (createIfNotExists) {
103103
path = filePath
@@ -109,8 +109,8 @@ class ResourceMapper {
109109
path += this._indexFilename
110110
}
111111
// If the extension is not correct for the content type, append the correct extension
112-
if (!isFolder && this._getContentTypeByExtension(path) !== contentType) {
113-
path += `$${contentType in extensions ? `.${extensions[contentType][0]}` : '.unknown'}`
112+
if (!isFolder) {
113+
path = this._addContentTypeExtension(path, contentType)
114114
}
115115
// Determine the path of an existing file
116116
} else {
@@ -139,7 +139,7 @@ class ResourceMapper {
139139
}
140140
}
141141
path = `${folder}${match}`
142-
contentType = this._getContentTypeByExtension(match)
142+
contentType = this._getContentTypeFromExtension(match)
143143
}
144144
return { path, contentType: contentType || this._defaultContentType }
145145
}
@@ -160,11 +160,25 @@ class ResourceMapper {
160160
}
161161

162162
// Gets the expected content type based on the extension of the path
163-
_getContentTypeByExtension (path) {
163+
_getContentTypeFromExtension (path) {
164164
const extension = /\.([^/.]+)$/.exec(path)
165165
return extension && this._types[extension[1].toLowerCase()] || this._defaultContentType
166166
}
167167

168+
// Appends an extension for the specific content type, if needed
169+
_addContentTypeExtension (path, contentType) {
170+
// If we would guess the wrong content type from the extension, try appending a better one
171+
const contentTypeFromExtension = this._getContentTypeFromExtension(path)
172+
if (contentTypeFromExtension !== contentType) {
173+
// Some extensions fit multiple content types, so only switch if there's an improvement
174+
const newExtension = contentType in extensions ? extensions[contentType][0] : 'unknown'
175+
if (this._types[newExtension] !== contentTypeFromExtension) {
176+
path += `$.${newExtension}`
177+
}
178+
}
179+
return path
180+
}
181+
168182
// Removes possible trailing slashes from a path
169183
_removeTrailingSlash (path) {
170184
return path.replace(/\/+$/, '')

test/integration/http-test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,27 @@ describe('HTTP APIs', function () {
559559
.expect(hasHeader('acl', suffixAcl))
560560
.expect(201, done)
561561
})
562+
it('should create new resource even if body is empty', function (done) {
563+
server.post('/post-tests/')
564+
.set('slug', 'post-resource-empty')
565+
.set('content-type', 'text/turtle')
566+
.expect(hasHeader('describedBy', suffixMeta))
567+
.expect(hasHeader('acl', suffixAcl))
568+
.expect('location', /.*\.ttl/)
569+
.expect(201, done)
570+
})
571+
it('should error with 415 if the body is empty and no content type is provided', function (done) {
572+
server.post('/post-tests/')
573+
.set('slug', 'post-resource-empty-fail')
574+
.expect(415, done)
575+
})
576+
it('should error with 415 if the body is provided but there is no content-type header', function (done) {
577+
server.post('/post-tests/')
578+
.set('slug', 'post-resource-rdf-no-content-type')
579+
.send(postRequest1Body)
580+
.set('content-type', '')
581+
.expect(415, done)
582+
})
562583
it('should create new resource even if no trailing / is in the target',
563584
function (done) {
564585
server.post('')

test/unit/resource-mapper-test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ describe('ResourceMapper', () => {
119119
contentType: 'text/n3'
120120
})
121121

122+
itMapsUrl(mapper, 'a URL with a file extension having more than one possible content type',
123+
{
124+
url: 'http://localhost/space/foo.mp3',
125+
contentType: 'audio/mp3',
126+
createIfNotExists: true
127+
},
128+
{
129+
path: `${rootPath}space/foo.mp3`,
130+
contentType: 'audio/mp3'
131+
})
132+
122133
// GET/HEAD/POST/DELETE/PATCH base cases
123134

124135
itMapsUrl(mapper, 'a URL of a non-existing file',

0 commit comments

Comments
 (0)