Skip to content

Commit

Permalink
feat: report collection urls with trailing slash to clients who don't…
Browse files Browse the repository at this point in the history
… give them, as per spec
  • Loading branch information
hperrin committed Aug 11, 2022
1 parent 77544de commit 7528d4c
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 1 deletion.
6 changes: 6 additions & 0 deletions packages/nephele/src/Methods/COPY.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ export class COPY extends Method {
response.locals.baseUrl
);

if ((await resource.isCollection()) && !url.toString().endsWith('/')) {
response.set({
'Content-Location': `${url}/`,
});
}

if (!destination) {
throw new BadRequestError('Destination header is required.');
}
Expand Down
7 changes: 7 additions & 0 deletions packages/nephele/src/Methods/GET_HEAD.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ export class GET_HEAD extends Method {
url,
response.locals.baseUrl
);

if ((await resource.isCollection()) && !url.toString().endsWith('/')) {
response.set({
'Content-Location': `${url}/`,
});
}

const properties = await resource.getProperties();
const etagPromise = resource.getEtag();
const lastModifiedPromise = properties.get('getlastmodified');
Expand Down
6 changes: 6 additions & 0 deletions packages/nephele/src/Methods/LOCK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ export class LOCK extends Method {
}
}

if ((await resource.isCollection()) && !url.toString().endsWith('/')) {
response.set({
'Content-Location': `${url}/`,
});
}

const timeoutRequests = timeoutHeader.split(/,\s+/);
let timeout = Infinity;
for (let curTreq of timeoutRequests) {
Expand Down
16 changes: 15 additions & 1 deletion packages/nephele/src/Methods/MKCOL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ForbiddenError,
LockedError,
MediaTypeNotSupportedError,
ResourceExistsError,
ResourceNotFoundError,
ResourceTreeNotCompleteError,
} from '../Errors/index.js';
Expand All @@ -22,6 +23,12 @@ export class MKCOL extends Method {
response.locals.baseUrl
);

if (!url.toString().endsWith('/')) {
response.set({
'Content-Location': `${url}/`,
});
}

try {
const parent = await this.getParentResource(request, response, resource);
if (!(await parent?.isCollection())) {
Expand Down Expand Up @@ -80,7 +87,14 @@ export class MKCOL extends Method {
Date: new Date().toUTCString(),
});

await resource.create(response.locals.user);
try {
await resource.create(response.locals.user);
} catch (e: any) {
if (e instanceof ResourceExistsError) {
response.removeHeader('Content-Location');
}
throw e;
}

response.status(201); // Created
response.set({
Expand Down
6 changes: 6 additions & 0 deletions packages/nephele/src/Methods/MOVE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ export class MOVE extends Method {
response.locals.baseUrl
);

if ((await resource.isCollection()) && !url.toString().endsWith('/')) {
response.set({
'Content-Location': `${url}/`,
});
}

if (!destination) {
throw new BadRequestError('Destination header is required.');
}
Expand Down
6 changes: 6 additions & 0 deletions packages/nephele/src/Methods/PROPFIND.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ export class PROPFIND extends Method {
response.locals.baseUrl
);

if ((await resource.isCollection()) && !url.toString().endsWith('/')) {
response.set({
'Content-Location': `${url}/`,
});
}

if (!['0', '1', 'infinity'].includes(depth)) {
throw new BadRequestError(
'Depth header must be one of "0", "1", or "infinity".'
Expand Down
7 changes: 7 additions & 0 deletions packages/nephele/src/Methods/PROPPATCH.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ export class PROPPATCH extends Method {
url,
response.locals.baseUrl
);

if ((await resource.isCollection()) && !url.toString().endsWith('/')) {
response.set({
'Content-Location': `${url}/`,
});
}

const props = await resource.getProperties();

const xmlBody = await this.getBodyXML(request, response);
Expand Down
6 changes: 6 additions & 0 deletions packages/nephele/src/Methods/PUT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ export class PUT extends Method {
}
}

if ((await resource.isCollection()) && !url.toString().endsWith('/')) {
response.set({
'Content-Location': `${url}/`,
});
}

try {
const parent = await this.getParentResource(request, response, resource);
if (!(await parent?.isCollection())) {
Expand Down
6 changes: 6 additions & 0 deletions packages/nephele/src/Methods/UNLOCK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ export class UNLOCK extends Method {
response.locals.baseUrl
);

if ((await resource.isCollection()) && !url.toString().endsWith('/')) {
response.set({
'Content-Location': `${url}/`,
});
}

if (lockTokenHeader == null || lockTokenHeader.trim() === '') {
throw new BadRequestError(
'UNLOCK method must include a lock token in the Lock-Token header.'
Expand Down

0 comments on commit 7528d4c

Please sign in to comment.