diff --git a/routes/redirects.js b/routes/redirects.js index 07081b1..ecf8034 100644 --- a/routes/redirects.js +++ b/routes/redirects.js @@ -41,6 +41,12 @@ router.get("/([a-z][a-z])/:page([a-z-]+)", (req, res) => { // Redirec ILC1 URL to its URI router.get("/ILC/1", (req, res) => res.redirect("/en/node/472")) +// Redirect local vocabulary URIs to URI search +router.get("/en/Format/:id([a-zA-Z0-9_-]+)", (req, res) => + res.redirect(`/?uri=http://bartoc.org/en/Format/${req.params.id}`)) +router.get("/language/:id([a-z]{2,3})", (req, res) => + res.redirect(`/?uri=http://bartoc.org/language/${req.params.id}`)) + // redirect old subject URLs to vocabulary search for (const [url, uri] of readCsv("./data/eurovoc-ids.csv")) { diff --git a/routes/uri.js b/routes/uri.js new file mode 100644 index 0000000..e9f7053 --- /dev/null +++ b/routes/uri.js @@ -0,0 +1,70 @@ +import express from "express" +const router = express.Router() + +import config from "../config/index.js" + +const suffix = (s, prefix) => s.startsWith(prefix) ? s.slice(prefix.length) : null + +const conceptView = (id, uri) => `/en/node/${id}?uri=${encodeURIComponent(uri)}#content` + +// query uri at base +router.get("/", async (req, res, next) => { + const { uri } = req.query + if (!uri) { + next() + } else { + + // BARTOC URI, URL or lookalike + const bartocUri = uri.match('^https?://(www\.)?bartoc.org/(.*)') + if (bartocUri) { + const localPart = bartocUri[2] + + // known vocabularies with namespace at bartoc.org + if (localPart.startsWith("en/Format/")) { + res.redirect(conceptView("20000", `http://bartoc.org/${localPart}`)) + } else if (localPart.startsWith("language/")) { + res.redirect(conceptView("20287", `http://bartoc.org/${localPart}`)) + } else { + // TODO: add ILC as well + // any other page + res.redirect(`/${localPart}`) + } + + return + } + + // Vocabulary or concept stored in the backend + const dataEndpoint = config.registry._api.api + "data" + const jskos = await config.registry.axios.get(dataEndpoint, { params: { uri } }) + .then(res => res[0]) + .catch(() => null) + if (jskos) { + const type = jskos.type[0] + if (type === "http://www.w3.org/2004/02/skos/core#ConceptScheme") { + // known vocabulary + const id = suffix(jskos.uri, "http://bartoc.org/en/node/") + if (id) { + res.redirect(`/en/node/${id}`) + return + } + } else if (type === "http://www.w3.org/2004/02/skos/core#Concept") { + // known concept + console.log(jskos.inScheme) + const schemes = jskos.inScheme + .map(s => suffix(s.uri, "http://bartoc.org/en/node/")) + .filter(Boolean) + if (schemes.length) { + res.redirect(conceptView(schemes[0], concept)) + return + } + } + } + + // TODO: try to match to a known vocabulary namespace + // e.g. http://bartoc.org/api-type/jskos + + next() + } +}) + +export default router diff --git a/server.js b/server.js index 23c58eb..6ea4316 100644 --- a/server.js +++ b/server.js @@ -58,11 +58,12 @@ app.use("/dist/", express.static("dist")) import redirectsRoute from "./routes/redirects.js" import apiRoute from "./routes/api.js" +import uriRoute from "./routes/uri.js" import pageRoute from "./routes/page.js" -// Routes without server-side backend access app.use(redirectsRoute) app.use("/api", apiRoute) +app.use(uriRoute) app.use(pageRoute) // render HTML page with EJS @@ -161,12 +162,7 @@ function conceptPageHandler(prefix) { } } - -app.get("/en/Format/:id", conceptPageHandler("http://bartoc.org/en/Format/") ) - -app.get("/language/:id([a-z]{2,3})", conceptPageHandler("https://bartoc.org/language/") ) - -// FIXME: ILC is not in the BARTOC registry yet +// TODO: ILC is not in the BARTOC registry yet app.get("/ILC/1/:id([a-z0-9-]+)", conceptPageHandler("https://bartoc.org/ILC/1/") ) // list of terminology registries diff --git a/views/404.ejs b/views/404.ejs index e70d3fb..b40af1f 100644 --- a/views/404.ejs +++ b/views/404.ejs @@ -1,5 +1,16 @@ <%- include('header') %> -
Sorry, the resource could not be found!
++ Sorry, the resource could not be found! + Are you looking for vocabularies? +
++
+ Search by URI: +
+ <%- include('footer') %>