UNPKG

16.7 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.serverAssets = void 0;
4var tslib_1 = require("tslib");
5var debug_ = require("debug");
6var express = require("express");
7var mime = require("mime-types");
8var path = require("path");
9var zipHasEntry_1 = require("r2-shared-js/dist/es5/src/_utils/zipHasEntry");
10var transformer_1 = require("r2-shared-js/dist/es5/src/transform/transformer");
11var RangeUtils_1 = require("r2-utils-js/dist/es5/src/_utils/http/RangeUtils");
12var BufferUtils_1 = require("r2-utils-js/dist/es5/src/_utils/stream/BufferUtils");
13var request_ext_1 = require("./request-ext");
14var debug = debug_("r2:streamer#http/server-assets");
15function serverAssets(server, routerPathBase64) {
16 var _this = this;
17 var routerAssets = express.Router({ strict: false });
18 routerAssets.get("/", function (req, res) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
19 var reqparams, isShow, isHead, pathBase64Str, publication, err_1, zipInternal, err, zip, pathInZip, err, isDivina, link, findLinkRecursive, relativePath, _i, _a, l, _b, _c, l, _d, _e, l, err, mediaType, isText, isEncrypted, isPartialByteRangeRequest, partialByteBegin, partialByteEnd, ranges, err, zipStream_, _f, err_2, doTransform, sessionInfo, fullUrl, transformedStream, err_3, err, zipData, err_4, partialByteLength, rangeHeader;
20 return tslib_1.__generator(this, function (_g) {
21 switch (_g.label) {
22 case 0:
23 reqparams = req.params;
24 if (!reqparams.pathBase64) {
25 reqparams.pathBase64 = req.pathBase64;
26 }
27 if (!reqparams.asset) {
28 reqparams.asset = req.asset;
29 }
30 if (!reqparams.lcpPass64) {
31 reqparams.lcpPass64 = req.lcpPass64;
32 }
33 isShow = req.query.show;
34 isHead = req.method.toLowerCase() === "head";
35 if (isHead) {
36 debug("HEAD !!!!!!!!!!!!!!!!!!!");
37 }
38 pathBase64Str = Buffer.from(reqparams.pathBase64, "base64").toString("utf8");
39 _g.label = 1;
40 case 1:
41 _g.trys.push([1, 3, , 4]);
42 return [4, server.loadOrGetCachedPublication(pathBase64Str)];
43 case 2:
44 publication = _g.sent();
45 return [3, 4];
46 case 3:
47 err_1 = _g.sent();
48 debug(err_1);
49 res.status(500).send("<html><body><p>Internal Server Error</p><p>"
50 + err_1 + "</p></body></html>");
51 return [2];
52 case 4:
53 zipInternal = publication.findFromInternal("zip");
54 if (!zipInternal) {
55 err = "No publication zip!";
56 debug(err);
57 res.status(500).send("<html><body><p>Internal Server Error</p><p>"
58 + err + "</p></body></html>");
59 return [2];
60 }
61 zip = zipInternal.Value;
62 pathInZip = reqparams.asset;
63 if (!zipHasEntry_1.zipHasEntry(zip, pathInZip, undefined)) {
64 err = "Asset not in zip! " + pathInZip;
65 debug(err);
66 res.status(500).send("<html><body><p>Internal Server Error</p><p>"
67 + err + "</p></body></html>");
68 return [2];
69 }
70 isDivina = publication.Metadata && publication.Metadata.RDFType &&
71 (/http[s]?:\/\/schema\.org\/ComicStory$/.test(publication.Metadata.RDFType) ||
72 /http[s]?:\/\/schema\.org\/VisualNarrative$/.test(publication.Metadata.RDFType));
73 findLinkRecursive = function (relativePath, l) {
74 if (l.Href === relativePath) {
75 return l;
76 }
77 var found;
78 if (l.Children) {
79 for (var _i = 0, _a = l.Children; _i < _a.length; _i++) {
80 var child = _a[_i];
81 found = findLinkRecursive(relativePath, child);
82 if (found) {
83 return found;
84 }
85 }
86 }
87 if (l.Alternate) {
88 for (var _b = 0, _c = l.Alternate; _b < _c.length; _b++) {
89 var alt = _c[_b];
90 found = findLinkRecursive(relativePath, alt);
91 if (found) {
92 return found;
93 }
94 }
95 }
96 return undefined;
97 };
98 if ((publication.Resources || publication.Spine || publication.Links)
99 && pathInZip.indexOf("META-INF/") !== 0
100 && !pathInZip.endsWith(".opf")) {
101 relativePath = pathInZip;
102 if (publication.Resources) {
103 for (_i = 0, _a = publication.Resources; _i < _a.length; _i++) {
104 l = _a[_i];
105 link = findLinkRecursive(relativePath, l);
106 if (link) {
107 break;
108 }
109 }
110 }
111 if (!link) {
112 if (publication.Spine) {
113 for (_b = 0, _c = publication.Spine; _b < _c.length; _b++) {
114 l = _c[_b];
115 link = findLinkRecursive(relativePath, l);
116 if (link) {
117 break;
118 }
119 }
120 }
121 }
122 if (!link) {
123 if (publication.Links) {
124 for (_d = 0, _e = publication.Links; _d < _e.length; _d++) {
125 l = _e[_d];
126 link = findLinkRecursive(relativePath, l);
127 if (link) {
128 break;
129 }
130 }
131 }
132 }
133 if (!link &&
134 !isDivina) {
135 err = "Asset not declared in publication spine/resources!" + relativePath;
136 debug(err);
137 res.status(500).send("<html><body><p>Internal Server Error</p><p>"
138 + err + "</p></body></html>");
139 return [2];
140 }
141 }
142 if (server.isSecured() && !link &&
143 (pathInZip.indexOf("META-INF/") === 0 || pathInZip.endsWith(".opf"))) {
144 res.status(200).send("<html><body></body></html>");
145 return [2];
146 }
147 mediaType = mime.lookup(pathInZip);
148 if (link && link.TypeLink) {
149 mediaType = link.TypeLink;
150 }
151 isText = (typeof mediaType === "string") && (mediaType.indexOf("text/") === 0 ||
152 mediaType.indexOf("application/xhtml") === 0 ||
153 mediaType.indexOf("application/xml") === 0 ||
154 mediaType.indexOf("application/json") === 0 ||
155 mediaType.indexOf("application/svg") === 0 ||
156 mediaType.indexOf("application/smil") === 0 ||
157 mediaType.indexOf("+json") > 0 ||
158 mediaType.indexOf("+smil") > 0 ||
159 mediaType.indexOf("+svg") > 0 ||
160 mediaType.indexOf("+xhtml") > 0 ||
161 mediaType.indexOf("+xml") > 0);
162 isEncrypted = link && link.Properties && link.Properties.Encrypted;
163 isPartialByteRangeRequest = ((req.headers && req.headers.range) ? true : false);
164 partialByteBegin = 0;
165 partialByteEnd = -1;
166 if (isPartialByteRangeRequest) {
167 debug(req.headers.range);
168 ranges = RangeUtils_1.parseRangeHeader(req.headers.range);
169 if (ranges && ranges.length) {
170 if (ranges.length > 1) {
171 err = "Too many HTTP ranges: " + req.headers.range;
172 debug(err);
173 res.status(416).send("<html><body><p>Internal Server Error</p><p>"
174 + err + "</p></body></html>");
175 return [2];
176 }
177 partialByteBegin = ranges[0].begin;
178 partialByteEnd = ranges[0].end;
179 if (partialByteBegin < 0) {
180 partialByteBegin = 0;
181 }
182 }
183 debug(pathInZip + " >> " + partialByteBegin + "-" + partialByteEnd);
184 }
185 _g.label = 5;
186 case 5:
187 _g.trys.push([5, 10, , 11]);
188 if (!(isPartialByteRangeRequest && !isEncrypted)) return [3, 7];
189 return [4, zip.entryStreamRangePromise(pathInZip, partialByteBegin, partialByteEnd)];
190 case 6:
191 _f = _g.sent();
192 return [3, 9];
193 case 7: return [4, zip.entryStreamPromise(pathInZip)];
194 case 8:
195 _f = _g.sent();
196 _g.label = 9;
197 case 9:
198 zipStream_ = _f;
199 return [3, 11];
200 case 10:
201 err_2 = _g.sent();
202 debug(err_2);
203 res.status(500).send("<html><body><p>Internal Server Error</p><p>"
204 + err_2 + "</p></body></html>");
205 return [2];
206 case 11:
207 doTransform = true;
208 sessionInfo = req.query[request_ext_1.URL_PARAM_SESSION_INFO];
209 if (!(doTransform && link)) return [3, 16];
210 fullUrl = "" + server.serverUrl() + req.originalUrl;
211 transformedStream = void 0;
212 _g.label = 12;
213 case 12:
214 _g.trys.push([12, 14, , 15]);
215 return [4, transformer_1.Transformers.tryStream(publication, link, fullUrl, zipStream_, isPartialByteRangeRequest, partialByteBegin, partialByteEnd, sessionInfo)];
216 case 13:
217 transformedStream = _g.sent();
218 return [3, 15];
219 case 14:
220 err_3 = _g.sent();
221 debug(err_3);
222 res.status(500).send("<html><body><p>Internal Server Error</p><p>"
223 + err_3 + "</p></body></html>");
224 return [2];
225 case 15:
226 if (transformedStream) {
227 if (transformedStream !== zipStream_) {
228 debug("Asset transformed ok: " + link.Href);
229 }
230 zipStream_ = transformedStream;
231 }
232 else {
233 err = "Transform fail (encryption scheme not supported?)";
234 debug(err);
235 res.status(500).send("<html><body><p>Internal Server Error</p><p>"
236 + err + "</p></body></html>");
237 return [2];
238 }
239 _g.label = 16;
240 case 16:
241 if (!isShow) return [3, 21];
242 zipData = void 0;
243 _g.label = 17;
244 case 17:
245 _g.trys.push([17, 19, , 20]);
246 return [4, BufferUtils_1.streamToBufferPromise(zipStream_.stream)];
247 case 18:
248 zipData = _g.sent();
249 return [3, 20];
250 case 19:
251 err_4 = _g.sent();
252 debug(err_4);
253 res.status(500).send("<html><body><p>Internal Server Error</p><p>"
254 + err_4 + "</p></body></html>");
255 return [2];
256 case 20:
257 if (zipData) {
258 debug("CHECK: " + zipStream_.length + " ==> " + zipData.length);
259 }
260 res.status(200).send("<html><body>" +
261 "<h1>" + path.basename(pathBase64Str) + "</h1>" +
262 "<h2>" + mediaType + "</h2>" +
263 ((isText && zipData) ?
264 ("<p><pre>" +
265 zipData.toString("utf8").replace(/&/g, "&amp;")
266 .replace(/</g, "&lt;")
267 .replace(/>/g, "&gt;")
268 .replace(/"/g, "&quot;")
269 .replace(/'/g, "&apos;") +
270 "</pre></p>")
271 : "<p>BINARY</p>") + "</body></html>");
272 return [2];
273 case 21:
274 server.setResponseCORS(res);
275 if (isPartialByteRangeRequest || isEncrypted) {
276 server.setResponseCacheHeaders(res, false);
277 }
278 else {
279 server.setResponseCacheHeaders(res, true);
280 }
281 if (mediaType) {
282 res.set("Content-Type", mediaType);
283 }
284 res.setHeader("Accept-Ranges", "bytes");
285 if (isPartialByteRangeRequest) {
286 if (partialByteEnd < 0) {
287 partialByteEnd = zipStream_.length - 1;
288 }
289 partialByteLength = isPartialByteRangeRequest ?
290 partialByteEnd - partialByteBegin + 1 :
291 zipStream_.length;
292 res.setHeader("Content-Length", "" + partialByteLength);
293 rangeHeader = "bytes " + partialByteBegin + "-" + partialByteEnd + "/" + zipStream_.length;
294 res.setHeader("Content-Range", rangeHeader);
295 res.status(206);
296 }
297 else {
298 res.setHeader("Content-Length", "" + zipStream_.length);
299 res.status(200);
300 }
301 if (isHead) {
302 res.end();
303 }
304 else {
305 zipStream_.stream
306 .on("error", function f() {
307 debug("ZIP ERROR " + pathInZip);
308 })
309 .pipe(res)
310 .on("error", function f() {
311 debug("RES ERROR " + pathInZip);
312 })
313 .on("close", function f() {
314 res.end();
315 });
316 }
317 return [2];
318 }
319 });
320 }); });
321 routerPathBase64.param("asset", function (req, _res, next, value, _name) {
322 if (value) {
323 value = value.replace(/\/\/+/g, "/");
324 }
325 req.asset = value;
326 next();
327 });
328 routerPathBase64.use("/:" + request_ext_1._pathBase64 + "/:" + request_ext_1._asset + "(*)", routerAssets);
329}
330exports.serverAssets = serverAssets;
331//# sourceMappingURL=server-assets.js.map
\No newline at end of file