This commit is contained in:
2021-10-05 12:54:12 +08:00
parent a7ebffaa49
commit 010fed101f
14 changed files with 228013 additions and 2955 deletions

101
modules/actions/dir.ejs Normal file
View File

@ -0,0 +1,101 @@
<%if(path!=="/"){path+="/"}%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Index of <%= path %></title>
<style>
body {
font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.5;
padding: 0 10px 5px
}
table {
width: 100%;
border-collapse: collapse;
font: .85em Monaco, monospace
}
tr.even {
background-color: #eee
}
th {
text-align: left
}
td,
th {
padding: .1em .25em
}
.version-wrapper {
line-height: 2.25em;
float: right
}
#version {
font-size: 1em
}
address {
text-align: right
}
</style>
</head>
<body>
<h1>Index of <%= path %></h1>
<hr />
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Size</th>
<th>Last Modified</th>
</tr>
</thead>
<tbody>
<%
files.sort((fileA,fileB) => {
let nameA = fileA.path.toUpperCase();
let nameB = fileB.path.toUpperCase();
if(fileA.type === "directory") return -1;
else if(fileB.type === "directory") return 1;
else if(nameA<nameB) return -1;
else if(nameA>nameB) return 1;
else return 0;
})
if(path!=="/"){
files.splice(0,0,{
path: "..",
type: "directory",
});
}
%>
<% files.forEach((file,index) => { let name = `${file.path.replace(path,"")}${file.type==="directory"?"/":""}` %>
<tr class="<%= index%2===0?"even":"odd" %> ">
<td><a title="<%= name %>" href="<%= name %>"><%= name %></a></td>
<td><%= file.type==="directory"?"-":file.contentType %></td>
<td><%= file.type==="directory"?"-":(()=>{
if(file.size<=1024) return file.size+" B";
else if(file.size<=1024*1024) return (file.size/1024).toFixed(2)+" KiB";
else return (file.size/1024/1024).toFixed(2)+" MB";
})() %></td>
<td><%= file.type==="directory"?"-":new Date(Date.parse(file.lastModified)).toISOString()
%></td>
</tr>
<% }) %>
</tbody>
</table>
<hr />
<address><%= package %> </address>
<address>186526 Edge/1.20.1</address>
</body>
</html>

View File

@ -99,4 +99,14 @@ async function serveDirectoryMetadata(req, res) {
res.send(metadata);
}
export async function getMetadataMoreEasier(req,res) {
const stream = await getPackage(req.packageName, req.packageVersion, req.log);
const filename = req.filename.slice(0, -1) || '/';
const entries = await findMatchingEntries(stream, filename);
const metadata = getMetadata(entries[filename], entries);
return metadata;
}
export default asyncHandler(serveDirectoryMetadata);

View File

@ -29,7 +29,6 @@ export default function serveMainPage(req, res) {
res
.set({
'Cache-Control': 'public, max-age=14400', // 4 hours
'Cache-Tag': 'main'
})
.send(html);

View File

@ -1,15 +1,11 @@
import cors from 'cors';
import express from 'express';
import morgan from 'morgan';
import ejs from 'ejs';
import serveDirectoryBrowser from './actions/serveDirectoryBrowser.js';
import serveDirectoryMetadata from './actions/serveDirectoryMetadata.js';
import serveFileBrowser from './actions/serveFileBrowser.js';
import serveDirectoryMetadata, { getMetadataMoreEasier } from './actions/serveDirectoryMetadata.js';
import serveFileMetadata from './actions/serveFileMetadata.js';
import serveFile from './actions/serveFile.js';
import serveMainPage from './actions/serveMainPage.js';
import serveModule from './actions/serveModule.js';
import serveStats from './actions/serveStats.js';
import allowQuery from './middleware/allowQuery.js';
import findEntry from './middleware/findEntry.js';
@ -21,6 +17,117 @@ import validatePackagePathname from './middleware/validatePackagePathname.js';
import validatePackageName from './middleware/validatePackageName.js';
import validatePackageVersion from './middleware/validatePackageVersion.js';
const renderFolderBrowser = async (req, res, next) => {
res.set({
'Cache-Control': 'public, max-age=14400', // 4 hours
'Cache-Tag': 'browse'
});
const html = await ejs.render(`<%if(path!=="/"){path+="/"}%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Index of <%= path %></title>
<style>
body {
font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.5;
padding: 0 10px 5px
}
table {
width: 100%;
border-collapse: collapse;
font: .85em Monaco, monospace
}
tr.even {
background-color: #eee
}
th {
text-align: left
}
td,
th {
padding: .1em .25em
}
.version-wrapper {
line-height: 2.25em;
float: right
}
#version {
font-size: 1em
}
address {
text-align: right
}
</style>
</head>
<body>
<h1>Index of <%= path %></h1>
<hr />
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Size</th>
<th>Last Modified</th>
</tr>
</thead>
<tbody>
<%
files.sort((fileA,fileB) => {
let nameA = fileA.path.toUpperCase();
let nameB = fileB.path.toUpperCase();
if(fileA.type === "directory") return -1;
else if(fileB.type === "directory") return 1;
else if(nameA<nameB) return -1;
else if(nameA>nameB) return 1;
else return 0;
})
if(path!=="/"){
files.splice(0,0,{
path: "..",
type: "directory",
});
}
%>
<% files.forEach((file,index) => { let name = file.path.replace(path,"")+(file.type==="directory"?"/":""); %>
<tr class="<%= index%2===0?"even":"odd" %> ">
<td><a title="<%= name %>" href="<%= name %>"><%= name %></a></td>
<td><%= file.type==="directory"?"-":file.contentType %></td>
<td><%= file.type==="directory"?"-":(()=>{
if(file.size<=1024) return file.size+" B";
else if(file.size<=1024*1024) return (file.size/1024).toFixed(2)+" KiB";
else return (file.size/1024/1024).toFixed(2)+" MB";
})() %></td>
<td><%= file.type==="directory"?"-":new Date(Date.parse(file.lastModified)).toISOString()
%></td>
</tr>
<% }) %>
</tbody>
</table>
<hr />
<address><%= package %> </address>
<address>186526 Edge/1.20.1</address>
</body>
</html>`, Object.assign({ package: `${req.packageName}@${req.packageVersion}` }, await getMetadataMoreEasier(req, res)), { async: true });
res.send(html);
};
function createApp(callback) {
const app = express();
callback(app);
@ -33,20 +140,17 @@ export default function createServer() {
app.enable('trust proxy');
app.enable('strict routing');
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'));
}
app.use(cors());
app.use(express.static('public', { maxAge: '1y' }));
app.use(requestLog);
app.get('/', serveMainPage);
app.get('/api/stats', serveStats);
app.use(redirectLegacyURLs);
app.all('/', (req, res) => {
res.send("To infinity and beyond!");
})
app.use(
'/browse',
createApp(app => {
@ -58,16 +162,13 @@ export default function createServer() {
validatePackagePathname,
validatePackageName,
validatePackageVersion,
serveDirectoryBrowser
renderFolderBrowser,
);
app.get(
'*',
noQuery(),
validatePackagePathname,
validatePackageName,
validatePackageVersion,
serveFileBrowser
(req, res, next) => {
res.redirect(req.path.replace("/browser", ""));
}
);
})
);
@ -132,9 +233,12 @@ export default function createServer() {
});
// Send old */ requests to the new /browse UI.
app.get('*/', (req, res) => {
res.redirect(302, '/browse' + req.url);
});
app.get('*/', noQuery(),
validatePackagePathname,
validatePackageName,
validatePackageVersion,
renderFolderBrowser
);
app.get(
'*',

View File

@ -5,8 +5,8 @@
export default function asyncHandler(handler) {
return (req, res, next) => {
Promise.resolve(handler(req, res, next)).catch(error => {
req.log.error(`Unexpected error in ${handler.name}!`);
req.log.error(error.stack);
console.error(`Unexpected error in ${handler.name}!`);
console.error(error.stack);
next(error);
});