@hanivanrizky/nestjs-html-parser
Version:
โ ๏ธ ARCHIVED - This package is no longer maintained. Please migrate to @hanivanrizky/nestjs-xpath-parser (https://github.com/Hanivan/nestjs-xpath-parser)
230 lines โข 8.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.testUrlWithRobustConfig = testUrlWithRobustConfig;
exports.demonstrateSSLAndErrorHandling = demonstrateSSLAndErrorHandling;
const html_parser_service_1 = require("../html-parser.service");
async function demonstrateSSLAndErrorHandling(verbose = false) {
const parser = new html_parser_service_1.HtmlParserService();
console.log('๐ง SSL and Error Handling Demo');
console.log('='.repeat(50));
// Test URLs with different types of issues
const testCases = [
{
name: 'Valid HTTPS Site',
url: 'https://httpbin.org/html',
config: { verbose },
},
{
name: 'Self-Signed Certificate',
url: 'https://self-signed.badssl.com/',
config: {
rejectUnauthorized: false,
retryOnErrors: { ssl: true },
verbose,
},
},
{
name: 'Expired Certificate',
url: 'https://expired.badssl.com/',
config: {
ignoreSSLErrors: true,
verbose,
},
},
{
name: 'Wrong Host Certificate',
url: 'https://wrong.host.badssl.com/',
config: {
rejectUnauthorized: false,
retryOnErrors: { ssl: true },
retries: 2,
verbose,
},
},
{
name: 'Dead Domain (DNS Failure)',
url: 'https://this-domain-definitely-does-not-exist-12345.com',
config: {
retries: 2,
retryDelay: 1000,
retryOnErrors: { dns: true },
timeout: 5000,
verbose,
},
},
{
name: 'Connection Timeout',
url: 'https://httpbin.org/delay/10',
config: {
timeout: 3000,
retries: 2,
retryOnErrors: { timeout: true },
verbose,
},
},
{
name: 'Robust Configuration (Handle Most Errors)',
url: 'https://httpbin.org/status/503', // Service unavailable
config: {
rejectUnauthorized: false,
ignoreSSLErrors: false,
timeout: 10000,
retries: 3,
retryDelay: 2000,
retryOnErrors: {
ssl: true,
timeout: true,
dns: true,
connectionRefused: true,
},
verbose,
},
},
];
const results = [];
for (const testCase of testCases) {
console.log(`\n๐งช Testing: ${testCase.name}`);
console.log(`๐ URL: ${testCase.url}`);
if (verbose) {
console.log(`๐ง Config:`, testCase.config);
}
try {
const startTime = Date.now();
const response = await parser.fetchHtml(testCase.url, testCase.config);
const duration = Date.now() - startTime;
// Try to extract title
const title = parser.extractSingle(response.data, '//title/text()', 'xpath', undefined, { verbose: false });
console.log(`โ
Success! (${duration}ms)`);
console.log(`๐ Status: ${response.status} ${response.statusText}`);
console.log(`๐ Title: ${title || 'No title found'}`);
console.log(`๐ Content length: ${response.data.length} characters`);
results.push({
url: testCase.url,
success: true,
title: title || undefined,
});
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
// Extract error type from enhanced error message
const errorTypeMatch = errorMessage.match(/Error type: (\w+)/);
const errorType = errorTypeMatch ? errorTypeMatch[1] : 'unknown';
console.log(`โ Failed: ${errorType}`);
console.log(`๐ Error: ${errorMessage}`);
results.push({
url: testCase.url,
success: false,
error: errorMessage,
errorType,
});
}
}
// Summary
console.log('\n๐ SUMMARY RESULTS');
console.log('='.repeat(40));
const successful = results.filter((r) => r.success);
const failed = results.filter((r) => !r.success);
console.log(`โ
Successful: ${successful.length}/${results.length}`);
console.log(`โ Failed: ${failed.length}/${results.length}`);
if (successful.length > 0) {
console.log('\n๐ฏ Successful Requests:');
successful.forEach((result, index) => {
console.log(` ${index + 1}. ${result.title || 'No title'} - ${result.url}`);
});
}
if (failed.length > 0) {
console.log('\n๐ฅ Failed Requests by Error Type:');
const errorGroups = failed.reduce((groups, result) => {
const type = result.errorType || 'unknown';
if (!groups[type])
groups[type] = [];
groups[type].push(result);
return groups;
}, {});
Object.entries(errorGroups).forEach(([errorType, errors]) => {
console.log(`\n ๐ด ${errorType.toUpperCase()} (${errors.length})`);
errors.forEach((error, index) => {
console.log(` ${index + 1}. ${error.url}`);
});
});
}
// Recommendations
console.log('\n๐ก RECOMMENDATIONS FOR COMMON ISSUES');
console.log('='.repeat(45));
console.log('๐ SSL Certificate Issues:');
console.log(' - Use rejectUnauthorized: false for self-signed certificates');
console.log(' - Use ignoreSSLErrors: true for completely broken SSL (use with caution)');
console.log(' - Enable retryOnErrors.ssl: true for transient SSL issues');
console.log('\n๐ Dead Domains:');
console.log(' - Enable retryOnErrors.dns: true for temporary DNS issues');
console.log(' - Reduce timeout for faster failure detection');
console.log(' - Use domain health checking before scraping');
console.log('\nโฑ๏ธ Timeout Issues:');
console.log(' - Increase timeout value for slow sites');
console.log(' - Enable retryOnErrors.timeout: true');
console.log(' - Use proxy rotation for better performance');
console.log('\n๐ก๏ธ Connection Issues:');
console.log(' - Enable retryOnErrors.connectionRefused: true');
console.log(' - Use different user agents to avoid blocking');
console.log(' - Implement proxy rotation for resilience');
}
// Utility function to test a single URL with robust configuration
async function testUrlWithRobustConfig(url, verbose = false) {
const parser = new html_parser_service_1.HtmlParserService();
const robustConfig = {
// SSL handling
rejectUnauthorized: false,
ignoreSSLErrors: false,
// Timeouts and retries
timeout: 15000,
retries: 5,
retryDelay: 2000,
maxRedirects: 10,
// Retry on all common error types
retryOnErrors: {
ssl: true,
timeout: true,
dns: true,
connectionRefused: true,
},
// User agent rotation
useRandomUserAgent: true,
// Additional headers
headers: {
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
},
verbose,
};
try {
const response = await parser.fetchHtml(url, robustConfig);
const title = parser.extractSingle(response.data, '//title/text()');
return {
url,
success: true,
title: title || undefined,
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
const errorTypeMatch = errorMessage.match(/Error type: (\w+)/);
return {
url,
success: false,
error: errorMessage,
errorType: errorTypeMatch ? errorTypeMatch[1] : 'unknown',
};
}
}
// Run the demonstration if this file is executed directly
if (require.main === module) {
// Check for verbose flag in command line arguments
const verbose = process.argv.includes('--verbose') || process.argv.includes('-v');
demonstrateSSLAndErrorHandling(verbose)
.then(() => console.log('\n๐ง SSL and error handling demo completed!'))
.catch(console.error);
}
//# sourceMappingURL=ssl-and-dead-domains.js.map