-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
140 lines (117 loc) · 4.75 KB
/
server.js
File metadata and controls
140 lines (117 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import express from "express";
import { advanced_readability_cleanup, get_readability_article } from "./cleanup.js";
import { HTML2Text } from "./convert_htm_to_plaintext.js";
import packageJson from "./package.json" with { type: "json" };
import * as Sentry from "@sentry/node";
// Suppress noisy CSS parsing warnings from JSDOM
const originalConsoleError = console.error;
console.error = (...args) => {
if (args[0]?.includes?.('Could not parse CSS stylesheet')) {
return; // Suppress CSS parsing errors
}
originalConsoleError.apply(console, args);
};
const app = express();
// Enable JSON body parsing for POST requests
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
// Sentry prefix: START
Sentry.init({
dsn: "https://754bd6621282bfc97d64d3dc12fba591@o176103.ingest.us.sentry.io/4506971631517696",
integrations: [
// enable HTTP calls tracing
new Sentry.Integrations.Http({ tracing: true }),
// enable Express.js middleware tracing
new Sentry.Integrations.Express({ app }),
],
// Performance Monitoring
tracesSampleRate: 0.1, // Capture 10% of the transactions
});
// The request handler must be the first middleware on the app
app.use(Sentry.Handlers.requestHandler());
// TracingHandler creates a trace for every incoming request
app.use(Sentry.Handlers.tracingHandler());
// Sentry prefix: END
app.get("/cleanup", async (req, res) => {
const { url } = req.query;
const startTime = Date.now();
console.log(`[${new Date().toISOString()}] GET /cleanup - Starting: ${url}`);
try {
console.log(`[${new Date().toISOString()}] Calling advanced_readability_cleanup...`);
const html = await advanced_readability_cleanup(url);
console.log(`[${new Date().toISOString()}] ✓ Cleanup done (${html.length} chars)`);
console.log(`[${new Date().toISOString()}] Getting readability article...`);
const readabilityResult = await get_readability_article(url);
console.log(`[${new Date().toISOString()}] ✓ Readability done`);
const duration = Date.now() - startTime;
console.log(`[${new Date().toISOString()}] ✓ Complete in ${duration}ms`);
// Send the cleaned up content as the response with metadata
res.send({
html: html,
text: HTML2Text(html),
title: readabilityResult.title,
excerpt: readabilityResult.excerpt,
byline: readabilityResult.byline,
siteName: readabilityResult.siteName
});
} catch (e) {
const duration = Date.now() - startTime;
console.log(`[${new Date().toISOString()}] ✗ Error after ${duration}ms: ${e.message}`);
res.status(500).send(e.message);
}
});
// POST endpoint that accepts HTML content directly
app.post("/cleanup", async (req, res) => {
const { url, htmlContent } = req.body;
const startTime = Date.now();
console.log(`[${new Date().toISOString()}] POST /cleanup - Starting: ${url} (${htmlContent?.length || 0} bytes HTML)`);
if (!htmlContent) {
return res.status(400).send("htmlContent is required");
}
try {
console.log(`[${new Date().toISOString()}] Calling advanced_readability_cleanup...`);
const html = await advanced_readability_cleanup(url, htmlContent);
console.log(`[${new Date().toISOString()}] ✓ Cleanup done (${html.length} chars)`);
console.log(`[${new Date().toISOString()}] Getting readability article...`);
const readabilityResult = await get_readability_article(url, htmlContent);
console.log(`[${new Date().toISOString()}] ✓ Readability done`);
const duration = Date.now() - startTime;
console.log(`[${new Date().toISOString()}] ✓ Complete in ${duration}ms`);
// Send the cleaned up content as the response with metadata
res.send({
html: html,
text: HTML2Text(html),
title: readabilityResult.title,
excerpt: readabilityResult.excerpt,
byline: readabilityResult.byline,
siteName: readabilityResult.siteName
});
} catch (e) {
const duration = Date.now() - startTime;
console.log(`[${new Date().toISOString()}] ✗ Error after ${duration}ms: ${e.message}`);
res.status(500).send(e.message);
}
});
app.get("/ping", async (req, res) => {
res.send("pong");
});
app.get("/debug-sentry", function mainHandler() {
throw new Error("My first Sentry error!");
});
// ----> Sentry Appendix: START
app.use(Sentry.Handlers.errorHandler());
// Optional fallthrough error handler
app.use(function onError(err, req, res, next) {
// The error id is attached to `res.sentry` to be returned
// and optionally displayed to the user for support.
res.statusCode = 500;
res.end(res.sentry + "\n");
});
// ----> Sentry Appendix: END
// Start the server
const port = 3456;
app.listen(port, () => {
console.log(
`Server (${packageJson.version}) is running on http://localhost:${port}`,
);
});