mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
181 lines
5.6 KiB
TypeScript
181 lines
5.6 KiB
TypeScript
import fetch from 'cross-fetch';
|
|
import { pathExists } from 'fs-extra';
|
|
import type { App } from '../../src/init/App';
|
|
import { getPort } from '../util/Util';
|
|
import {
|
|
getDefaultVariables,
|
|
getTestConfigPath,
|
|
getTestFolder,
|
|
instantiateFromConfig,
|
|
removeFolder,
|
|
} from './Config';
|
|
|
|
const port = getPort('FileBackend');
|
|
const baseUrl = `http://localhost:${port}/`;
|
|
|
|
const rootFilePath = getTestFolder('file-backend');
|
|
|
|
describe('A server with a file backend storage', (): void => {
|
|
let app: App;
|
|
|
|
beforeAll(async(): Promise<void> => {
|
|
await removeFolder(rootFilePath);
|
|
const variables = {
|
|
...getDefaultVariables(port, baseUrl),
|
|
'urn:solid-server:default:variable:rootFilePath': rootFilePath,
|
|
};
|
|
|
|
// Create and start the server
|
|
const instances = await instantiateFromConfig(
|
|
'urn:solid-server:test:Instances',
|
|
[
|
|
getTestConfigPath('server-file.json'),
|
|
],
|
|
variables,
|
|
) as Record<string, any>;
|
|
({ app } = instances);
|
|
|
|
await app.start();
|
|
});
|
|
|
|
afterAll(async(): Promise<void> => {
|
|
await removeFolder(rootFilePath);
|
|
await app.stop();
|
|
});
|
|
|
|
it('can put a document for which the URI path contains URL-encoded separator characters.', async(): Promise<void> => {
|
|
const url = `${baseUrl}c1/c2/t1%2f`;
|
|
const res = await fetch(url, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'content-type': 'text/plain',
|
|
},
|
|
body: 'abc',
|
|
});
|
|
expect(res.status).toBe(201);
|
|
expect(res.headers.get('location')).toBe(`${baseUrl}c1/c2/t1%2F`);
|
|
|
|
// The resource should not be accessible through ${baseUrl}c1/c2/t1/.
|
|
const check1 = await fetch(`${baseUrl}c1/c2/t1/}`, {
|
|
method: 'GET',
|
|
headers: {
|
|
accept: 'text/plain',
|
|
},
|
|
});
|
|
expect(check1.status).toBe(404);
|
|
|
|
// Check that the created resource is not a container
|
|
const check2 = await fetch(url, {
|
|
method: 'GET',
|
|
headers: {
|
|
accept: 'text/plain',
|
|
},
|
|
});
|
|
const linkHeaderValues = check2.headers.get('link')!.split(',').map((item): string => item.trim());
|
|
expect(linkHeaderValues).not.toContain('<http://www.w3.org/ns/ldp#Container>; rel="type"');
|
|
|
|
// Check that the appropriate file path exists
|
|
const check3 = await pathExists(`${rootFilePath}/c1/c2/t1%2F$.txt`);
|
|
expect(check3).toBe(true);
|
|
});
|
|
|
|
it('can post a document using a slug that contains URL-encoded separator characters.', async(): Promise<void> => {
|
|
const slug = 't1%2Faa';
|
|
const res = await fetch(baseUrl, {
|
|
method: 'POST',
|
|
headers: {
|
|
'content-type': 'text/plain',
|
|
slug,
|
|
},
|
|
body: 'abc',
|
|
});
|
|
expect(res.status).toBe(201);
|
|
expect(res.headers.get('location')).toBe(`${baseUrl}${slug}`);
|
|
|
|
// Check that the appropriate file path exists
|
|
const check = await pathExists(`${rootFilePath}/${slug}$.txt`);
|
|
expect(check).toBe(true);
|
|
});
|
|
|
|
it('prevents accessing a document via a different identifier that results in the same path after URL decoding.',
|
|
async(): Promise<void> => {
|
|
// First put a resource using a path without encoded separator characters: foo/bar
|
|
const url = `${baseUrl}foo/bar`;
|
|
await fetch(url, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'content-type': 'text/plain',
|
|
},
|
|
body: 'abc',
|
|
});
|
|
|
|
// The resource at foo/bar should not be accessible using the url encoded variant of this path: foo%2Fbar
|
|
const check1 = await fetch(`${baseUrl}foo%2Fbar`, {
|
|
method: 'GET',
|
|
headers: {
|
|
accept: 'text/plain',
|
|
},
|
|
});
|
|
// Expect foo%2Fbar to correctly refer to a different document, which does not exist.
|
|
expect(check1.status).toBe(404);
|
|
|
|
// Check that the the appropriate file path for foo/bar exists
|
|
const check2 = await pathExists(`${rootFilePath}/foo/bar$.txt`);
|
|
expect(check2).toBe(true);
|
|
|
|
// Next, put a resource using a path with an encoded separator character: bar%2Ffoo
|
|
await fetch(`${baseUrl}bar%2Ffoo`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'content-type': 'text/plain',
|
|
},
|
|
body: 'abc',
|
|
});
|
|
|
|
// The resource at bar%2Ffoo should not be accessible through bar/foo
|
|
const check3 = await fetch(`${baseUrl}bar/foo`, {
|
|
method: 'GET',
|
|
headers: {
|
|
accept: 'text/plain',
|
|
},
|
|
});
|
|
// Expect bar/foo to correctly refer to a different document, which does not exist.
|
|
expect(check3.status).toBe(404);
|
|
|
|
// Check that the the appropriate file path for bar%foo exists
|
|
const check4 = await pathExists(`${rootFilePath}/bar%2Ffoo$.txt`);
|
|
expect(check4).toBe(true);
|
|
});
|
|
|
|
it('supports content types for which no extension mapping can be found (and falls back to using .unknown).',
|
|
async(): Promise<void> => {
|
|
const url = `${baseUrl}test`;
|
|
const res = await fetch(url, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'content-type': 'unknown/some-type',
|
|
},
|
|
body: 'abc',
|
|
});
|
|
expect(res.status).toBe(201);
|
|
expect(res.headers.get('location')).toBe(`${baseUrl}test`);
|
|
|
|
// Check if the document can be retrieved
|
|
const check1 = await fetch(`${baseUrl}test`, {
|
|
method: 'GET',
|
|
headers: {
|
|
accept: '*/*',
|
|
},
|
|
});
|
|
const body = await check1.text();
|
|
expect(check1.status).toBe(200);
|
|
expect(body).toBe('abc');
|
|
// The content-type should be unknown/some-type.
|
|
expect(check1.headers.get('content-type')).toBe('unknown/some-type');
|
|
|
|
// Check if the expected file was created
|
|
const check2 = await pathExists(`${rootFilePath}/test$.unknown`);
|
|
expect(check2).toBe(true);
|
|
});
|
|
});
|