So far I could manage to generate a vanilla JS script from the above linked project to gain Blob API support. This is what I got:
function mergeArrays(...arrays) {
const out = new Uint8Array(arrays.reduce((total, arr) => total + arr.length, 0));
let offset = 0;
for (const arr of arrays) {
out.set(arr, offset);
offset += arr.length;
}
return out;
}
var _a;
/** @internal */ const $$buffers = Symbol('buffers');
/** @internal */ const $$merged = Symbol('merged');
/** @internal */ const $$size = Symbol('size');
const $$options = Symbol('options');
let encoder;
class BlobImpl {
constructor(blobParts = [], options = {}) {
/** @internal */ this[_a] = [];
const { endings } = this[$$options] = options;
if (endings !== undefined && endings !== 'transparent') {
throw new TypeError('only transparent endings are supported');
}
for (let blobPart of blobParts) {
if (typeof blobPart === 'string') {
if (!encoder) {
encoder = new TextEncoder();
}
this[$$buffers].push(encoder.encode(blobPart));
continue;
}
if (blobPart instanceof Uint8Array) {
this[$$buffers].push(blobPart);
continue;
}
if (ArrayBuffer.isView(blobPart)) {
blobPart = blobPart.buffer;
}
if (blobPart instanceof ArrayBuffer) {
this[$$buffers].push(new Uint8Array(blobPart));
continue;
}
if (blobPart instanceof BlobImpl) {
this[$$buffers].push(...blobPart[$$buffers]);
}
}
this[$$size] = this[$$buffers].reduce((size, buf) => size + buf.length, 0);
}
get size() {
return this[$$size];
}
get type() {
return this[$$options].type || '';
}
/** @internal */ get [(_a = $$buffers, $$merged)]() {
return mergeArrays(...this[$$buffers]);
}
slice(start = 0, end = this[$$size], contentType = '') {
if (start < 0) {
start = Math.max(this[$$size] + end, 0);
}
else {
start = Math.min(start, this[$$size]);
}
if (end < 0) {
end = Math.max(this[$$size] + end, 0);
}
else {
end = Math.min(end, this[$$size]);
}
if (Array.from(contentType, (_, i) => contentType.charCodeAt(i)).some((c) => c < 0x20 || 0x7e < c)) {
contentType = '';
}
else {
contentType = String.prototype.toLowerCase.call(contentType);
}
const newParts = [];
let offset = 0;
for (const buf of this[$$buffers]) {
const sum = offset + buf.length;
if (sum < start) {
continue;
}
if (!newParts.length) {
if (sum < end) {
newParts.push(buf.slice(start - offset, end - offset));
break;
}
newParts.push(buf.slice(start - offset));
}
if (sum < end) {
newParts.push(buf.slice(0, end - offset));
break;
}
newParts.push(buf);
}
return new BlobImpl(newParts, { type: contentType });
}
stream() {
return new ReadableStream({
type: 'bytes',
start: (controller) => {
for (const buf of this[$$buffers]) {
controller.enqueue(buf);
}
controller.close();
},
});
}
text() {
return Promise.resolve(new TextDecoder().decode(this[$$merged]));
}
arrayBuffer() {
return Promise.resolve(this[$$merged].buffer);
}
}
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
/**
* Respond to the request
* @param {Request} request
*/
async function handleRequest(request) {
var myHeaders = new Headers();
myHeaders.append('Cookie', '__cfduid=redacted; __cfruid=metoo');
image = await fetch('https://http.cat/100');
var formdata = new FormData();
formdata.append('asd.png', new BlobImpl(image, {type: 'image/png'}), 'asd.png');
formdata.append('payload_json', '{"content": "test"}');
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata,
redirect: 'follow'
};
aaa = await fetch('https://httpbin.org/anything', requestOptions);
return new Response(JSON.stringify(await aaa.json()), {status: 200})
}
I assume instead of new BlobImpl(image, {type: 'image/png'})
I should have new BlobImpl(await image.text(), {type: 'image/png'})
. Well, it throws a warn that the representation might be wrong then, though it seems to be able to produce a valid representation of the image. Though in this case my worker gets a timeout. I guess because this impl is too slow for my image.
Any workarounds? I personally wouldn’t care if it would be extremely hacky, but it’s really disappointing me that I can’t solve that. Discord’s webhook API works the way as it is. And in order to be able to post images, I must use this format.