A central component for Solid servers, handles Web Access Control and Linked Data Platform concerns.
The entry point is src/server.ts, which instantiates a http server, a BlobTree storage, and the core app. This is not drawn in the diagram above.
The BlobTree storage exposes a carefully tuned interface to the persistence layer, which is similar to the well-known "key-value store" concept, where opaque Blobs can be stored and retrieved, using arbitrary strings as keys. But the BlobTree interface differs from a key-value store interface in that it not only allows writing and reading blobs of data, but also querying 'Containers', which is similar to doing ls
on a folder on a unix file system: it gives you a list of the directly contained blobs and containers.
This means that if we store all LDP resources inside BlobTree blobs, using the resource path from the http level as the blob's path at the BlobTree level, then implementing LDP GET requests on containers becomes very easy out of the box.
The interface looks as follows (BlobTree
in the diagram):
interface BlobTree extends events.EventEmitter {
getContainer (path: Path): Container
getBlob (path: Path): Blob
}
interface Node {
exists (): Promise<boolean>,
delete (): Promise<void>
}
interface Blob extends Node {
getData (): Promise<ReadableStream | undefined>
setData (data: ReadableStream): Promise<void>
}
interface Container extends Node {
getMembers (): Promise<Array<Member>>
}
interface Member {
name: string
isContainer: boolean
}
interface Path {
constructor (segments: Array<string>)
toParent (): Path
toChild (segment: string): Path
isRoot (): boolean
toString (): string
toContainerPathPrefix (): string
hasSuffix (suffix: string): boolean
removeSuffix (suffix: string): Path
appendSuffix (suffix: string): Path
}
The core application code is in src/lib/core/executeTask.ts and given a WacLdpTask
(see below), it deals with:
WacLdpResult
(see below) result for src/lib/api/http/HttpResponderErrorResult
, to be cast to WacLdpResult
The auth code is in src/lib/authorization/ and deals with:
The Auth Interface looks as follows:
async function determineWebId (bearerToken: string, audience: string): Promise<string | undefined>
async function readAcl (resourcePath: Path, resourceIsContainer: boolean, storage: BlobTree)
async function determineAllowedAgentsForModes (task: ModesCheckTask): Promise<AccessModes>
interface ModesCheckTask {
aclGraph: any,
isAdjacent: boolean,
resourcePath: string
}
interface AccessModes {
read: Array<string>
write: Array<string>
append: Array<string>
control: Array<string>
}
async function appIsTrustedForMode (task: OriginCheckTask): Promise<boolean>
interface OriginCheckTask {
origin: string,
mode: string,
resourceOwners: Array<string>
}
In src/lib/api/http/ are two important classes, one for parsing an incoming http request, and one for constructing an outgoing http response. Although each step they do, like setting a numeric http response status code, or extracting a bearer token string from an authorization header, is computationally simple, a lot of the correctness of this module (looking at https://github.com/w3c/ldp-testsuite and the WAC test suite that is under development) depends on the details in these two files.
interface WacLdpTask {
isContainer: boolean
omitBody: boolean
parsedContentType: ParsedContentType | undefined
origin: string | undefined
contentType: string | undefined
ifMatch: string | undefined
ifNoneMatchStar: boolean
ifNoneMatchList: Array<string> | undefined
bearerToken: string | undefined
wacLdpTaskType: TaskType
path: Path
requestBody: string | undefined
}
enum TaskType {
containerRead,
containerMemberAdd,
containerDelete,
globRead,
blobRead,
blobWrite,
blobUpdate,
blobDelete,
getOptions,
unknown
}
enum ParsedContentType {
RdfJsonLd,
RdfTurtle
}
interface WacLdpResponse {
resultType: ResultType
resourceData: ResourceData | undefined
createdLocation: string | undefined
isContainer: boolean
}
The following operations are available:
Currently supported representations for RDF are Turtle and JSON-LD. The only currently allowed patch type for RDF are SPARQL-update (any)
and SPARQL-update (appendOnly)
. The currently allowed filter types for RDF are SPARQL-SELECT
, ldp-paging
, and prefer-minimal-container
.
In the future, we might add similar modules for e.g. HTML/RDFa or partial updates to binary blobs, and when that happens we will turn this component into an abstract 'content operations' component, of which RDF, HTML/RDFa and Binary are instantiations.
Published under an MIT license by inrupt, Inc.
Contributors: