generated from nathanwoodburn/python-webserver-template
fix: Remove scripts from html to stop redirects or other random things
All checks were successful
Build Docker / BuildImage (push) Successful in 30s
All checks were successful
Build Docker / BuildImage (push) Successful in 30s
This commit is contained in:
@@ -1,40 +1,40 @@
|
|||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
// Get references to elements
|
// Get references to elements
|
||||||
const curlButton = document.getElementById('curl');
|
const curlButton = document.getElementById('curl');
|
||||||
const curlUrlInput = document.getElementById('curl-url');
|
const curlUrlInput = document.getElementById('curl-url');
|
||||||
const resultsContainer = document.getElementById('curl-results');
|
const resultsContainer = document.getElementById('curl-results');
|
||||||
|
|
||||||
// Add click event listener to the button
|
// Add click event listener to the button
|
||||||
curlButton.addEventListener('click', function() {
|
curlButton.addEventListener('click', function () {
|
||||||
// Get the URL from the input
|
// Get the URL from the input
|
||||||
const url = curlUrlInput.value.trim();
|
const url = curlUrlInput.value.trim();
|
||||||
|
|
||||||
// Validate URL
|
// Validate URL
|
||||||
if (!url) {
|
if (!url) {
|
||||||
showMessage('Please enter a URL', 'error');
|
showMessage('Please enter a URL', 'error');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the url
|
// Update the url
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
params.append('url', url);
|
params.append('url', url);
|
||||||
history.pushState(null, null, `?${params.toString()}`);
|
history.pushState(null, null, `?${params.toString()}`);
|
||||||
|
|
||||||
// Show loading state
|
// Show loading state
|
||||||
curlButton.disabled = true;
|
curlButton.disabled = true;
|
||||||
curlButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Loading...';
|
curlButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Loading...';
|
||||||
|
|
||||||
// Clear previous results
|
// Clear previous results
|
||||||
resultsContainer.innerHTML = '';
|
resultsContainer.innerHTML = '';
|
||||||
showMessage('Fetching content...', 'info');
|
showMessage('Fetching content...', 'info');
|
||||||
|
|
||||||
// Make the request
|
// Make the request
|
||||||
handleCurlRequest(url);
|
handleCurlRequest(url);
|
||||||
});
|
});
|
||||||
// Add enter key listener to input
|
// Add enter key listener to input
|
||||||
curlUrlInput.addEventListener('keyup', function(event) {
|
curlUrlInput.addEventListener('keyup', function (event) {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
curlButton.click();
|
curlButton.click();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -43,22 +43,22 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
* @param {string} url - The URL to curl
|
* @param {string} url - The URL to curl
|
||||||
*/
|
*/
|
||||||
function handleCurlRequest(url) {
|
function handleCurlRequest(url) {
|
||||||
// Encode the URL for the API endpoint
|
// Encode the URL for the API endpoint
|
||||||
const encodedUrl = encodeURIComponent(url);
|
const encodedUrl = encodeURIComponent(url);
|
||||||
const apiEndpoint = `/api/v1/curl/${encodedUrl}`;
|
const apiEndpoint = `/api/v1/curl/${encodedUrl}`;
|
||||||
|
|
||||||
fetch(apiEndpoint)
|
fetch(apiEndpoint)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// Clear loading message
|
// Clear loading message
|
||||||
resultsContainer.innerHTML = '';
|
resultsContainer.innerHTML = '';
|
||||||
|
|
||||||
if (data.success === true) {
|
if (data.success === true) {
|
||||||
// Create a result card with iframe
|
// Create a result card with iframe
|
||||||
const resultCard = document.createElement('div');
|
const resultCard = document.createElement('div');
|
||||||
resultCard.className = 'card shadow border-0 rounded-lg mb-5';
|
resultCard.className = 'card shadow border-0 rounded-lg mb-5';
|
||||||
|
|
||||||
resultCard.innerHTML = `
|
resultCard.innerHTML = `
|
||||||
<div class="card-header bg-success text-white py-3 d-flex justify-content-between align-items-center">
|
<div class="card-header bg-success text-white py-3 d-flex justify-content-between align-items-center">
|
||||||
<h3 class="h5 mb-0">Result for ${escapeHtml(url)}</h3>
|
<h3 class="h5 mb-0">Result for ${escapeHtml(url)}</h3>
|
||||||
<div>
|
<div>
|
||||||
@@ -72,24 +72,26 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
resultsContainer.appendChild(resultCard);
|
resultsContainer.appendChild(resultCard);
|
||||||
|
|
||||||
// Get reference to the iframe and buttons
|
// Get reference to the iframe and buttons
|
||||||
const iframe = document.getElementById('result-iframe');
|
const iframe = document.getElementById('result-iframe');
|
||||||
const viewSourceButton = document.getElementById('view-source');
|
const viewSourceButton = document.getElementById('view-source');
|
||||||
|
|
||||||
// Create a blob URL from the HTML content
|
const cleanedHtml = removeScripts(data.result);
|
||||||
const blob = new Blob([data.result], { type: 'text/html' });
|
|
||||||
const blobUrl = URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
// Set the iframe src to the blob URL
|
// Create a blob URL from the cleaned HTML content
|
||||||
iframe.src = blobUrl;
|
const blob = new Blob([cleanedHtml], { type: 'text/html' });
|
||||||
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
|
||||||
// Add event listener to view source button
|
// Set the iframe src to the blob URL
|
||||||
viewSourceButton.addEventListener('click', function() {
|
iframe.src = blobUrl;
|
||||||
// Show source code in a modal or new window
|
|
||||||
const sourceWindow = window.open('', '_blank');
|
// Add event listener to view source button
|
||||||
sourceWindow.document.write(`
|
viewSourceButton.addEventListener('click', function () {
|
||||||
|
// Show source code in a modal or new window
|
||||||
|
const sourceWindow = window.open('', '_blank');
|
||||||
|
sourceWindow.document.write(`
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
@@ -101,44 +103,83 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
<body>${escapeHtml(data.result)}</body>
|
<body>${escapeHtml(data.result)}</body>
|
||||||
</html>
|
</html>
|
||||||
`);
|
`);
|
||||||
sourceWindow.document.close();
|
sourceWindow.document.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set up cleanup when iframe is no longer needed
|
// Set up cleanup when iframe is no longer needed
|
||||||
window.addEventListener('beforeunload', function() {
|
window.addEventListener('beforeunload', function () {
|
||||||
URL.revokeObjectURL(blobUrl);
|
URL.revokeObjectURL(blobUrl);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Show error message
|
||||||
|
showMessage(data.error || 'Failed to get content', 'error');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
showMessage(`Request failed: ${error.message}`, 'error');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
// Reset button state
|
||||||
|
curlButton.disabled = false;
|
||||||
|
curlButton.innerHTML = '<i class="bi bi-shield-check me-2"></i>HTTP Request';
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
// Show error message
|
|
||||||
showMessage(data.error || 'Failed to get content', 'error');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
showMessage(`Request failed: ${error.message}`, 'error');
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
// Reset button state
|
|
||||||
curlButton.disabled = false;
|
|
||||||
curlButton.innerHTML = '<i class="bi bi-shield-check me-2"></i>HTTP Request';
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Remove all script tags and event handlers from HTML content
|
||||||
|
* @param {string} html - The HTML content
|
||||||
|
* @returns {string} - HTML content with scripts removed
|
||||||
|
*/
|
||||||
|
function removeScripts(html) {
|
||||||
|
// Create a DOM parser to work with the HTML
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const doc = parser.parseFromString(html, 'text/html');
|
||||||
|
|
||||||
|
// Remove all script elements
|
||||||
|
const scripts = doc.getElementsByTagName('script');
|
||||||
|
while (scripts.length > 0) {
|
||||||
|
scripts[0].parentNode.removeChild(scripts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove inline event handlers from all elements
|
||||||
|
const allElements = doc.getElementsByTagName('*');
|
||||||
|
for (let i = 0; i < allElements.length; i++) {
|
||||||
|
const element = allElements[i];
|
||||||
|
const attrs = element.attributes;
|
||||||
|
const attrsToRemove = [];
|
||||||
|
|
||||||
|
// Collect all event handler attributes (on*)
|
||||||
|
for (let j = 0; j < attrs.length; j++) {
|
||||||
|
if (attrs[j].name.toLowerCase().startsWith('on')) {
|
||||||
|
attrsToRemove.push(attrs[j].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the collected attributes
|
||||||
|
attrsToRemove.forEach(attr => {
|
||||||
|
element.removeAttribute(attr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the cleaned HTML
|
||||||
|
return doc.documentElement.outerHTML;
|
||||||
|
}
|
||||||
|
/**
|
||||||
* Display a message in the results container
|
* Display a message in the results container
|
||||||
* @param {string} message - The message to display
|
* @param {string} message - The message to display
|
||||||
* @param {string} type - Message type (error, success, info)
|
* @param {string} type - Message type (error, success, info)
|
||||||
*/
|
*/
|
||||||
function showMessage(message, type) {
|
function showMessage(message, type) {
|
||||||
// Clear previous content
|
// Clear previous content
|
||||||
resultsContainer.innerHTML = '';
|
resultsContainer.innerHTML = '';
|
||||||
|
|
||||||
// Create alert element
|
// Create alert element
|
||||||
const alert = document.createElement('div');
|
const alert = document.createElement('div');
|
||||||
alert.className = `alert alert-${getAlertClass(type)} shadow-sm`;
|
alert.className = `alert alert-${getAlertClass(type)} shadow-sm`;
|
||||||
alert.innerHTML = message;
|
alert.innerHTML = message;
|
||||||
|
|
||||||
// Add the alert to the results container
|
// Add the alert to the results container
|
||||||
resultsContainer.appendChild(alert);
|
resultsContainer.appendChild(alert);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,11 +188,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
* @returns {string} - Bootstrap alert class
|
* @returns {string} - Bootstrap alert class
|
||||||
*/
|
*/
|
||||||
function getAlertClass(type) {
|
function getAlertClass(type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'error': return 'danger';
|
case 'error': return 'danger';
|
||||||
case 'success': return 'success';
|
case 'success': return 'success';
|
||||||
case 'info': default: return 'info';
|
case 'info': default: return 'info';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,21 +201,21 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
* @returns {string} - Escaped text
|
* @returns {string} - Escaped text
|
||||||
*/
|
*/
|
||||||
function escapeHtml(text) {
|
function escapeHtml(text) {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.textContent = text;
|
div.textContent = text;
|
||||||
return div.innerHTML;
|
return div.innerHTML;
|
||||||
}
|
}
|
||||||
// Check if params are present
|
// Check if params are present
|
||||||
if (window.location.search) {
|
if (window.location.search) {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const url = params.get('url');
|
const url = params.get('url');
|
||||||
if (url) {
|
if (url) {
|
||||||
// Add url to input
|
// Add url to input
|
||||||
curlUrlInput.value = url;
|
curlUrlInput.value = url;
|
||||||
// Show loading state
|
// Show loading state
|
||||||
curlButton.disabled = true;
|
curlButton.disabled = true;
|
||||||
curlButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Loading...';
|
curlButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Loading...';
|
||||||
handleCurlRequest(url);
|
handleCurlRequest(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user