UNPKG

15.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Server = exports.MAX_PREFETCH_LINKS = void 0;
4var tslib_1 = require("tslib");
5var child_process = require("child_process");
6var debug_ = require("debug");
7var express = require("express");
8var fs = require("fs");
9var http = require("http");
10var https = require("https");
11var path = require("path");
12var tmp_1 = require("tmp");
13var serializable_1 = require("r2-lcp-js/dist/es5/src/serializable");
14var opds2_1 = require("r2-opds-js/dist/es5/src/opds/opds2/opds2");
15var publication_parser_1 = require("r2-shared-js/dist/es5/src/parser/publication-parser");
16var UrlUtils_1 = require("r2-utils-js/dist/es5/src/_utils/http/UrlUtils");
17var self_signed_1 = require("../utils/self-signed");
18var server_assets_1 = require("./server-assets");
19var server_lcp_lsd_show_1 = require("./server-lcp-lsd-show");
20var server_manifestjson_1 = require("./server-manifestjson");
21var server_mediaoverlays_1 = require("./server-mediaoverlays");
22var server_opds_browse_v1_1 = require("./server-opds-browse-v1");
23var server_opds_browse_v2_1 = require("./server-opds-browse-v2");
24var server_opds_convert_v1_to_v2_1 = require("./server-opds-convert-v1-to-v2");
25var server_opds_local_feed_1 = require("./server-opds-local-feed");
26var server_pub_1 = require("./server-pub");
27var server_root_1 = require("./server-root");
28var server_secure_1 = require("./server-secure");
29var server_url_1 = require("./server-url");
30var server_version_1 = require("./server-version");
31var debug = debug_("r2:streamer#http/server");
32exports.MAX_PREFETCH_LINKS = 10;
33var Server = (function () {
34 function Server(options) {
35 this.lcpBeginToken = "*-";
36 this.lcpEndToken = "-*";
37 this.disableReaders = options && options.disableReaders ? options.disableReaders : false;
38 this.disableDecryption = options && options.disableDecryption ? options.disableDecryption : false;
39 this.disableRemotePubUrl = options && options.disableRemotePubUrl ? options.disableRemotePubUrl : false;
40 this.disableOPDS = options && options.disableOPDS ? options.disableOPDS : false;
41 this.maxPrefetchLinks = options && options.maxPrefetchLinks ? options.maxPrefetchLinks : exports.MAX_PREFETCH_LINKS;
42 this.publications = [];
43 this.pathPublicationMap = {};
44 this.publicationsOPDSfeed = undefined;
45 this.publicationsOPDSfeedNeedsUpdate = true;
46 this.creatingPublicationsOPDS = false;
47 this.opdsJsonFilePath = tmp_1.tmpNameSync({ prefix: "readium2-OPDS2-", postfix: ".json" });
48 this.expressApp = express();
49 server_secure_1.serverSecure(this, this.expressApp);
50 var staticOptions = {
51 etag: false,
52 };
53 if (!this.disableReaders) {
54 this.expressApp.use("/readerNYPL", express.static("misc/readers/reader-NYPL", staticOptions));
55 this.expressApp.use("/readerHADRIEN", express.static("misc/readers/reader-HADRIEN", staticOptions));
56 }
57 server_root_1.serverRoot(this, this.expressApp);
58 server_version_1.serverVersion(this, this.expressApp);
59 if (!this.disableRemotePubUrl) {
60 server_url_1.serverRemotePub(this, this.expressApp);
61 server_lcp_lsd_show_1.serverLCPLSD_show(this, this.expressApp);
62 }
63 if (!this.disableOPDS) {
64 server_opds_browse_v1_1.serverOPDS_browse_v1(this, this.expressApp);
65 server_opds_browse_v2_1.serverOPDS_browse_v2(this, this.expressApp);
66 server_opds_local_feed_1.serverOPDS_local_feed(this, this.expressApp);
67 server_opds_convert_v1_to_v2_1.serverOPDS_convert_v1_to_v2(this, this.expressApp);
68 }
69 var routerPathBase64 = server_pub_1.serverPub(this, this.expressApp);
70 server_manifestjson_1.serverManifestJson(this, routerPathBase64);
71 server_mediaoverlays_1.serverMediaOverlays(this, routerPathBase64);
72 server_assets_1.serverAssets(this, routerPathBase64);
73 }
74 Server.prototype.preventRobots = function () {
75 this.expressApp.get("/robots.txt", function (_req, res) {
76 var robotsTxt = "User-agent: *\nDisallow: /\n";
77 res.header("Content-Type", "text/plain");
78 res.status(200).send(robotsTxt);
79 });
80 };
81 Server.prototype.expressUse = function (pathf, func) {
82 this.expressApp.use(pathf, func);
83 };
84 Server.prototype.expressGet = function (paths, func) {
85 this.expressApp.get(paths, func);
86 };
87 Server.prototype.isStarted = function () {
88 return (typeof this.serverInfo() !== "undefined") &&
89 (typeof this.httpServer !== "undefined") ||
90 (typeof this.httpsServer !== "undefined");
91 };
92 Server.prototype.isSecured = function () {
93 return (typeof this.serverInfo() !== "undefined") &&
94 (typeof this.httpsServer !== "undefined");
95 };
96 Server.prototype.getSecureHTTPHeader = function (url) {
97 return server_secure_1.serverSecureHTTPHeader(this, url);
98 };
99 Server.prototype.start = function (port, secure) {
100 return tslib_1.__awaiter(this, void 0, void 0, function () {
101 var envPort, p;
102 var _this = this;
103 return tslib_1.__generator(this, function (_a) {
104 if (this.isStarted()) {
105 return [2, Promise.resolve(this.serverInfo())];
106 }
107 envPort = 0;
108 try {
109 envPort = process.env.PORT ? parseInt(process.env.PORT, 10) : 0;
110 }
111 catch (err) {
112 debug(err);
113 envPort = 0;
114 }
115 p = port || envPort || 3000;
116 debug("PORT: " + port + " || " + envPort + " || 3000 => " + p);
117 if (secure) {
118 this.httpServer = undefined;
119 return [2, new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
120 var certData, err_1;
121 var _this = this;
122 return tslib_1.__generator(this, function (_a) {
123 switch (_a.label) {
124 case 0:
125 _a.trys.push([0, 2, , 3]);
126 return [4, self_signed_1.generateSelfSignedData()];
127 case 1:
128 certData = _a.sent();
129 return [3, 3];
130 case 2:
131 err_1 = _a.sent();
132 debug(err_1);
133 reject("err");
134 return [2];
135 case 3:
136 this.httpsServer = https.createServer({ key: certData.private, cert: certData.cert }, this.expressApp).listen(p, function () {
137 _this.serverData = tslib_1.__assign(tslib_1.__assign({}, certData), { urlHost: "127.0.0.1", urlPort: p, urlScheme: "https" });
138 resolve(_this.serverData);
139 });
140 return [2];
141 }
142 });
143 }); })];
144 }
145 else {
146 this.httpsServer = undefined;
147 return [2, new Promise(function (resolve, _reject) {
148 _this.httpServer = http.createServer(_this.expressApp).listen(p, function () {
149 _this.serverData = {
150 urlHost: "127.0.0.1",
151 urlPort: p,
152 urlScheme: "http",
153 };
154 resolve(_this.serverData);
155 });
156 })];
157 }
158 return [2];
159 });
160 });
161 };
162 Server.prototype.stop = function () {
163 if (this.isStarted()) {
164 if (this.httpServer) {
165 this.httpServer.close();
166 this.httpServer = undefined;
167 }
168 if (this.httpsServer) {
169 this.httpsServer.close();
170 this.httpsServer = undefined;
171 }
172 this.serverData = undefined;
173 this.uncachePublications();
174 }
175 };
176 Server.prototype.serverInfo = function () {
177 return this.serverData;
178 };
179 Server.prototype.serverUrl = function () {
180 if (!this.isStarted()) {
181 return undefined;
182 }
183 var info = this.serverInfo();
184 if (!info) {
185 return undefined;
186 }
187 if (info.urlPort === 443 || info.urlPort === 80) {
188 return info.urlScheme + "://" + info.urlHost;
189 }
190 return info.urlScheme + "://" + info.urlHost + ":" + info.urlPort;
191 };
192 Server.prototype.setResponseCacheHeaders = function (res, enableCaching) {
193 if (enableCaching) {
194 res.setHeader("Cache-Control", "public,max-age=86400");
195 }
196 else {
197 res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
198 res.setHeader("Pragma", "no-cache");
199 res.setHeader("Expires", "0");
200 }
201 };
202 Server.prototype.setResponseCORS = function (res) {
203 res.setHeader("Access-Control-Allow-Origin", "*");
204 res.setHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
205 res.setHeader("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Ranges, Content-Range, Range, Link, Transfer-Encoding, X-Requested-With, Authorization, Accept, Origin, User-Agent, DNT, Cache-Control, Keep-Alive, If-Modified-Since");
206 res.setHeader("Access-Control-Expose-Headers", "Content-Type, Content-Length, Accept-Ranges, Content-Range, Range, Link, Transfer-Encoding, X-Requested-With, Authorization, Accept, Origin, User-Agent, DNT, Cache-Control, Keep-Alive, If-Modified-Since");
207 };
208 Server.prototype.addPublications = function (pubs) {
209 var _this = this;
210 pubs.forEach(function (pub) {
211 if (_this.publications.indexOf(pub) < 0) {
212 _this.publicationsOPDSfeedNeedsUpdate = true;
213 _this.publications.push(pub);
214 }
215 });
216 return pubs.map(function (pub) {
217 var pubid = UrlUtils_1.encodeURIComponent_RFC3986(Buffer.from(pub).toString("base64"));
218 return "/pub/" + pubid + "/manifest.json";
219 });
220 };
221 Server.prototype.removePublications = function (pubs) {
222 var _this = this;
223 pubs.forEach(function (pub) {
224 _this.uncachePublication(pub);
225 var i = _this.publications.indexOf(pub);
226 if (i >= 0) {
227 _this.publicationsOPDSfeedNeedsUpdate = true;
228 _this.publications.splice(i, 1);
229 }
230 });
231 return pubs.map(function (pub) {
232 var pubid = UrlUtils_1.encodeURIComponent_RFC3986(Buffer.from(pub).toString("base64"));
233 return "/pub/" + pubid + "/manifest.json";
234 });
235 };
236 Server.prototype.getPublications = function () {
237 return this.publications;
238 };
239 Server.prototype.loadOrGetCachedPublication = function (filePath) {
240 return tslib_1.__awaiter(this, void 0, void 0, function () {
241 var publication, err_2;
242 return tslib_1.__generator(this, function (_a) {
243 switch (_a.label) {
244 case 0:
245 publication = this.cachedPublication(filePath);
246 if (!!publication) return [3, 5];
247 _a.label = 1;
248 case 1:
249 _a.trys.push([1, 3, , 4]);
250 return [4, publication_parser_1.PublicationParsePromise(filePath)];
251 case 2:
252 publication = _a.sent();
253 return [3, 4];
254 case 3:
255 err_2 = _a.sent();
256 debug(err_2);
257 return [2, Promise.reject(err_2)];
258 case 4:
259 this.cachePublication(filePath, publication);
260 _a.label = 5;
261 case 5: return [2, publication];
262 }
263 });
264 });
265 };
266 Server.prototype.isPublicationCached = function (filePath) {
267 return typeof this.cachedPublication(filePath) !== "undefined";
268 };
269 Server.prototype.cachedPublication = function (filePath) {
270 return this.pathPublicationMap[filePath];
271 };
272 Server.prototype.cachePublication = function (filePath, pub) {
273 if (!this.isPublicationCached(filePath)) {
274 this.pathPublicationMap[filePath] = pub;
275 }
276 };
277 Server.prototype.uncachePublication = function (filePath) {
278 if (this.isPublicationCached(filePath)) {
279 var pub = this.cachedPublication(filePath);
280 if (pub) {
281 pub.freeDestroy();
282 }
283 this.pathPublicationMap[filePath] = undefined;
284 delete this.pathPublicationMap[filePath];
285 }
286 };
287 Server.prototype.uncachePublications = function () {
288 var _this = this;
289 Object.keys(this.pathPublicationMap).forEach(function (filePath) {
290 _this.uncachePublication(filePath);
291 });
292 };
293 Server.prototype.publicationsOPDS = function () {
294 if (this.publicationsOPDSfeedNeedsUpdate) {
295 this.publicationsOPDSfeed = undefined;
296 if (fs.existsSync(this.opdsJsonFilePath)) {
297 fs.unlinkSync(this.opdsJsonFilePath);
298 }
299 }
300 if (this.publicationsOPDSfeed) {
301 return this.publicationsOPDSfeed;
302 }
303 debug("OPDS2.json => " + this.opdsJsonFilePath);
304 if (!fs.existsSync(this.opdsJsonFilePath)) {
305 if (!this.creatingPublicationsOPDS) {
306 this.creatingPublicationsOPDS = true;
307 this.publicationsOPDSfeedNeedsUpdate = false;
308 var jsFile = path.join(__dirname, "opds2-create-cli.js");
309 var args_1 = [jsFile, this.opdsJsonFilePath];
310 this.publications.forEach(function (pub) {
311 var filePathBase64 = UrlUtils_1.encodeURIComponent_RFC3986(Buffer.from(pub).toString("base64"));
312 args_1.push(filePathBase64);
313 });
314 debug("SPAWN OPDS2-create: " + args_1[0]);
315 var child = child_process.spawn("node", args_1, {
316 cwd: process.cwd(),
317 env: process.env,
318 });
319 child.stdout.on("data", function (data) {
320 debug(data.toString());
321 });
322 child.stderr.on("data", function (data) {
323 debug(data.toString());
324 });
325 }
326 return undefined;
327 }
328 this.creatingPublicationsOPDS = false;
329 var jsonStr = fs.readFileSync(this.opdsJsonFilePath, { encoding: "utf8" });
330 if (!jsonStr) {
331 return undefined;
332 }
333 var json = global.JSON.parse(jsonStr);
334 this.publicationsOPDSfeed = serializable_1.TaJsonDeserialize(json, opds2_1.OPDSFeed);
335 return this.publicationsOPDSfeed;
336 };
337 return Server;
338}());
339exports.Server = Server;
340//# sourceMappingURL=server.js.map
\No newline at end of file