UNPKG

3.48 kBJavaScriptView Raw
1/*
2 * Copyright 2018 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12
13'use strict';
14
15const mime = require('mime');
16const path = require('path');
17const { debug } = require('@adobe/helix-log');
18const {
19 isCheckedOut, resolveBlob, createBlobReadStream, determineRefPathName,
20} = require('./git');
21const { resolveRepositoryPath } = require('./utils');
22
23/**
24 * Export the raw content handler (express middleware) through a parameterizable function
25 *
26 * @param {object} options configuration hash
27 * @returns {function(*, *, *)} handler function
28 */
29function createMiddleware(options) {
30 /**
31 * Express middleware handling raw content requests
32 *
33 * @param {Request} req Request object
34 * @param {Response} res Response object
35 * @param {callback} next next middleware in chain
36 */
37 return async (req, res, next) => {
38 const { owner } = req.params;
39 const repoName = req.params.repo;
40 let refName = req.params.ref;
41 let fpath = req.params[0];
42
43 let repPath = resolveRepositoryPath(options, owner, repoName);
44 // temporary fix until isomorphic git can handle windows paths
45 // see https://github.com/isomorphic-git/isomorphic-git/issues/783
46 repPath = repPath.replace(/\\/g, '/');
47
48 // issue: #53: handle branch names containing '/' (e.g. 'foo/bar')
49 const parsed = await determineRefPathName(repPath, `${req.params.ref}/${req.params[0]}`);
50 if (parsed) {
51 refName = parsed.ref;
52 fpath = parsed.pathName;
53 }
54
55 // issue #68: lenient handling of redundant slashes in path
56 fpath = path.normalize(fpath);
57 // temporary fix until isomorphic git can handle windows paths
58 // see https://github.com/isomorphic-git/isomorphic-git/issues/783
59 fpath = fpath.replace(/\\/g, '/');
60
61 // remove leading slash
62 if (fpath.length && fpath[0] === '/') {
63 fpath = fpath.substr(1);
64 }
65
66 // project-helix/#187: serve modified content only if the requested ref is currently checked out
67 isCheckedOut(repPath, refName)
68 .then((serveUncommitted) => resolveBlob(repPath, refName, fpath, serveUncommitted))
69 .then((oid) => {
70 const mimeType = mime.getType(fpath) || 'text/plain';
71 res.writeHead(200, {
72 'Content-Type': mimeType,
73 ETag: oid,
74 // TODO: review cache-control header
75 'Cache-Control': 'max-age=0, private, must-revalidate',
76 });
77 createBlobReadStream(repPath, oid)
78 .then((stream) => stream.pipe(res));
79 })
80 .catch((err) => {
81 // TODO: use generic errors
82 if (err.code === 'TreeOrBlobNotFoundError' || err.code === 'ResolveRefError') {
83 debug(`[rawHandler] resource not found: ${err.message}`);
84 res.status(404).send('not found.');
85 } else {
86 debug(`[rawHandler] code: ${err.code} message: ${err.message} stack: ${err.stack}`);
87 next(err);
88 }
89 });
90 };
91}
92module.exports = createMiddleware;