* Returns a fetch document handler used by the ACLChecker to fetch .acl * resources up the inheritance chain. * The `fetch(uri, callback)` results in the callback, with either: * - `callback(err, graph)` if any error is encountered, or * - `callback(null, graph)` with the parsed RDF graph of
(mapper, serverUri)
| 290 | * @return {Function} Returns a `fetch(uri, callback)` handler |
| 291 | */ |
| 292 | function fetchLocalOrRemote (mapper, serverUri) { |
| 293 | async function doFetch (url) { |
| 294 | // Convert the URL into a filename |
| 295 | let body, path, contentType |
| 296 | |
| 297 | if (Url.parse(url).host.includes(Url.parse(serverUri).host)) { |
| 298 | // Fetch the acl from local |
| 299 | try { |
| 300 | ({ path, contentType } = await mapper.mapUrlToFile({ url })) |
| 301 | } catch (err) { |
| 302 | // delete from cache |
| 303 | delete temporaryCache[url] |
| 304 | throw new HTTPError(404, err) |
| 305 | } |
| 306 | // Read the file from disk |
| 307 | body = await promisify(fs.readFile)(path, { encoding: 'utf8' }) |
| 308 | } else { |
| 309 | // Fetch the acl from the internet |
| 310 | const response = await fetch(url) |
| 311 | body = await response.text() |
| 312 | contentType = response.headers.get('content-type') |
| 313 | } |
| 314 | return { body, contentType } |
| 315 | } |
| 316 | return async function fetch (url, graph = rdf.graph()) { |
| 317 | graph.initPropertyActions(['sameAs']) // activate sameAs |
| 318 | if (!temporaryCache[url]) { |
| 319 | // debugCache('Populating cache', url) |
| 320 | temporaryCache[url] = { |
| 321 | timer: setTimeout(() => { |
| 322 | // debugCache('Expunging from cache', url) |
| 323 | delete temporaryCache[url] |
| 324 | if (Object.keys(temporaryCache).length === 0) { |
| 325 | // debugCache('Cache is empty again') |
| 326 | } |
| 327 | }, EXPIRY_MS), |
| 328 | promise: doFetch(url) |
| 329 | } |
| 330 | } |
| 331 | // debugCache('Cache hit', url) |
| 332 | const { body, contentType } = await temporaryCache[url].promise |
| 333 | // Parse the file as Turtle |
| 334 | rdf.parse(body, graph, url, contentType) |
| 335 | return graph |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | // Returns the index of the last slash before the given position |
| 340 | function lastSlash (string, pos = string.length) { |
no test coverage detected