Skip to content

Commit

Permalink
Move validateHttpResponse helper to avoid interdependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensworks committed Apr 25, 2024
1 parent b96bb90 commit 07323db
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { MediatorHttp } from '@comunica/bus-http';
import { ActorHttp } from '@comunica/bus-http';
import { validateAndCloseHttpResponse, ActorHttp } from '@comunica/bus-http';
import type { IQuadDestination } from '@comunica/bus-rdf-update-quads';
import { validateHttpResponse } from '@comunica/bus-rdf-update-quads';
import type { IActionContext } from '@comunica/types';
import type * as RDF from '@rdfjs/types';
import type { AsyncIterator } from 'asynciterator';
Expand Down Expand Up @@ -67,7 +66,7 @@ export class QuadDestinationPatchSparqlUpdate implements IQuadDestination {
input: this.url,
});

await validateHttpResponse(this.url, httpResponse);
await validateAndCloseHttpResponse(this.url, httpResponse);
}

public async deleteGraphs(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import type { MediatorHttp } from '@comunica/bus-http';
import { ActorHttp } from '@comunica/bus-http';
import { validateAndCloseHttpResponse, ActorHttp } from '@comunica/bus-http';
import type { MediatorRdfSerialize, MediatorRdfSerializeMediaTypes } from '@comunica/bus-rdf-serialize';
import type { IQuadDestination } from '@comunica/bus-rdf-update-quads';
import { validateHttpResponse } from '@comunica/bus-rdf-update-quads';
import type { IActionContext } from '@comunica/types';
import type * as RDF from '@rdfjs/types';
import type { AsyncIterator } from 'asynciterator';
Expand Down Expand Up @@ -77,7 +76,7 @@ export class QuadDestinationPutLdp implements IQuadDestination {
input: this.url,
});

await validateHttpResponse(this.url, httpResponse);
await validateAndCloseHttpResponse(this.url, httpResponse);
}

public async deleteGraphs(
Expand Down
1 change: 1 addition & 0 deletions packages/bus-http/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './ActorHttp';
export * from './utils';
24 changes: 24 additions & 0 deletions packages/bus-http/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Use require instead of import for default exports, to be compatible with variants of esModuleInterop in tsconfig.
import stringifyStream = require('stream-to-string');
import { ActorHttp } from './ActorHttp';

/**
* Check if the http response is valid, and throw an error if not.
* @param url The original URL that was to be updated.
* @param httpResponse The update response.
*/
export async function validateAndCloseHttpResponse(url: string, httpResponse: Response): Promise<void> {
// Check if update was successful
if (httpResponse.status >= 400) {
// Consume the body, to avoid process to hang
let bodyString = 'empty response';
if (httpResponse.body) {
const responseStream = ActorHttp.toNodeReadable(httpResponse.body);
bodyString = await stringifyStream(responseStream);
}
throw new Error(`Could not update ${url} (HTTP status ${httpResponse.status}):\n${bodyString}`);
}

// Close response body, as we don't need it
await httpResponse.body?.cancel();
}
1 change: 1 addition & 0 deletions packages/bus-http/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"is-stream": "^2.0.1",
"readable-from-web": "^1.0.0",
"readable-stream-node-to-web": "^1.0.1",
"stream-to-string": "^1.2.0",
"web-streams-ponyfill": "^1.4.2"
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { validateHttpResponse } from '../lib/IQuadDestination';
import { validateAndCloseHttpResponse } from '../lib/utils';

const streamifyString = require('streamify-string');

describe('validateHttpResponse', () => {
describe('validateAndCloseHttpResponse', () => {
it('should do nothing with a valid response', async() => {
await validateHttpResponse('URL', <Response> { status: 200 });
await validateAndCloseHttpResponse('URL', <Response> { status: 200 });
});

it('should cancel the body on a valid response', async() => {
const body = <any> { cancel: jest.fn() };
await validateHttpResponse('URL', <Response> { status: 200, body });
await validateAndCloseHttpResponse('URL', <Response> { status: 200, body });
expect(body.cancel).toHaveBeenCalledTimes(1);
});

it('should throw with an invalid response', async() => {
await expect(validateHttpResponse('URL', <Response> { status: 400 })).rejects
await expect(validateAndCloseHttpResponse('URL', <Response> { status: 400 })).rejects
.toThrow('Could not update URL (HTTP status 400):\nempty response');
});

it('should throw with an invalid response with body', async() => {
const body = streamifyString('BODY');
await expect(validateHttpResponse('URL', <Response> { status: 400, body })).rejects
await expect(validateAndCloseHttpResponse('URL', <Response> { status: 400, body })).rejects
.toThrow('Could not update URL (HTTP status 400):\nBODY');
});
});
25 changes: 0 additions & 25 deletions packages/bus-rdf-update-quads/lib/IQuadDestination.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { ActorHttp } from '@comunica/bus-http';
import type * as RDF from '@rdfjs/types';
import type { AsyncIterator } from 'asynciterator';

// Use require instead of import for default exports, to be compatible with variants of esModuleInterop in tsconfig.
import stringifyStream = require('stream-to-string');

/**
* A quad destination.
*/
Expand Down Expand Up @@ -44,24 +40,3 @@ export interface IQuadDestination {
*/
createGraphs: (graphs: RDF.NamedNode[], requireNonExistence: boolean) => Promise<void>;
}

/**
* Check if the http response is valid, and throw an error if not.
* @param url The original URL that was to be updated.
* @param httpResponse The update response.
*/
export async function validateHttpResponse(url: string, httpResponse: Response): Promise<void> {
// Check if update was successful
if (httpResponse.status >= 400) {
// Consume the body, to avoid process to hang
let bodyString = 'empty response';
if (httpResponse.body) {
const responseStream = ActorHttp.toNodeReadable(httpResponse.body);
bodyString = await stringifyStream(responseStream);
}
throw new Error(`Could not update ${url} (HTTP status ${httpResponse.status}):\n${bodyString}`);
}

// Close response body, as we don't need it
await httpResponse.body?.cancel();
}
4 changes: 1 addition & 3 deletions packages/bus-rdf-update-quads/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,10 @@
},
"dependencies": {
"@comunica/actor-context-preprocess-query-source-skolemize": "^3.0.3",
"@comunica/bus-http": "^3.0.3",
"@comunica/context-entries": "^3.0.3",
"@comunica/core": "^3.0.3",
"@comunica/types": "^3.0.3",
"@rdfjs/types": "*",
"asynciterator": "^3.9.0",
"stream-to-string": "^1.2.0"
"asynciterator": "^3.9.0"
}
}

0 comments on commit 07323db

Please sign in to comment.