mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
fix: use full encoded topic iri in streaming http receiveFrom url template
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
"@id": "urn:solid-server:default:StreamingHttp2023RequestHandler",
|
||||
"@type": "StreamingHttpRequestHandler",
|
||||
"streamMap": { "@id": "urn:solid-server:default:StreamingHttpMap" },
|
||||
"baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" },
|
||||
"pathPrefix": { "@id": "urn:solid-server:default:variable:streamingHTTPReceiveFromPrefix" },
|
||||
"generator": { "@id": "urn:solid-server:default:BaseNotificationGenerator" },
|
||||
"serializer": { "@id": "urn:solid-server:default:BaseNotificationSerializer" },
|
||||
|
||||
@@ -19,8 +19,8 @@ export class StreamingHttpMetadataWriter extends MetadataWriter {
|
||||
}
|
||||
|
||||
public async handle(input: { response: HttpResponse; metadata: RepresentationMetadata }): Promise<void> {
|
||||
const resourcePath = input.metadata.identifier.value.replace(this.baseUrl, '');
|
||||
const receiveFrom = `${this.baseUrl}${this.pathPrefix}${resourcePath}`;
|
||||
const encodedUrl = encodeURIComponent(input.metadata.identifier.value);
|
||||
const receiveFrom = `${this.baseUrl}${this.pathPrefix}${encodedUrl}`;
|
||||
const link = `<${receiveFrom}>; rel="http://www.w3.org/ns/solid/terms#updatesViaStreamingHttp2023"`;
|
||||
this.logger.debug('Adding updatesViaStreamingHttp2023 to the Link header');
|
||||
addHeader(input.response, 'Link', link);
|
||||
|
||||
@@ -28,6 +28,7 @@ export class StreamingHttpRequestHandler extends OperationHttpHandler {
|
||||
|
||||
public constructor(
|
||||
private readonly streamMap: StreamingHttpMap,
|
||||
private readonly baseUrl: string,
|
||||
private readonly pathPrefix: string,
|
||||
private readonly generator: NotificationGenerator,
|
||||
private readonly serializer: NotificationSerializer,
|
||||
@@ -39,7 +40,7 @@ export class StreamingHttpRequestHandler extends OperationHttpHandler {
|
||||
}
|
||||
|
||||
public async handle({ operation, request }: OperationHttpHandlerInput): Promise<ResponseDescription> {
|
||||
const topic = operation.target.path.replace(this.pathPrefix, '');
|
||||
const topic = decodeURIComponent(operation.target.path.replace(this.baseUrl + this.pathPrefix, ''));
|
||||
|
||||
// Verify if the client is allowed to connect
|
||||
const credentials = await this.credentialsExtractor.handleSafe(request);
|
||||
|
||||
@@ -17,6 +17,7 @@ import namedNode = DataFactory.namedNode;
|
||||
|
||||
const port = getPort('StreamingHTTPChannel2023');
|
||||
const baseUrl = `http://localhost:${port}/`;
|
||||
const pathPrefix = '.notifications/StreamingHTTPChannel2023';
|
||||
|
||||
const rootFilePath = getTestFolder('StreamingHTTPChannel2023');
|
||||
const stores: [string, any][] = [
|
||||
@@ -38,13 +39,16 @@ async function readChunk(reader: ReadableStreamDefaultReader): Promise<Store> {
|
||||
return new Store(parser.parse(notification));
|
||||
}
|
||||
|
||||
function endpoint(topic: string): string {
|
||||
return joinUrl(baseUrl, pathPrefix, encodeURIComponent(topic));
|
||||
}
|
||||
|
||||
describe.each(stores)('A server supporting StreamingHTTPChannel2023 using %s', (name, { configs, teardown }): void => {
|
||||
let app: App;
|
||||
let store: ResourceStore;
|
||||
const webId = 'http://example.com/card/#me';
|
||||
const topic = joinUrl(baseUrl, '/foo');
|
||||
const pathPrefix = '.notifications/StreamingHTTPChannel2023';
|
||||
const receiveFrom = joinUrl(baseUrl, pathPrefix, '/foo');
|
||||
const receiveFrom = endpoint(topic);
|
||||
|
||||
beforeAll(async(): Promise<void> => {
|
||||
const variables = {
|
||||
@@ -246,7 +250,7 @@ describe.each(stores)('A server supporting StreamingHTTPChannel2023 using %s', (
|
||||
|
||||
it('prevents connecting to channels of restricted topics.', async(): Promise<void> => {
|
||||
const restricted = joinUrl(baseUrl, '/restricted');
|
||||
const restrictedReceiveFrom = joinUrl(baseUrl, pathPrefix, '/restricted');
|
||||
const restrictedReceiveFrom = endpoint(restricted);
|
||||
await store.setRepresentation({ path: restricted }, new BasicRepresentation('new', 'text/plain'));
|
||||
|
||||
// Only allow our WebID to read
|
||||
@@ -285,7 +289,7 @@ describe.each(stores)('A server supporting StreamingHTTPChannel2023 using %s', (
|
||||
|
||||
it('emits container notifications if contents get added or removed.', async(): Promise<void> => {
|
||||
const resource = joinUrl(baseUrl, '/resource');
|
||||
const baseReceiveFrom = joinUrl(baseUrl, pathPrefix, '/');
|
||||
const baseReceiveFrom = endpoint(joinUrl(baseUrl, '/'));
|
||||
|
||||
// Connecting to the base URL, which is the parent container
|
||||
const streamingResponse = await fetch(baseReceiveFrom);
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
} from '../../../../../src/server/notifications/StreamingHttpChannel2023/StreamingHttpMetadataWriter';
|
||||
import { RepresentationMetadata } from '../../../../../src/http/representation/RepresentationMetadata';
|
||||
import type { HttpResponse } from '../../../../../src/server/HttpResponse';
|
||||
import type { ResourceIdentifier } from '../../../../../src/http/representation/ResourceIdentifier';
|
||||
|
||||
describe('A StreamingHttpMetadataWriter', (): void => {
|
||||
const baseUrl = 'http://example.org/';
|
||||
@@ -12,9 +13,10 @@ describe('A StreamingHttpMetadataWriter', (): void => {
|
||||
const rel = 'http://www.w3.org/ns/solid/terms#updatesViaStreamingHttp2023';
|
||||
|
||||
it('adds the correct link header.', async(): Promise<void> => {
|
||||
const topic: ResourceIdentifier = { path: 'http://example.com/foo' };
|
||||
const response = createResponse() as HttpResponse;
|
||||
const metadata = new RepresentationMetadata({ path: 'http://example.org/foo/bar/baz' });
|
||||
const metadata = new RepresentationMetadata(topic);
|
||||
await expect(writer.handle({ response, metadata })).resolves.toBeUndefined();
|
||||
expect(response.getHeaders()).toEqual({ link: `<http://example.org/.notifications/StreamingHTTPChannel2023/foo/bar/baz>; rel="${rel}"` });
|
||||
expect(response.getHeaders()).toEqual({ link: `<http://example.org/.notifications/StreamingHTTPChannel2023/${encodeURIComponent(topic.path)}>; rel="${rel}"` });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,6 +31,7 @@ jest.mock('../../../../../src/logging/LogUtil', (): any => {
|
||||
describe('A StreamingHttpRequestHandler', (): void => {
|
||||
const logger: jest.Mocked<Logger> = getLoggerFor('mock') as any;
|
||||
const topic: ResourceIdentifier = { path: 'http://example.com/foo' };
|
||||
const baseUrl = 'http://example.com/';
|
||||
const pathPrefix = '.notifications/StreamingHTTPChannel2023/';
|
||||
const channel: NotificationChannel = {
|
||||
id: 'id',
|
||||
@@ -64,7 +65,7 @@ describe('A StreamingHttpRequestHandler', (): void => {
|
||||
beforeEach(async(): Promise<void> => {
|
||||
operation = {
|
||||
method: 'GET',
|
||||
target: { path: 'http://example.com/.notifications/StreamingHTTPChannel2023/foo' },
|
||||
target: { path: `http://example.com/.notifications/StreamingHTTPChannel2023/${encodeURIComponent(topic.path)}` },
|
||||
body: new BasicRepresentation(),
|
||||
preferences: {},
|
||||
};
|
||||
@@ -95,6 +96,7 @@ describe('A StreamingHttpRequestHandler', (): void => {
|
||||
|
||||
handler = new StreamingHttpRequestHandler(
|
||||
streamMap,
|
||||
baseUrl,
|
||||
pathPrefix,
|
||||
generator,
|
||||
serializer,
|
||||
@@ -151,6 +153,7 @@ describe('A StreamingHttpRequestHandler', (): void => {
|
||||
} as any;
|
||||
handler = new StreamingHttpRequestHandler(
|
||||
streamMap,
|
||||
baseUrl,
|
||||
pathPrefix,
|
||||
generator,
|
||||
serializer,
|
||||
|
||||
Reference in New Issue
Block a user