mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
fix: Join and normalize paths consistently.
This commit is contained in:
parent
ee072b038a
commit
f454b781ff
@ -1,12 +1,11 @@
|
|||||||
/* eslint-disable unicorn/no-process-exit */
|
/* eslint-disable unicorn/no-process-exit */
|
||||||
|
|
||||||
import * as path from 'path';
|
|
||||||
import type { ReadStream, WriteStream } from 'tty';
|
import type { ReadStream, WriteStream } from 'tty';
|
||||||
import type { LoaderProperties } from 'componentsjs';
|
import type { LoaderProperties } from 'componentsjs';
|
||||||
import { Loader } from 'componentsjs';
|
import { Loader } from 'componentsjs';
|
||||||
import yargs from 'yargs';
|
import yargs from 'yargs';
|
||||||
import { getLoggerFor } from '../logging/LogUtil';
|
import { getLoggerFor } from '../logging/LogUtil';
|
||||||
import { ensureTrailingSlash } from '../util/PathUtil';
|
import { joinFilePath, toSystemFilePath, ensureTrailingSlash } from '../util/PathUtil';
|
||||||
import type { Initializer } from './Initializer';
|
import type { Initializer } from './Initializer';
|
||||||
|
|
||||||
export class CliRunner {
|
export class CliRunner {
|
||||||
@ -44,14 +43,14 @@ export class CliRunner {
|
|||||||
|
|
||||||
// Gather settings for instantiating the server
|
// Gather settings for instantiating the server
|
||||||
const loaderProperties: LoaderProperties = {
|
const loaderProperties: LoaderProperties = {
|
||||||
mainModulePath: this.resolvePath(params.mainModulePath),
|
mainModulePath: toSystemFilePath(this.resolveFilePath(params.mainModulePath)),
|
||||||
scanGlobal: params.globalModules,
|
scanGlobal: params.globalModules,
|
||||||
};
|
};
|
||||||
const configFile = this.resolvePath(params.config, 'config/config-default.json');
|
const configFile = this.resolveFilePath(params.config, 'config/config-default.json');
|
||||||
const variables = this.createVariables(params);
|
const variables = this.createVariables(params);
|
||||||
|
|
||||||
// Create and execute the server initializer
|
// Create and execute the server initializer
|
||||||
this.createInitializer(loaderProperties, configFile, variables)
|
this.createInitializer(loaderProperties, toSystemFilePath(configFile), variables)
|
||||||
.then(
|
.then(
|
||||||
async(initializer): Promise<void> => initializer.handleSafe(),
|
async(initializer): Promise<void> => initializer.handleSafe(),
|
||||||
(error: Error): void => {
|
(error: Error): void => {
|
||||||
@ -70,10 +69,10 @@ export class CliRunner {
|
|||||||
* Resolves a path relative to the current working directory,
|
* Resolves a path relative to the current working directory,
|
||||||
* falling back to a path relative to this module.
|
* falling back to a path relative to this module.
|
||||||
*/
|
*/
|
||||||
protected resolvePath(cwdPath?: string | null, modulePath = ''): string {
|
protected resolveFilePath(cwdPath?: string | null, modulePath = ''): string {
|
||||||
return typeof cwdPath === 'string' ?
|
return typeof cwdPath === 'string' ?
|
||||||
path.join(process.cwd(), cwdPath) :
|
joinFilePath(process.cwd(), cwdPath) :
|
||||||
path.join(__dirname, '../../', modulePath);
|
joinFilePath(__dirname, '../../', modulePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,10 +84,11 @@ export class CliRunner {
|
|||||||
params.baseUrl ? ensureTrailingSlash(params.baseUrl) : `http://localhost:${params.port}/`,
|
params.baseUrl ? ensureTrailingSlash(params.baseUrl) : `http://localhost:${params.port}/`,
|
||||||
'urn:solid-server:default:variable:loggingLevel': params.loggingLevel,
|
'urn:solid-server:default:variable:loggingLevel': params.loggingLevel,
|
||||||
'urn:solid-server:default:variable:port': params.port,
|
'urn:solid-server:default:variable:port': params.port,
|
||||||
'urn:solid-server:default:variable:rootFilePath': this.resolvePath(params.rootFilePath),
|
'urn:solid-server:default:variable:rootFilePath':
|
||||||
|
this.resolveFilePath(params.rootFilePath),
|
||||||
'urn:solid-server:default:variable:sparqlEndpoint': params.sparqlEndpoint,
|
'urn:solid-server:default:variable:sparqlEndpoint': params.sparqlEndpoint,
|
||||||
'urn:solid-server:default:variable:podTemplateFolder':
|
'urn:solid-server:default:variable:podTemplateFolder':
|
||||||
params.podTemplateFolder ?? this.resolvePath(null, 'templates'),
|
this.resolveFilePath(params.podTemplateFolder, 'templates'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { promises as fsPromises } from 'fs';
|
import { promises as fsPromises } from 'fs';
|
||||||
import { posix } from 'path';
|
|
||||||
import { Parser } from 'n3';
|
import { Parser } from 'n3';
|
||||||
import { RepresentationMetadata } from '../../ldp/representation/RepresentationMetadata';
|
import { RepresentationMetadata } from '../../ldp/representation/RepresentationMetadata';
|
||||||
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||||
@ -8,14 +7,12 @@ import type {
|
|||||||
FileIdentifierMapperFactory,
|
FileIdentifierMapperFactory,
|
||||||
ResourceLink,
|
ResourceLink,
|
||||||
} from '../../storage/mapping/FileIdentifierMapper';
|
} from '../../storage/mapping/FileIdentifierMapper';
|
||||||
import { isContainerIdentifier } from '../../util/PathUtil';
|
import { joinFilePath, isContainerIdentifier } from '../../util/PathUtil';
|
||||||
import { guardedStreamFrom } from '../../util/StreamUtil';
|
import { guardedStreamFrom } from '../../util/StreamUtil';
|
||||||
import type { Resource, ResourcesGenerator } from './ResourcesGenerator';
|
import type { Resource, ResourcesGenerator } from './ResourcesGenerator';
|
||||||
import type { TemplateEngine } from './TemplateEngine';
|
import type { TemplateEngine } from './TemplateEngine';
|
||||||
import Dict = NodeJS.Dict;
|
import Dict = NodeJS.Dict;
|
||||||
|
|
||||||
const { join: joinPath } = posix;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates resources by making use of a template engine.
|
* Generates resources by making use of a template engine.
|
||||||
* The template folder structure will be kept.
|
* The template folder structure will be kept.
|
||||||
@ -77,7 +74,7 @@ export class TemplatedResourcesGenerator implements ResourcesGenerator {
|
|||||||
private async* generateLinks(folderPath: string, mapper: FileIdentifierMapper): AsyncIterable<ResourceLink> {
|
private async* generateLinks(folderPath: string, mapper: FileIdentifierMapper): AsyncIterable<ResourceLink> {
|
||||||
const files = await fsPromises.readdir(folderPath);
|
const files = await fsPromises.readdir(folderPath);
|
||||||
for (const name of files) {
|
for (const name of files) {
|
||||||
const filePath = joinPath(folderPath, name);
|
const filePath = joinFilePath(folderPath, name);
|
||||||
const stats = await fsPromises.lstat(filePath);
|
const stats = await fsPromises.lstat(filePath);
|
||||||
yield mapper.mapFilePathToUrl(filePath, stats.isDirectory());
|
yield mapper.mapFilePathToUrl(filePath, stats.isDirectory());
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import type { Stats } from 'fs';
|
import type { Stats } from 'fs';
|
||||||
import { createWriteStream, createReadStream, promises as fsPromises } from 'fs';
|
import { createWriteStream, createReadStream, promises as fsPromises } from 'fs';
|
||||||
import { posix } from 'path';
|
|
||||||
import type { Readable } from 'stream';
|
import type { Readable } from 'stream';
|
||||||
import { DataFactory } from 'n3';
|
import { DataFactory } from 'n3';
|
||||||
import type { NamedNode, Quad } from 'rdf-js';
|
import type { NamedNode, Quad } from 'rdf-js';
|
||||||
@ -13,7 +12,7 @@ import { isSystemError } from '../../util/errors/SystemError';
|
|||||||
import { UnsupportedMediaTypeHttpError } from '../../util/errors/UnsupportedMediaTypeHttpError';
|
import { UnsupportedMediaTypeHttpError } from '../../util/errors/UnsupportedMediaTypeHttpError';
|
||||||
import { guardStream } from '../../util/GuardedStream';
|
import { guardStream } from '../../util/GuardedStream';
|
||||||
import type { Guarded } from '../../util/GuardedStream';
|
import type { Guarded } from '../../util/GuardedStream';
|
||||||
import { isContainerIdentifier } from '../../util/PathUtil';
|
import { joinFilePath, isContainerIdentifier } from '../../util/PathUtil';
|
||||||
import { parseQuads, pushQuad, serializeQuads } from '../../util/QuadUtil';
|
import { parseQuads, pushQuad, serializeQuads } from '../../util/QuadUtil';
|
||||||
import { generateContainmentQuads, generateResourceQuads } from '../../util/ResourceUtil';
|
import { generateContainmentQuads, generateResourceQuads } from '../../util/ResourceUtil';
|
||||||
import { toLiteral } from '../../util/TermUtil';
|
import { toLiteral } from '../../util/TermUtil';
|
||||||
@ -21,8 +20,6 @@ import { CONTENT_TYPE, DC, LDP, POSIX, RDF, XSD } from '../../util/Vocabularies'
|
|||||||
import type { FileIdentifierMapper, ResourceLink } from '../mapping/FileIdentifierMapper';
|
import type { FileIdentifierMapper, ResourceLink } from '../mapping/FileIdentifierMapper';
|
||||||
import type { DataAccessor } from './DataAccessor';
|
import type { DataAccessor } from './DataAccessor';
|
||||||
|
|
||||||
const { join: joinPath } = posix;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DataAccessor that uses the file system to store documents as files and containers as folders.
|
* DataAccessor that uses the file system to store documents as files and containers as folders.
|
||||||
*/
|
*/
|
||||||
@ -298,14 +295,14 @@ export class FileDataAccessor implements DataAccessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ignore non-file/directory entries in the folder
|
// Ignore non-file/directory entries in the folder
|
||||||
const childStats = await fsPromises.lstat(joinPath(link.filePath, childName));
|
const childStats = await fsPromises.lstat(joinFilePath(link.filePath, childName));
|
||||||
if (!childStats.isFile() && !childStats.isDirectory()) {
|
if (!childStats.isFile() && !childStats.isDirectory()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the URI corresponding to the child resource
|
// Generate the URI corresponding to the child resource
|
||||||
const childLink = await this.resourceMapper
|
const childLink = await this.resourceMapper
|
||||||
.mapFilePathToUrl(joinPath(link.filePath, childName), childStats.isDirectory());
|
.mapFilePathToUrl(joinFilePath(link.filePath, childName), childStats.isDirectory());
|
||||||
|
|
||||||
// Generate metadata of this specific child
|
// Generate metadata of this specific child
|
||||||
const subject = DataFactory.namedNode(childLink.identifier.path);
|
const subject = DataFactory.namedNode(childLink.identifier.path);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { promises as fsPromises } from 'fs';
|
import { promises as fsPromises } from 'fs';
|
||||||
import { posix } from 'path';
|
|
||||||
import * as mime from 'mime-types';
|
import * as mime from 'mime-types';
|
||||||
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||||
import { getLoggerFor } from '../../logging/LogUtil';
|
import { getLoggerFor } from '../../logging/LogUtil';
|
||||||
@ -9,13 +8,13 @@ import {
|
|||||||
encodeUriPathComponents,
|
encodeUriPathComponents,
|
||||||
ensureTrailingSlash,
|
ensureTrailingSlash,
|
||||||
isContainerIdentifier,
|
isContainerIdentifier,
|
||||||
|
joinFilePath,
|
||||||
|
normalizeFilePath,
|
||||||
trimTrailingSlashes,
|
trimTrailingSlashes,
|
||||||
} from '../../util/PathUtil';
|
} from '../../util/PathUtil';
|
||||||
import type { FileIdentifierMapper, FileIdentifierMapperFactory, ResourceLink } from './FileIdentifierMapper';
|
import type { FileIdentifierMapper, FileIdentifierMapperFactory, ResourceLink } from './FileIdentifierMapper';
|
||||||
import { getAbsolutePath, getRelativePath, validateRelativePath } from './MapperUtil';
|
import { getAbsolutePath, getRelativePath, validateRelativePath } from './MapperUtil';
|
||||||
|
|
||||||
const { join: joinPath, normalize: normalizePath } = posix;
|
|
||||||
|
|
||||||
export interface ResourcePath {
|
export interface ResourcePath {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +49,7 @@ export class ExtensionBasedMapper implements FileIdentifierMapper {
|
|||||||
|
|
||||||
public constructor(base: string, rootFilepath: string, overrideTypes = { acl: TEXT_TURTLE, meta: TEXT_TURTLE }) {
|
public constructor(base: string, rootFilepath: string, overrideTypes = { acl: TEXT_TURTLE, meta: TEXT_TURTLE }) {
|
||||||
this.baseRequestURI = trimTrailingSlashes(base);
|
this.baseRequestURI = trimTrailingSlashes(base);
|
||||||
this.rootFilepath = trimTrailingSlashes(normalizePath(rootFilepath));
|
this.rootFilepath = trimTrailingSlashes(normalizeFilePath(rootFilepath));
|
||||||
this.types = { ...mime.types, ...overrideTypes };
|
this.types = { ...mime.types, ...overrideTypes };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +100,7 @@ export class ExtensionBasedMapper implements FileIdentifierMapper {
|
|||||||
|
|
||||||
// Matching file found
|
// Matching file found
|
||||||
if (fileName) {
|
if (fileName) {
|
||||||
filePath = joinPath(folder, fileName);
|
filePath = joinFilePath(folder, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.info(`The path for ${identifier.path} is ${filePath}`);
|
this.logger.info(`The path for ${identifier.path} is ${filePath}`);
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
import { posix } from 'path';
|
|
||||||
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||||
import { getLoggerFor } from '../../logging/LogUtil';
|
import { getLoggerFor } from '../../logging/LogUtil';
|
||||||
import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpError';
|
import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpError';
|
||||||
import {
|
import {
|
||||||
encodeUriPathComponents,
|
encodeUriPathComponents,
|
||||||
ensureTrailingSlash, isContainerIdentifier,
|
ensureTrailingSlash,
|
||||||
|
isContainerIdentifier,
|
||||||
|
normalizeFilePath,
|
||||||
trimTrailingSlashes,
|
trimTrailingSlashes,
|
||||||
} from '../../util/PathUtil';
|
} from '../../util/PathUtil';
|
||||||
import type { FileIdentifierMapper, ResourceLink } from './FileIdentifierMapper';
|
import type { FileIdentifierMapper, ResourceLink } from './FileIdentifierMapper';
|
||||||
import { getAbsolutePath, getRelativePath, validateRelativePath } from './MapperUtil';
|
import { getAbsolutePath, getRelativePath, validateRelativePath } from './MapperUtil';
|
||||||
|
|
||||||
const { normalize: normalizePath } = posix;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapper that always returns a fixed content type for files.
|
* A mapper that always returns a fixed content type for files.
|
||||||
*/
|
*/
|
||||||
@ -24,7 +23,7 @@ export class FixedContentTypeMapper implements FileIdentifierMapper {
|
|||||||
|
|
||||||
public constructor(base: string, rootFilepath: string, contentType: string) {
|
public constructor(base: string, rootFilepath: string, contentType: string) {
|
||||||
this.baseRequestURI = trimTrailingSlashes(base);
|
this.baseRequestURI = trimTrailingSlashes(base);
|
||||||
this.rootFilepath = trimTrailingSlashes(normalizePath(rootFilepath));
|
this.rootFilepath = trimTrailingSlashes(normalizeFilePath(rootFilepath));
|
||||||
this.contentType = contentType;
|
this.contentType = contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import { posix } from 'path';
|
|
||||||
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||||
import { getLoggerFor } from '../../logging/LogUtil';
|
import { getLoggerFor } from '../../logging/LogUtil';
|
||||||
import { BadRequestHttpError } from '../../util/errors/BadRequestHttpError';
|
import { BadRequestHttpError } from '../../util/errors/BadRequestHttpError';
|
||||||
import { NotFoundHttpError } from '../../util/errors/NotFoundHttpError';
|
import { NotFoundHttpError } from '../../util/errors/NotFoundHttpError';
|
||||||
import { decodeUriPathComponents } from '../../util/PathUtil';
|
import { joinFilePath, decodeUriPathComponents } from '../../util/PathUtil';
|
||||||
|
|
||||||
const { join: joinPath } = posix;
|
|
||||||
|
|
||||||
const logger = getLoggerFor('MapperUtil');
|
const logger = getLoggerFor('MapperUtil');
|
||||||
|
|
||||||
@ -18,7 +15,7 @@ const logger = getLoggerFor('MapperUtil');
|
|||||||
* @returns Absolute path of the file.
|
* @returns Absolute path of the file.
|
||||||
*/
|
*/
|
||||||
export const getAbsolutePath = (rootFilepath: string, path: string, identifier = ''): string =>
|
export const getAbsolutePath = (rootFilepath: string, path: string, identifier = ''): string =>
|
||||||
joinPath(rootFilepath, path, identifier);
|
joinFilePath(rootFilepath, path, identifier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strips the baseRequestURI from the identifier and checks if the stripped base URI matches the store's one.
|
* Strips the baseRequestURI from the identifier and checks if the stripped base URI matches the store's one.
|
||||||
|
@ -1,5 +1,46 @@
|
|||||||
|
import platform, { posix } from 'path';
|
||||||
import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifier';
|
import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifier';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes a potential Windows path into a POSIX path.
|
||||||
|
*
|
||||||
|
* @param path - Path to check (POSIX or Windows).
|
||||||
|
*
|
||||||
|
* @returns The potentially changed path (POSIX).
|
||||||
|
*/
|
||||||
|
const windowsToPosixPath = (path: string): string => path.replace(/\\+/gu, '/');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves relative segments in the path/
|
||||||
|
*
|
||||||
|
* @param path - Path to check (POSIX or Windows).
|
||||||
|
*
|
||||||
|
* @returns The potentially changed path (POSIX).
|
||||||
|
*/
|
||||||
|
export const normalizeFilePath = (path: string): string =>
|
||||||
|
posix.normalize(windowsToPosixPath(path));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the paths to the base path.
|
||||||
|
*
|
||||||
|
* @param basePath - The base path (POSIX or Windows).
|
||||||
|
* @param paths - Subpaths to attach (POSIX).
|
||||||
|
*
|
||||||
|
* @returns The potentially changed path (POSIX).
|
||||||
|
*/
|
||||||
|
export const joinFilePath = (basePath: string, ...paths: string[]): string =>
|
||||||
|
posix.join(windowsToPosixPath(basePath), ...paths);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the path into an OS-dependent path.
|
||||||
|
*
|
||||||
|
* @param path - Path to check (POSIX).
|
||||||
|
*
|
||||||
|
* @returns The potentially changed path (OS-dependent).
|
||||||
|
*/
|
||||||
|
export const toSystemFilePath = (path: string): string =>
|
||||||
|
platform.normalize(path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes sure the input path has exactly 1 slash at the end.
|
* Makes sure the input path has exactly 1 slash at the end.
|
||||||
* Multiple slashes will get merged into one.
|
* Multiple slashes will get merged into one.
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { mkdirSync } from 'fs';
|
import { mkdirSync } from 'fs';
|
||||||
import { join } from 'path';
|
|
||||||
import * as Path from 'path';
|
|
||||||
import { Loader } from 'componentsjs';
|
import { Loader } from 'componentsjs';
|
||||||
import * as rimraf from 'rimraf';
|
import * as rimraf from 'rimraf';
|
||||||
|
import { joinFilePath, toSystemFilePath } from '../../src/util/PathUtil';
|
||||||
|
|
||||||
export const BASE = 'http://test.com';
|
export const BASE = 'http://test.com';
|
||||||
|
|
||||||
@ -12,17 +11,17 @@ export const BASE = 'http://test.com';
|
|||||||
export const instantiateFromConfig = async(componentUrl: string, configFile: string,
|
export const instantiateFromConfig = async(componentUrl: string, configFile: string,
|
||||||
variables?: Record<string, any>): Promise<any> => {
|
variables?: Record<string, any>): Promise<any> => {
|
||||||
// Initialize the Components.js loader
|
// Initialize the Components.js loader
|
||||||
const mainModulePath = Path.join(__dirname, '../../');
|
const mainModulePath = joinFilePath(__dirname, '../../');
|
||||||
const loader = new Loader({ mainModulePath });
|
const loader = new Loader({ mainModulePath });
|
||||||
await loader.registerAvailableModuleResources();
|
await loader.registerAvailableModuleResources();
|
||||||
|
|
||||||
// Instantiate the component from the config
|
// Instantiate the component from the config
|
||||||
const configPath = Path.join(__dirname, 'config', configFile);
|
const configPath = toSystemFilePath(joinFilePath(__dirname, 'config', configFile));
|
||||||
return loader.instantiateFromUrl(componentUrl, configPath, undefined, { variables });
|
return loader.instantiateFromUrl(componentUrl, configPath, undefined, { variables });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTestFolder = (name: string): string =>
|
export const getTestFolder = (name: string): string =>
|
||||||
join(__dirname, '../tmp', name);
|
joinFilePath(__dirname, '../tmp', name);
|
||||||
|
|
||||||
export const createFolder = (folder: string): void => {
|
export const createFolder = (folder: string): void => {
|
||||||
mkdirSync(folder, { recursive: true });
|
mkdirSync(folder, { recursive: true });
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { createReadStream } from 'fs';
|
import { createReadStream } from 'fs';
|
||||||
import { join } from 'path';
|
|
||||||
import type { HttpHandler, Initializer, ResourceStore } from '../../src/';
|
import type { HttpHandler, Initializer, ResourceStore } from '../../src/';
|
||||||
import { RepresentationMetadata } from '../../src/ldp/representation/RepresentationMetadata';
|
import {
|
||||||
import { guardStream } from '../../src/util/GuardedStream';
|
CONTENT_TYPE, LDP,
|
||||||
import { CONTENT_TYPE, LDP } from '../../src/util/Vocabularies';
|
RepresentationMetadata, guardStream, joinFilePath,
|
||||||
|
} from '../../src/';
|
||||||
import { AclHelper, ResourceHelper } from '../util/TestHelpers';
|
import { AclHelper, ResourceHelper } from '../util/TestHelpers';
|
||||||
import { BASE, getTestFolder, createFolder, removeFolder, instantiateFromConfig } from './Config';
|
import { BASE, getTestFolder, createFolder, removeFolder, instantiateFromConfig } from './Config';
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ describe.each(stores)('An LDP handler with auth using %s', (name, { storeUrn, se
|
|||||||
// Write test resource
|
// Write test resource
|
||||||
await store.setRepresentation({ path: `${BASE}/permanent.txt` }, {
|
await store.setRepresentation({ path: `${BASE}/permanent.txt` }, {
|
||||||
binary: true,
|
binary: true,
|
||||||
data: guardStream(createReadStream(join(__dirname, '../assets/permanent.txt'))),
|
data: guardStream(createReadStream(joinFilePath(__dirname, '../assets/permanent.txt'))),
|
||||||
metadata: new RepresentationMetadata({ [CONTENT_TYPE]: 'text/plain' }),
|
metadata: new RepresentationMetadata({ [CONTENT_TYPE]: 'text/plain' }),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { Server } from 'http';
|
import type { Server } from 'http';
|
||||||
import { join } from 'path';
|
|
||||||
import fetch from 'cross-fetch';
|
import fetch from 'cross-fetch';
|
||||||
import type { HttpServerFactory } from '../../src/server/HttpServerFactory';
|
import type { HttpServerFactory } from '../../src/server/HttpServerFactory';
|
||||||
|
import { joinFilePath } from '../../src/util/PathUtil';
|
||||||
import { readableToString } from '../../src/util/StreamUtil';
|
import { readableToString } from '../../src/util/StreamUtil';
|
||||||
import { instantiateFromConfig } from './Config';
|
import { instantiateFromConfig } from './Config';
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ describe('A server with a pod handler', (): void => {
|
|||||||
'urn:solid-server:default:ServerFactory', 'server-without-auth.json', {
|
'urn:solid-server:default:ServerFactory', 'server-without-auth.json', {
|
||||||
'urn:solid-server:default:variable:port': port,
|
'urn:solid-server:default:variable:port': port,
|
||||||
'urn:solid-server:default:variable:baseUrl': baseUrl,
|
'urn:solid-server:default:variable:baseUrl': baseUrl,
|
||||||
'urn:solid-server:default:variable:podTemplateFolder': join(__dirname, '../assets/templates'),
|
'urn:solid-server:default:variable:podTemplateFolder': joinFilePath(__dirname, '../assets/templates'),
|
||||||
},
|
},
|
||||||
) as HttpServerFactory;
|
) as HttpServerFactory;
|
||||||
server = factory.startServer(port);
|
server = factory.startServer(port);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as path from 'path';
|
|
||||||
import { Loader } from 'componentsjs';
|
import { Loader } from 'componentsjs';
|
||||||
import { CliRunner } from '../../../src/init/CliRunner';
|
import { CliRunner } from '../../../src/init/CliRunner';
|
||||||
import type { Initializer } from '../../../src/init/Initializer';
|
import type { Initializer } from '../../../src/init/Initializer';
|
||||||
|
import { joinFilePath, toSystemFilePath } from '../../../src/util/PathUtil';
|
||||||
|
|
||||||
const initializer: jest.Mocked<Initializer> = {
|
const initializer: jest.Mocked<Initializer> = {
|
||||||
handleSafe: jest.fn(),
|
handleSafe: jest.fn(),
|
||||||
@ -34,12 +34,12 @@ describe('CliRunner', (): void => {
|
|||||||
|
|
||||||
expect(Loader).toHaveBeenCalledTimes(1);
|
expect(Loader).toHaveBeenCalledTimes(1);
|
||||||
expect(Loader).toHaveBeenCalledWith({
|
expect(Loader).toHaveBeenCalledWith({
|
||||||
mainModulePath: path.join(__dirname, '../../../'),
|
mainModulePath: toSystemFilePath(joinFilePath(__dirname, '../../../')),
|
||||||
});
|
});
|
||||||
expect(loader.instantiateFromUrl).toHaveBeenCalledTimes(1);
|
expect(loader.instantiateFromUrl).toHaveBeenCalledTimes(1);
|
||||||
expect(loader.instantiateFromUrl).toHaveBeenCalledWith(
|
expect(loader.instantiateFromUrl).toHaveBeenCalledWith(
|
||||||
'urn:solid-server:default:Initializer',
|
'urn:solid-server:default:Initializer',
|
||||||
path.join(__dirname, '/../../../config/config-default.json'),
|
toSystemFilePath(joinFilePath(__dirname, '/../../../config/config-default.json')),
|
||||||
undefined,
|
undefined,
|
||||||
{
|
{
|
||||||
variables: {
|
variables: {
|
||||||
@ -48,7 +48,7 @@ describe('CliRunner', (): void => {
|
|||||||
'urn:solid-server:default:variable:rootFilePath': '/var/cwd/',
|
'urn:solid-server:default:variable:rootFilePath': '/var/cwd/',
|
||||||
'urn:solid-server:default:variable:sparqlEndpoint': undefined,
|
'urn:solid-server:default:variable:sparqlEndpoint': undefined,
|
||||||
'urn:solid-server:default:variable:loggingLevel': 'info',
|
'urn:solid-server:default:variable:loggingLevel': 'info',
|
||||||
'urn:solid-server:default:variable:podTemplateFolder': path.join(__dirname, '../../../templates'),
|
'urn:solid-server:default:variable:podTemplateFolder': joinFilePath(__dirname, '../../../templates'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -77,18 +77,18 @@ describe('CliRunner', (): void => {
|
|||||||
|
|
||||||
expect(Loader).toHaveBeenCalledTimes(1);
|
expect(Loader).toHaveBeenCalledTimes(1);
|
||||||
expect(Loader).toHaveBeenCalledWith({
|
expect(Loader).toHaveBeenCalledWith({
|
||||||
mainModulePath: '/var/cwd/module/path',
|
mainModulePath: toSystemFilePath('/var/cwd/module/path'),
|
||||||
scanGlobal: true,
|
scanGlobal: true,
|
||||||
});
|
});
|
||||||
expect(loader.instantiateFromUrl).toHaveBeenCalledWith(
|
expect(loader.instantiateFromUrl).toHaveBeenCalledWith(
|
||||||
'urn:solid-server:default:Initializer',
|
'urn:solid-server:default:Initializer',
|
||||||
'/var/cwd/myconfig.json',
|
toSystemFilePath('/var/cwd/myconfig.json'),
|
||||||
undefined,
|
undefined,
|
||||||
{
|
{
|
||||||
variables: {
|
variables: {
|
||||||
'urn:solid-server:default:variable:baseUrl': 'http://pod.example/',
|
'urn:solid-server:default:variable:baseUrl': 'http://pod.example/',
|
||||||
'urn:solid-server:default:variable:loggingLevel': 'debug',
|
'urn:solid-server:default:variable:loggingLevel': 'debug',
|
||||||
'urn:solid-server:default:variable:podTemplateFolder': 'templates',
|
'urn:solid-server:default:variable:podTemplateFolder': '/var/cwd/templates',
|
||||||
'urn:solid-server:default:variable:port': 4000,
|
'urn:solid-server:default:variable:port': 4000,
|
||||||
'urn:solid-server:default:variable:rootFilePath': '/var/cwd/root',
|
'urn:solid-server:default:variable:rootFilePath': '/var/cwd/root',
|
||||||
'urn:solid-server:default:variable:sparqlEndpoint': 'http://localhost:5000/sparql',
|
'urn:solid-server:default:variable:sparqlEndpoint': 'http://localhost:5000/sparql',
|
||||||
@ -116,18 +116,18 @@ describe('CliRunner', (): void => {
|
|||||||
|
|
||||||
expect(Loader).toHaveBeenCalledTimes(1);
|
expect(Loader).toHaveBeenCalledTimes(1);
|
||||||
expect(Loader).toHaveBeenCalledWith({
|
expect(Loader).toHaveBeenCalledWith({
|
||||||
mainModulePath: '/var/cwd/module/path',
|
mainModulePath: toSystemFilePath('/var/cwd/module/path'),
|
||||||
scanGlobal: true,
|
scanGlobal: true,
|
||||||
});
|
});
|
||||||
expect(loader.instantiateFromUrl).toHaveBeenCalledWith(
|
expect(loader.instantiateFromUrl).toHaveBeenCalledWith(
|
||||||
'urn:solid-server:default:Initializer',
|
'urn:solid-server:default:Initializer',
|
||||||
'/var/cwd/myconfig.json',
|
toSystemFilePath('/var/cwd/myconfig.json'),
|
||||||
undefined,
|
undefined,
|
||||||
{
|
{
|
||||||
variables: {
|
variables: {
|
||||||
'urn:solid-server:default:variable:baseUrl': 'http://pod.example/',
|
'urn:solid-server:default:variable:baseUrl': 'http://pod.example/',
|
||||||
'urn:solid-server:default:variable:loggingLevel': 'debug',
|
'urn:solid-server:default:variable:loggingLevel': 'debug',
|
||||||
'urn:solid-server:default:variable:podTemplateFolder': 'templates',
|
'urn:solid-server:default:variable:podTemplateFolder': '/var/cwd/templates',
|
||||||
'urn:solid-server:default:variable:port': 4000,
|
'urn:solid-server:default:variable:port': 4000,
|
||||||
'urn:solid-server:default:variable:rootFilePath': '/var/cwd/root',
|
'urn:solid-server:default:variable:rootFilePath': '/var/cwd/root',
|
||||||
'urn:solid-server:default:variable:sparqlEndpoint': 'http://localhost:5000/sparql',
|
'urn:solid-server:default:variable:sparqlEndpoint': 'http://localhost:5000/sparql',
|
||||||
|
@ -1,11 +1,41 @@
|
|||||||
|
import { sep } from 'path';
|
||||||
import {
|
import {
|
||||||
decodeUriPathComponents,
|
decodeUriPathComponents,
|
||||||
encodeUriPathComponents,
|
encodeUriPathComponents,
|
||||||
ensureTrailingSlash,
|
ensureTrailingSlash,
|
||||||
|
joinFilePath,
|
||||||
|
normalizeFilePath,
|
||||||
toCanonicalUriPath,
|
toCanonicalUriPath,
|
||||||
|
toSystemFilePath,
|
||||||
} from '../../../src/util/PathUtil';
|
} from '../../../src/util/PathUtil';
|
||||||
|
|
||||||
describe('PathUtil', (): void => {
|
describe('PathUtil', (): void => {
|
||||||
|
describe('normalizeFilePath', (): void => {
|
||||||
|
it('normalizes POSIX paths.', async(): Promise<void> => {
|
||||||
|
expect(normalizeFilePath('/foo/bar/../baz')).toEqual('/foo/baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('normalizes Windows paths.', async(): Promise<void> => {
|
||||||
|
expect(normalizeFilePath('c:\\foo\\bar\\..\\baz')).toEqual('c:/foo/baz');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('joinFilePath', (): void => {
|
||||||
|
it('joins POSIX paths.', async(): Promise<void> => {
|
||||||
|
expect(joinFilePath('/foo/bar/', '..', '/baz')).toEqual('/foo/baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('joins Windows paths.', async(): Promise<void> => {
|
||||||
|
expect(joinFilePath('c:\\foo\\bar\\', '..', '/baz')).toEqual(`c:/foo/baz`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('toSystemFilePath', (): void => {
|
||||||
|
it('converts a POSIX path to an OS-specific path.', async(): Promise<void> => {
|
||||||
|
expect(toSystemFilePath('c:/foo/bar/')).toEqual(`c:${sep}foo${sep}bar${sep}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('#ensureTrailingSlash', (): void => {
|
describe('#ensureTrailingSlash', (): void => {
|
||||||
it('makes sure there is always exactly 1 slash.', async(): Promise<void> => {
|
it('makes sure there is always exactly 1 slash.', async(): Promise<void> => {
|
||||||
expect(ensureTrailingSlash('http://test.com')).toEqual('http://test.com/');
|
expect(ensureTrailingSlash('http://test.com')).toEqual('http://test.com/');
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import type { IncomingHttpHeaders } from 'http';
|
import type { IncomingHttpHeaders } from 'http';
|
||||||
import { join } from 'path';
|
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import type { MockResponse } from 'node-mocks-http';
|
import type { MockResponse } from 'node-mocks-http';
|
||||||
import { createResponse } from 'node-mocks-http';
|
import { createResponse } from 'node-mocks-http';
|
||||||
import type { ResourceStore, PermissionSet, HttpHandler, HttpRequest } from '../../src/';
|
import type { ResourceStore, PermissionSet, HttpHandler, HttpRequest } from '../../src/';
|
||||||
import { guardedStreamFrom, RepresentationMetadata, ensureTrailingSlash } from '../../src/';
|
import { guardedStreamFrom, RepresentationMetadata, joinFilePath, ensureTrailingSlash } from '../../src/';
|
||||||
import { CONTENT_TYPE } from '../../src/util/Vocabularies';
|
import { CONTENT_TYPE } from '../../src/util/Vocabularies';
|
||||||
import { performRequest } from './Util';
|
import { performRequest } from './Util';
|
||||||
|
|
||||||
@ -109,7 +108,7 @@ export class ResourceHelper {
|
|||||||
public async createResource(fileLocation: string, slug: string, contentType: string, mayFail = false):
|
public async createResource(fileLocation: string, slug: string, contentType: string, mayFail = false):
|
||||||
Promise<MockResponse<any>> {
|
Promise<MockResponse<any>> {
|
||||||
const fileData = await fs.readFile(
|
const fileData = await fs.readFile(
|
||||||
join(__dirname, fileLocation),
|
joinFilePath(__dirname, fileLocation),
|
||||||
);
|
);
|
||||||
|
|
||||||
const response: MockResponse<any> = await this.performRequestWithBody(
|
const response: MockResponse<any> = await this.performRequestWithBody(
|
||||||
@ -131,7 +130,7 @@ export class ResourceHelper {
|
|||||||
public async replaceResource(fileLocation: string, requestUrl: string, contentType: string):
|
public async replaceResource(fileLocation: string, requestUrl: string, contentType: string):
|
||||||
Promise<MockResponse<any>> {
|
Promise<MockResponse<any>> {
|
||||||
const fileData = await fs.readFile(
|
const fileData = await fs.readFile(
|
||||||
join(__dirname, fileLocation),
|
joinFilePath(__dirname, fileLocation),
|
||||||
);
|
);
|
||||||
|
|
||||||
const putUrl = new URL(requestUrl);
|
const putUrl = new URL(requestUrl);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user