import { englishPage } from "./language"
// Instantiate the WebAssembly module with 32MB of memory.
const wasm = require('./resizer.wasm', {memory: new WebAssembly.Memory({initial: 1024})})
const resizer = wasm.exports
async function handleRequest(request) {
let {pathname, host} = new URL(request.url.toLowerCase())
if (pathname.endsWith('/')) pathname = pathname.substring(0, pathname.length - 1)
if (pathname === '/wasm-resizer.html') {
let page = englishPage(request) ? HOMEPAGE_EN : HOMEPAGE
page = page.replace('$[{host}]', host)
return new Response(page, {headers: {"Content-Type": "text/html; charset=utf-8"}})
} else {
return handleResize(request)
}
}
async function handleResize(request) {
const requestJSON = await request.json()
if (!requestJSON.url) {
return new Response('Please enter the image URL!')
}
const width = parseInt(requestJSON.width)
if (isNaN(width) || width <= 0) {
return new Response('Please enter a valid width!')
}
const headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
'Accept': '*/*'}
let response = await fetch(requestJSON.url, {cdnProxy: false, headers})
// Check if the response is an image. If not, we'll just return it.
let type = response.headers.get("Content-Type") || ""
if (!type.startsWith("image/")) {
return new Response('The response is not an image!')
}
// OK, we're going to resize. First, read the image data into memory.
let bytes = new Uint8Array(await response.arrayBuffer())
// Call our WebAssembly module's init() function to allocate space for the image.
let ptr = resizer.init(bytes.byteLength)
// Copy the image into WebAssembly memory.
const memoryBytes = new Uint8Array(wasm.env.memory.buffer)
memoryBytes.set(bytes, ptr)
// Call our WebAssembly module's resize() function to perform the resize.
let newSize = resizer.resize(bytes.byteLength, width)
if (newSize == 0) {
return new Response(`Resizing failed!`);
}
// Extract the result bytes from WebAssembly memory.
let resultBytes = memoryBytes.slice(ptr, ptr + newSize)
// Create a new response with the image bytes. Our resizer module always
// outputs JPEG regardless of input type, so change the header.
return new Response(resultBytes.buffer, {headers: {"Content-Type": "image/jpeg"}})
}
const HOMEPAGE_EN = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Resize Image</title>
<style>
body {
background-color: #f3f3f3;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, sans-serif;
}
.container {
border: 1px solid #ccc;
padding: 20px;
background-color: #fff;
}
.input-container {
margin-bottom: 20px;
}
.input-container label {
display: block;
margin-bottom: 5px;
}
.input-container input {
width: 420px;
padding: 5px;
font-size: 14px;
}
.button {
background-color: #0088cc;
color: #fff;
padding: 10px;
border: none;
cursor: pointer;
border-radius: 4px;
font-size: 14px;
}
.image-container {
margin-top: 20px;
}
.image-container img {
max-width: 100%;
height: auto;
}
</style>
</head>
<body>
<div class="container">
<div class="input-container">
<label for="imageUrl">Original Image URL (Our nodes may not be able to access it)</label>
<input type="text" id="imageUrl" value="http://$[{host}]/ECA-test/pet-shop-website-template/img/about.jpg">
</div>
<div class="input-container">
<label for="imageWidth">Resized Width (Must be less than the original width)</label>
<input type="text" id="imageWidth" value="365">
</div>
<button class="button" onclick="adjustImageSize()">Resize</button>
<div class="image-container" id="resultContainer"></div>
</div>
<script>
function adjustImageSize() {
var resultContainer = document.getElementById("resultContainer");
resultContainer.innerHTML = "";
var imageUrl = document.getElementById("imageUrl").value;
var imageWidth = document.getElementById("imageWidth").value;
var data = {
url: imageUrl,
width: imageWidth
};
fetch("/wasm-resizer", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => {
if (response.headers.has("content-type") && response.headers.get("content-type").startsWith("image/")) {
return response.blob();
} else {
return response.text();
}
})
.then(result => {
if (result instanceof Blob) {
var url = URL.createObjectURL(result);
var image = document.createElement("img");
image.src = url;
var resultContainer = document.getElementById("resultContainer");
resultContainer.innerHTML = "";
resultContainer.appendChild(image);
} else {
var resultContainer = document.getElementById("resultContainer");
resultContainer.innerHTML = result;
}
})
.catch(error => {
alert(error);
});
}
</script>
</body>
</html>
`
addEventListener("fetch", event => {
return event.respondWith(handleRequest(event.request))
})