UNPKG

21.5 kBSource Map (JSON)View Raw
1{"version":3,"file":"server-opds-local-feed.js","sourceRoot":"","sources":["../../../../src/http/server-opds-local-feed.ts"],"names":[],"mappings":"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","sourcesContent":["// ==LICENSE-BEGIN==\n// Copyright 2017 European Digital Reading Lab. All rights reserved.\n// Licensed to the Readium Foundation under one or more contributor license agreements.\n// Use of this source code is governed by a BSD-style license\n// that can be found in the LICENSE file exposed on Github (readium) in the project repository.\n// ==LICENSE-END==\n\nimport * as crypto from \"crypto\";\nimport * as css2json from \"css2json\";\nimport * as debug_ from \"debug\";\nimport * as DotProp from \"dot-prop\";\nimport * as express from \"express\";\nimport * as jsonMarkup from \"json-markup\";\nimport * as path from \"path\";\n\nimport { JsonArray, TaJsonSerialize } from \"@r2-lcp-js/serializable\";\nimport { OPDSLink } from \"@r2-opds-js/opds/opds2/opds2-link\";\nimport { isHTTP } from \"@r2-utils-js/_utils/http/UrlUtils\";\nimport { sortObject, traverseJsonObjects } from \"@r2-utils-js/_utils/JsonUtils\";\n\nimport { jsonSchemaValidate } from \"../utils/json-schema-validate\";\nimport { IRequestPayloadExtension, IRequestQueryParams, _jsonPath, _show } from \"./request-ext\";\nimport { Server } from \"./server\";\nimport { trailingSlashRedirect } from \"./server-trailing-slash-redirect\";\n\nconst debug = debug_(\"r2:streamer#http/server-opds-local-feed\");\n\n// tslint:disable-next-line:variable-name\nexport const serverOPDS_local_feed_PATH = \"/opds2\";\n// tslint:disable-next-line:variable-name\nexport const serverOPDS_local_feed_PATH_ = \"/publications.json\";\nexport function serverOPDS_local_feed(server: Server, topRouter: express.Application) {\n\n // https://github.com/mafintosh/json-markup/blob/master/style.css\n const jsonStyle = `\n.json-markup {\n line-height: 17px;\n font-size: 13px;\n font-family: monospace;\n white-space: pre;\n}\n.json-markup-key {\n font-weight: bold;\n}\n.json-markup-bool {\n color: firebrick;\n}\n.json-markup-string {\n color: green;\n}\n.json-markup-null {\n color: gray;\n}\n.json-markup-number {\n color: blue;\n}\n`;\n\n // tslint:disable-next-line:variable-name\n const routerOPDS_local_feed = express.Router({ strict: false });\n // routerOPDS2.use(morgan(\"combined\", { stream: { write: (msg: any) => debug(msg) } }));\n\n routerOPDS_local_feed.get([\"/\", \"/\" + _show + \"/:\" + _jsonPath + \"?\"],\n (req: express.Request, res: express.Response) => {\n\n const reqparams = (req as IRequestPayloadExtension).params;\n\n const isShow = req.url.indexOf(\"/show\") >= 0 || (req.query as IRequestQueryParams).show;\n if (!reqparams.jsonPath && (req.query as IRequestQueryParams).show) {\n reqparams.jsonPath = (req.query as IRequestQueryParams).show;\n }\n\n const isCanonical = (req.query as IRequestQueryParams).canonical &&\n (req.query as IRequestQueryParams).canonical === \"true\";\n\n const isSecureHttp = req.secure ||\n req.protocol === \"https\" ||\n req.get(\"X-Forwarded-Proto\") === \"https\"\n ;\n\n const rootUrl = (isSecureHttp ? \"https://\" : \"http://\")\n + req.headers.host;\n const selfURL = rootUrl + serverOPDS_local_feed_PATH + serverOPDS_local_feed_PATH_;\n\n const feed = server.publicationsOPDS();\n if (!feed) {\n const err = \"Publications OPDS2 feed not available yet, try again later.\";\n debug(err);\n res.status(503).send(\"<html><body><p>Resource temporarily unavailable</p><p>\"\n + err + \"</p></body></html>\");\n return;\n }\n\n if (!feed.findFirstLinkByRel(\"self\")) {\n feed.Links = [];\n const selfLink = new OPDSLink();\n selfLink.Href = selfURL;\n selfLink.TypeLink = \"application/opds+json\";\n selfLink.AddRel(\"self\");\n feed.Links.push(selfLink);\n }\n\n function absoluteURL(href: string): string {\n return rootUrl + \"/pub/\" + href;\n }\n\n function absolutizeURLs(jsonObj: any) {\n traverseJsonObjects(jsonObj,\n (obj) => {\n if (obj.href && typeof obj.href === \"string\") {\n\n if (!isHTTP(obj.href)) {\n // obj.href_ = obj.href;\n obj.href = absoluteURL(obj.href);\n }\n\n if (isShow &&\n (obj.type === \"application/webpub+json\"\n || obj.type === \"application/audiobook+json\"\n || obj.type === \"application/divina+json\") &&\n obj.rel === \"http://opds-spec.org/acquisition\" &&\n (obj.href as string).endsWith(\"/manifest.json\")) {\n obj.href += \"/show\";\n }\n }\n });\n }\n\n if (isShow) {\n let objToSerialize: any = null;\n\n if (reqparams.jsonPath) {\n switch (reqparams.jsonPath) {\n\n case \"all\": {\n objToSerialize = feed;\n break;\n }\n case \"metadata\": {\n objToSerialize = feed.Metadata;\n break;\n }\n case \"links\": {\n objToSerialize = feed.Links;\n break;\n }\n case \"publications\": {\n objToSerialize = feed.Publications;\n break;\n }\n default: {\n objToSerialize = null;\n }\n }\n } else {\n objToSerialize = feed;\n }\n\n if (!objToSerialize) {\n objToSerialize = {};\n }\n\n const jsonObj = TaJsonSerialize(objToSerialize);\n\n let validationStr: string | undefined;\n const doValidate = !reqparams.jsonPath || reqparams.jsonPath === \"all\";\n if (doValidate) {\n\n const jsonSchemasRootpath = path.join(process.cwd(), \"misc\", \"json-schema\");\n const jsonSchemasNames = [\n \"opds/feed\", // must be first!\n \"opds/publication\",\n \"opds/acquisition-object\",\n \"opds/catalog-entry\",\n \"opds/feed-metadata\",\n \"opds/properties\",\n // \"opds/authentication\",\n \"webpub-manifest/publication\",\n \"webpub-manifest/contributor-object\",\n \"webpub-manifest/contributor\",\n \"webpub-manifest/link\",\n \"webpub-manifest/metadata\",\n \"webpub-manifest/subcollection\",\n \"webpub-manifest/properties\",\n \"webpub-manifest/subject\",\n \"webpub-manifest/subject-object\",\n \"webpub-manifest/extensions/epub/metadata\",\n \"webpub-manifest/extensions/epub/subcollections\",\n \"webpub-manifest/extensions/epub/properties\",\n \"webpub-manifest/extensions/presentation/metadata\",\n \"webpub-manifest/extensions/presentation/properties\",\n \"webpub-manifest/language-map\",\n ];\n\n const validationErrors =\n jsonSchemaValidate(jsonSchemasRootpath, jsonSchemasNames, jsonObj);\n if (validationErrors) {\n validationStr = \"\";\n\n for (const err of validationErrors) {\n\n debug(\"JSON Schema validation FAIL.\");\n debug(err);\n\n const val = DotProp.get(jsonObj, err.jsonPath);\n const valueStr = (typeof val === \"string\") ?\n `${val}` :\n ((val instanceof Array || typeof val === \"object\") ?\n `${JSON.stringify(val)}` :\n \"\");\n debug(valueStr);\n\n let title = \"\";\n let pubIndex = \"\";\n if (/^publications\\.[0-9]+/.test(err.jsonPath)) {\n const jsonPubTitlePath =\n err.jsonPath.replace(/^(publications\\.[0-9]+).*/, \"$1.metadata.title\");\n debug(jsonPubTitlePath);\n title = DotProp.get(jsonObj, jsonPubTitlePath);\n debug(title);\n\n pubIndex = err.jsonPath.replace(/^publications\\.([0-9]+).*/, \"$1\");\n debug(pubIndex);\n }\n\n validationStr +=\n // tslint:disable-next-line:max-line-length\n `\\n___________INDEX___________ #${pubIndex} \"${title}\"\\n\\n${err.ajvMessage}: ${valueStr}\\n\\n'${err.ajvDataPath.replace(/^\\./, \"\")}' (${err.ajvSchemaPath})\\n\\n`;\n }\n }\n }\n\n absolutizeURLs(jsonObj);\n\n if (jsonObj.publications && (jsonObj.publications as JsonArray).length) {\n let i = 0;\n (jsonObj.publications as JsonArray).forEach((pub: any) => {\n pub.___________INDEX___________ = i++;\n });\n }\n\n // const jsonStr = global.JSON.stringify(jsonObj, null, \" \");\n\n // // breakLength: 100 maxArrayLength: undefined\n // const dumpStr = util.inspect(objToSerialize,\n // { showHidden: false, depth: 1000, colors: false, customInspect: true });\n\n const jsonPretty = jsonMarkup(jsonObj, css2json(jsonStyle));\n\n // const regex = new RegExp(\">\" + rootUrl + \"/([^<]+</a>)\", \"g\");\n // jsonPretty = jsonPretty.replace(regex, \">$1\");\n // jsonPretty = jsonPretty.replace(/>publications.json<\\/a>/, \">\" + rootUrl + \"/publications.json</a>\");\n\n res.status(200).send(\"<html><body>\" +\n \"<h1>OPDS2 JSON feed</h1>\" +\n \"<hr><p><pre>\" + jsonPretty + \"</pre></p>\" +\n // tslint:disable-next-line:max-line-length\n (doValidate ? (validationStr ? (\"<hr><p><pre>\" + validationStr + \"</pre></p>\") : (\"<hr><p>JSON SCHEMA OK.</p>\")) : \"\") +\n // \"<hr><p><pre>\" + jsonStr + \"</pre></p>\" +\n // \"<p><pre>\" + dumpStr + \"</pre></p>\" +\n \"</body></html>\");\n } else {\n server.setResponseCORS(res);\n res.set(\"Content-Type\", \"application/opds+json; charset=utf-8\");\n\n const publicationsJsonObj = TaJsonSerialize(feed);\n\n absolutizeURLs(publicationsJsonObj);\n\n const publicationsJsonStr = isCanonical ?\n global.JSON.stringify(sortObject(publicationsJsonObj), null, \"\") :\n global.JSON.stringify(publicationsJsonObj, null, \" \");\n\n const checkSum = crypto.createHash(\"sha256\");\n checkSum.update(publicationsJsonStr);\n const hash = checkSum.digest(\"hex\");\n\n const match = req.header(\"If-None-Match\");\n if (match === hash) {\n debug(\"opds2 publications.json cache\");\n res.status(304); // StatusNotModified\n res.end();\n return;\n }\n\n res.setHeader(\"ETag\", hash);\n // server.setResponseCacheHeaders(res, true);\n\n res.status(200).send(publicationsJsonStr);\n }\n });\n\n // tslint:disable-next-line:variable-name\n const routerOPDS_local_feed_ = express.Router({ strict: false });\n // routerOPDS2_.use(morgan(\"combined\", { stream: { write: (msg: any) => debug(msg) } }));\n\n routerOPDS_local_feed_.use(trailingSlashRedirect);\n\n routerOPDS_local_feed_.get(\"/\", (req: express.Request, res: express.Response) => {\n\n const i = req.originalUrl.indexOf(\"?\");\n\n let pathWithoutQuery = req.originalUrl;\n if (i >= 0) {\n pathWithoutQuery = pathWithoutQuery.substr(0, i);\n }\n\n let redirect = pathWithoutQuery +\n // (pathWithoutQuery.substr(-1) === \"/\" ? \"\" : \"/\") +\n serverOPDS_local_feed_PATH_ + \"/show\";\n redirect = redirect.replace(\"//\", \"/\");\n if (i >= 0) {\n redirect += req.originalUrl.substr(i);\n }\n\n // No need for CORS with \"show\" URL redirect\n // server.setResponseCORS(res);\n\n debug(`REDIRECT: ${req.originalUrl} ==> ${redirect}`);\n res.redirect(301, redirect);\n });\n\n routerOPDS_local_feed_.use(serverOPDS_local_feed_PATH_, routerOPDS_local_feed);\n\n topRouter.use(serverOPDS_local_feed_PATH, routerOPDS_local_feed_);\n}\n"]}
\No newline at end of file