Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 10x 10x 10x 10x 10x 10x 2x 8x 8x 8x 8x 8x 3x 8x 8x 1x 8x 6x 3x 3x 3x 10x 1x 3x 3x 3x 2x 2x 2x | import * as vscode from 'vscode';
import { ICredentialStorageService } from '@src/services/core';
import { AuthCredential } from '@src/services/core/credential';
import { SparqlConnection } from './sparql-connection';
import { WORKSPACE_CONNECTION } from './workspace-store';
import { getAuthorizationHeader } from './sparql-auth';
import { ISparqlEndpointTester } from './sparql-endpoint-tester.interface';
/**
* Tests the reachability of SPARQL endpoint connections by sending an ASK query
* via HTTP POST. Test progress is surfaced through events; results are returned
* to the caller — surfacing errors to the user is the caller's concern.
*/
export class SparqlEndpointTester implements ISparqlEndpointTester {
private _onDidConnectionTestStart = new vscode.EventEmitter<SparqlConnection>();
/**
* Fired immediately before a connection test begins.
*/
public readonly onDidConnectionTestStart = this._onDidConnectionTestStart.event;
private _onDidConnectionTestEnd = new vscode.EventEmitter<{ connection: SparqlConnection; error: { code: number; message: string } | null }>();
/**
* Fired when a connection test completes. `error` is `null` on success, or
* contains the error code and message on failure.
*/
public readonly onDidConnectionTestEnd = this._onDidConnectionTestEnd.event;
constructor(private readonly _credentialStorage: ICredentialStorageService) { }
/**
* Tests whether a SPARQL endpoint can be reached by sending an ASK query via HTTP POST.
* The workspace store is always considered reachable without testing.
* @param connection The SPARQL endpoint connection to test.
* @param credential If provided, uses these credentials instead of loading stored ones.
* @returns `null` on success, or an error object `{ code, message }` on failure.
*/
async testConnection(connection: SparqlConnection, credential?: AuthCredential | null): Promise<null | { code: number; message: string }> {
if (connection.id === WORKSPACE_CONNECTION.id) {
return null;
}
this._onDidConnectionTestStart.fire(connection);
try {
const headers: Record<string, string> = {
'Content-Type': 'application/sparql-query',
'Accept': 'application/sparql-results+json,application/json'
};
// An explicit credential (or explicit null) comes from the connection
// editor, where the user is entering credentials right now; only a
// stored-credential lookup can come back empty unexpectedly.
const usingStoredCredential = credential === undefined;
if (credential === undefined) {
credential = await this._credentialStorage.getCredential(connection.id);
}
const authHeader = await getAuthorizationHeader(credential ?? undefined);
if (authHeader) {
headers.Authorization = authHeader;
}
const response = await fetch(connection.endpointUrl, {
method: 'POST',
headers,
body: 'ASK WHERE { ?s ?p ?o }'
});
if (response.ok) {
this._onDidConnectionTestEnd.fire({ connection, error: null });
return null;
}
let message = await response.text() || response.statusText;
// Credentials live in the machine-local secret storage and are not
// synced with the settings a connection is stored in. A connection
// arriving from another machine (or another user, via version control)
// therefore fails authentication with no stored credential — explain
// that instead of leaving a bare HTTP error.
if ((response.status === 401 || response.status === 407) && usingStoredCredential && !credential) {
message = 'The endpoint requires authentication, but no credentials are stored for this connection on this machine. '
+ 'Credentials are kept in the local secret storage and do not sync with settings — '
+ `open the connection editor to enter them. (${message})`;
}
const error = {
code: response.status,
message
};
this._onDidConnectionTestEnd.fire({ connection, error });
return error;
} catch (e: any) {
const error = {
code: e.status || e.code || 0,
message: e.message || String(e)
};
this._onDidConnectionTestEnd.fire({ connection, error });
return error;
}
}
}
|