1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.serverMediaOverlays = void 0;
|
4 | const tslib_1 = require("tslib");
|
5 | const crypto = require("crypto");
|
6 | const css2json = require("css2json");
|
7 | const debug_ = require("debug");
|
8 | const express = require("express");
|
9 | const jsonMarkup = require("json-markup");
|
10 | const path = require("path");
|
11 | const serializable_1 = require("r2-lcp-js/dist/es7-es2016/src/serializable");
|
12 | const epub_1 = require("r2-shared-js/dist/es7-es2016/src/parser/epub");
|
13 | const UrlUtils_1 = require("r2-utils-js/dist/es7-es2016/src/_utils/http/UrlUtils");
|
14 | const JsonUtils_1 = require("r2-utils-js/dist/es7-es2016/src/_utils/JsonUtils");
|
15 | const request_ext_1 = require("./request-ext");
|
16 | const debug = debug_("r2:streamer#http/server-mediaoverlays");
|
17 | function serverMediaOverlays(server, routerPathBase64) {
|
18 | const jsonStyle = `
|
19 | .json-markup {
|
20 | line-height: 17px;
|
21 | font-size: 13px;
|
22 | font-family: monospace;
|
23 | white-space: pre;
|
24 | }
|
25 | .json-markup-key {
|
26 | font-weight: bold;
|
27 | }
|
28 | .json-markup-bool {
|
29 | color: firebrick;
|
30 | }
|
31 | .json-markup-string {
|
32 | color: green;
|
33 | }
|
34 | .json-markup-null {
|
35 | color: gray;
|
36 | }
|
37 | .json-markup-number {
|
38 | color: blue;
|
39 | }
|
40 | `;
|
41 | const routerMediaOverlays = express.Router({ strict: false });
|
42 | routerMediaOverlays.get(["/", "/" + request_ext_1._show + "/:" + epub_1.mediaOverlayURLParam + "?"], (req, res) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
43 | const reqparams = req.params;
|
44 | if (!reqparams.pathBase64) {
|
45 | reqparams.pathBase64 = req.pathBase64;
|
46 | }
|
47 | if (!reqparams.lcpPass64) {
|
48 | reqparams.lcpPass64 = req.lcpPass64;
|
49 | }
|
50 | const isShow = req.url.indexOf("/show") >= 0 || req.query.show;
|
51 | const isHead = req.method.toLowerCase() === "head";
|
52 | if (isHead) {
|
53 | debug("HEAD !!!!!!!!!!!!!!!!!!!");
|
54 | }
|
55 | const isCanonical = req.query.canonical &&
|
56 | req.query.canonical === "true";
|
57 | const isSecureHttp = req.secure ||
|
58 | req.protocol === "https" ||
|
59 | req.get("X-Forwarded-Proto") === "https";
|
60 | const pathBase64Str = Buffer.from(reqparams.pathBase64, "base64").toString("utf8");
|
61 | let publication;
|
62 | try {
|
63 | publication = yield server.loadOrGetCachedPublication(pathBase64Str);
|
64 | }
|
65 | catch (err) {
|
66 | debug(err);
|
67 | res.status(500).send("<html><body><p>Internal Server Error</p><p>"
|
68 | + err + "</p></body></html>");
|
69 | return;
|
70 | }
|
71 | const rootUrl = (isSecureHttp ? "https://" : "http://")
|
72 | + req.headers.host + "/pub/"
|
73 | + (reqparams.lcpPass64 ?
|
74 | (server.lcpBeginToken + UrlUtils_1.encodeURIComponent_RFC3986(reqparams.lcpPass64) + server.lcpEndToken) :
|
75 | "")
|
76 | + UrlUtils_1.encodeURIComponent_RFC3986(reqparams.pathBase64);
|
77 | function absoluteURL(href) {
|
78 | return rootUrl + "/" + href;
|
79 | }
|
80 | function absolutizeURLs(jsonObject) {
|
81 | JsonUtils_1.traverseJsonObjects(jsonObject, (obj) => {
|
82 | if (obj.text && typeof obj.text === "string"
|
83 | && !UrlUtils_1.isHTTP(obj.text)) {
|
84 | obj.text = absoluteURL(obj.text);
|
85 | }
|
86 | if (obj.audio && typeof obj.audio === "string"
|
87 | && !UrlUtils_1.isHTTP(obj.audio)) {
|
88 | obj.audio = absoluteURL(obj.audio);
|
89 | }
|
90 | });
|
91 | }
|
92 | let objToSerialize = null;
|
93 | const resource = isShow ?
|
94 | (req.query.show ?
|
95 | req.query.show :
|
96 | reqparams[epub_1.mediaOverlayURLParam]) :
|
97 | req.query[epub_1.mediaOverlayURLParam];
|
98 | if (resource && resource !== "all") {
|
99 | try {
|
100 | objToSerialize = yield epub_1.getMediaOverlay(publication, resource);
|
101 | }
|
102 | catch (err) {
|
103 | debug(err);
|
104 | res.status(500).send("<html><body><p>Internal Server Error</p><p>"
|
105 | + err + "</p></body></html>");
|
106 | return;
|
107 | }
|
108 | }
|
109 | else {
|
110 | try {
|
111 | objToSerialize = yield epub_1.getAllMediaOverlays(publication);
|
112 | }
|
113 | catch (err) {
|
114 | debug(err);
|
115 | res.status(500).send("<html><body><p>Internal Server Error</p><p>"
|
116 | + err + "</p></body></html>");
|
117 | return;
|
118 | }
|
119 | }
|
120 | if (!objToSerialize) {
|
121 | objToSerialize = [];
|
122 | }
|
123 | const jsonObj = serializable_1.TaJsonSerialize(objToSerialize);
|
124 | if (isShow) {
|
125 | absolutizeURLs(jsonObj);
|
126 | const jsonPretty = jsonMarkup(jsonObj, css2json(jsonStyle));
|
127 | res.status(200).send("<html><body>" +
|
128 | "<h1>" + path.basename(pathBase64Str) + "</h1>" +
|
129 | "<p><pre>" + jsonPretty + "</pre></p>" +
|
130 | "</body></html>");
|
131 | }
|
132 | else {
|
133 | server.setResponseCORS(res);
|
134 | res.set("Content-Type", "application/vnd.syncnarr+json; charset=utf-8");
|
135 | const jsonStr = isCanonical ?
|
136 | global.JSON.stringify(JsonUtils_1.sortObject(jsonObj), null, "") :
|
137 | global.JSON.stringify(jsonObj, null, " ");
|
138 | const checkSum = crypto.createHash("sha256");
|
139 | checkSum.update(jsonStr);
|
140 | const hash = checkSum.digest("hex");
|
141 | const match = req.header("If-None-Match");
|
142 | if (match === hash) {
|
143 | debug("smil cache");
|
144 | res.status(304);
|
145 | res.end();
|
146 | return;
|
147 | }
|
148 | res.setHeader("ETag", hash);
|
149 | res.status(200);
|
150 | if (isHead) {
|
151 | res.end();
|
152 | }
|
153 | else {
|
154 | res.send(jsonStr);
|
155 | }
|
156 | }
|
157 | }));
|
158 | routerPathBase64.use("/:" + request_ext_1._pathBase64 + "/" + epub_1.mediaOverlayURLPath, routerMediaOverlays);
|
159 | }
|
160 | exports.serverMediaOverlays = serverMediaOverlays;
|
161 |
|
\ | No newline at end of file |