import * as asserts from '@std/assert'; import * as fs from '@std/fs'; import * as path from '@std/path'; import { EPHEMERAL_SERVER, get_ephemeral_listen_server } from './helpers.ts'; import { ensureFile } from '@std/fs/ensure-file'; Deno.test({ name: 'GET static file', permissions: { env: true, read: true, write: true, net: true }, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); try { Deno.chdir('./tests/www'); test_server_info = await get_ephemeral_listen_server(); const response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/test.txt`, { method: 'GET' }); const body = await response.text(); asserts.assert(response.ok); asserts.assert(body); asserts.assertEquals(body, 'this is a test\n'); } finally { Deno.chdir(cwd); if (test_server_info) { await test_server_info?.server?.stop(); } } } }); Deno.test({ name: 'HEAD static file', permissions: { env: true, read: true, write: true, net: true }, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); try { Deno.chdir('./tests/www'); test_server_info = await get_ephemeral_listen_server(); const response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/test.txt`, { method: 'HEAD' }); asserts.assert(response.ok); asserts.assert(response.headers); asserts.assertEquals(response.headers.get('Content-Length'), '15'); } finally { Deno.chdir(cwd); if (test_server_info) { await test_server_info?.server?.stop(); } } } }); Deno.test({ name: 'OPTIONS static file', permissions: { env: true, read: true, write: true, net: true }, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); const PREVIOUS_PUT_PATHS_ALLOWED = Deno.env.get('SERVERUS_PUT_PATHS_ALLOWED'); const PREVIOUS_DELETE_PATHS_ALLOWED = Deno.env.get('SERVERUS_DELETE_PATHS_ALLOWED'); try { Deno.chdir('./tests/www'); Deno.env.delete('SERVERUS_PUT_PATHS_ALLOWED'); test_server_info = await get_ephemeral_listen_server(); const response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/test.txt`, { method: 'OPTIONS' }); await response.text(); asserts.assert(response.ok); asserts.assert(response.headers); asserts.assertEquals(response.headers.get('Allow'), ['GET', 'HEAD', 'OPTIONS'].join(',')); await test_server_info.server.stop(); Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', '.'); Deno.env.set('SERVERUS_DELETE_PATHS_ALLOWED', '.'); test_server_info = await get_ephemeral_listen_server(); const expanded_response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/test.txt`, { method: 'OPTIONS' }); await expanded_response.text(); asserts.assert(expanded_response.ok); asserts.assert(expanded_response.headers); asserts.assertEquals(expanded_response.headers.get('Allow'), ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'PUT'].join(',')); } finally { Deno.chdir(cwd); if (PREVIOUS_PUT_PATHS_ALLOWED) { Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', PREVIOUS_PUT_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_PUT_PATHS_ALLOWED'); } if (PREVIOUS_DELETE_PATHS_ALLOWED) { Deno.env.set('SERVERUS_DELETE_PATHS_ALLOWED', PREVIOUS_DELETE_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_DELETE_PATHS_ALLOWED'); } if (test_server_info) { await test_server_info?.server?.stop(); } } } }); Deno.test({ name: 'DISallow PUT to static files if SERVERUS_PUT_PATHS_ALLOWED is UNset', permissions: { env: true, read: true, write: true, net: true }, sanitizeResources: false, sanitizeOps: false, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); const PREVIOUS_PUT_PATHS_ALLOWED = Deno.env.get('SERVERUS_PUT_PATHS_ALLOWED'); try { Deno.chdir('./tests/www'); Deno.env.delete('SERVERUS_PUT_PATHS_ALLOWED'); test_server_info = await get_ephemeral_listen_server(); const put_body = new FormData(); put_body.append('file', new File(['this is a test PUT upload'], 'test_put_upload.txt')); // Sending a single file const put_response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/files/test_put_upload.txt`, { method: 'PUT', body: put_body }); asserts.assert(!put_response.ok); asserts.assertEquals(put_response.status, 400); } finally { Deno.chdir(cwd); if (PREVIOUS_PUT_PATHS_ALLOWED) { Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', PREVIOUS_PUT_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_PUT_PATHS_ALLOWED'); } if (test_server_info) { await test_server_info?.server?.stop(); } } } }); Deno.test({ name: 'allow PUT to static files if SERVERUS_PUT_PATHS_ALLOWED is set', permissions: { env: true, read: true, write: true, net: true }, sanitizeResources: false, sanitizeOps: false, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); const PREVIOUS_PUT_PATHS_ALLOWED = Deno.env.get('SERVERUS_PUT_PATHS_ALLOWED'); try { Deno.chdir('./tests/www'); Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', path.join(Deno.cwd(), 'files')); test_server_info = await get_ephemeral_listen_server(); const put_body = new FormData(); let test_file: File | undefined = new File(['this is a test PUT upload'], 'test_put_upload.txt'); put_body.append('file', test_file); // Sending a single file const put_response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/files/test_put_upload.txt`, { method: 'PUT', body: put_body }); asserts.assert(put_response.ok); const put_response_body = await put_response.json(); asserts.assert(put_response_body); asserts.assert(put_response_body.written); asserts.assertEquals( put_response_body.written?.[0], `http://${test_server_info.hostname}:${test_server_info.port}/files/test_put_upload.txt` ); put_body.delete('file'); test_file = undefined; const get_response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/files/test_put_upload.txt`, { method: 'GET' }); asserts.assert(get_response.ok); asserts.assert(get_response.body); const local_download_path = path.join(Deno.cwd(), 'files', 'test_put_upload.txt-downloaded'); await ensureFile(local_download_path); const file = await Deno.open(local_download_path, { truncate: true, write: true }); await get_response.body.pipeTo(file.writable); const download_content = await Deno.readTextFile(local_download_path); asserts.assert(download_content); asserts.assertEquals(download_content, 'this is a test PUT upload'); await Deno.remove(local_download_path); asserts.assert(!fs.existsSync(local_download_path)); const local_upload_path = path.join(Deno.cwd(), 'files', 'test_put_upload.txt'); asserts.assert(fs.existsSync(local_upload_path)); const stat = await Deno.lstat(local_upload_path); asserts.assert(stat); asserts.assert(stat.isFile); asserts.assertEquals(stat.size, 25); asserts.assertEquals(stat.mode! & 0o777, 0o755); await Deno.remove(local_upload_path); asserts.assert(!fs.existsSync(local_upload_path)); } finally { Deno.chdir(cwd); if (PREVIOUS_PUT_PATHS_ALLOWED) { Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', PREVIOUS_PUT_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_PUT_PATHS_ALLOWED'); } if (test_server_info) { await test_server_info?.server?.stop(); } } } }); Deno.test({ name: 'allow PUT to multiple files in a directory', permissions: { env: true, read: true, write: true, net: true }, sanitizeResources: false, sanitizeOps: false, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); const PREVIOUS_PUT_PATHS_ALLOWED = Deno.env.get('SERVERUS_PUT_PATHS_ALLOWED'); try { Deno.chdir('./tests/www'); Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', path.join(Deno.cwd(), 'files')); test_server_info = await get_ephemeral_listen_server(); const put_body = new FormData(); for (const i of [1, 2, 3]) { put_body.append('file', new File([`this is a test PUT upload ${i}`], `test_put_upload_${i}.txt`)); } const put_response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/files/test_multiple/`, { method: 'PUT', body: put_body }); asserts.assert(put_response.ok); const put_response_body = await put_response.json(); asserts.assert(put_response_body); asserts.assert(put_response_body.written); for await (const i of [1, 2, 3]) { const url = put_response_body.written?.[i - 1]; asserts.assertEquals( url, `http://${test_server_info.hostname}:${test_server_info.port}/files/test_multiple/test_put_upload_${i}.txt` ); const get_response = await fetch(url, { method: 'GET' }); asserts.assert(get_response.ok); asserts.assert(get_response.body); const local_download_path = path.join(Deno.cwd(), 'files', 'test_multiple', `test_put_upload_${i}.txt-downloaded`); await ensureFile(local_download_path); const file = await Deno.open(local_download_path, { truncate: true, write: true }); await get_response.body.pipeTo(file.writable); const download_content = await Deno.readTextFile(local_download_path); asserts.assert(download_content); asserts.assertEquals(download_content, `this is a test PUT upload ${i}`); await Deno.remove(local_download_path); asserts.assert(!fs.existsSync(local_download_path)); const local_upload_path = path.join(Deno.cwd(), 'files', 'test_multiple', `test_put_upload_${i}.txt`); asserts.assert(fs.existsSync(local_upload_path)); const stat = await Deno.lstat(local_upload_path); asserts.assert(stat); asserts.assert(stat.isFile); asserts.assertEquals(stat.size, 27); asserts.assertEquals(stat.mode! & 0o777, 0o755); await Deno.remove(local_upload_path); asserts.assert(!fs.existsSync(local_upload_path)); } const uploads_directory = path.join(Deno.cwd(), 'files', 'test_multiple'); await Deno.remove(uploads_directory); asserts.assert(!fs.existsSync(uploads_directory)); } finally { Deno.chdir(cwd); if (PREVIOUS_PUT_PATHS_ALLOWED) { Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', PREVIOUS_PUT_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_PUT_PATHS_ALLOWED'); } if (test_server_info) { await test_server_info?.server?.stop(); } } } }); Deno.test({ name: 'allow DELETE to static files if SERVERUS_DELETE_PATHS_ALLOWED is set', permissions: { env: true, read: true, write: true, net: true }, sanitizeResources: false, sanitizeOps: false, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); const PREVIOUS_PUT_PATHS_ALLOWED = Deno.env.get('SERVERUS_PUT_PATHS_ALLOWED'); const PREVIOUS_DELETE_PATHS_ALLOWED = Deno.env.get('SERVERUS_DELETE_PATHS_ALLOWED'); try { Deno.chdir('./tests/www'); Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', path.join(Deno.cwd(), 'files')); Deno.env.set('SERVERUS_DELETE_PATHS_ALLOWED', path.join(Deno.cwd(), 'files')); test_server_info = await get_ephemeral_listen_server(); const put_body = new FormData(); let test_file: File | undefined = new File(['this is a test DELETE upload'], 'test_delete_upload.txt'); put_body.append('file', test_file); const put_response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/files/test_delete_upload.txt`, { method: 'PUT', body: put_body }); asserts.assert(put_response.ok); const put_response_body = await put_response.json(); asserts.assert(put_response_body); asserts.assert(put_response_body.written); asserts.assertEquals( put_response_body.written?.[0], `http://${test_server_info.hostname}:${test_server_info.port}/files/test_delete_upload.txt` ); put_body.delete('file'); test_file = undefined; const get_response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/files/test_delete_upload.txt`, { method: 'GET' }); asserts.assert(get_response.ok); asserts.assert(get_response.body); const local_download_path = path.join(Deno.cwd(), 'files', 'test_delete_upload.txt-downloaded'); await ensureFile(local_download_path); const file = await Deno.open(local_download_path, { truncate: true, write: true }); await get_response.body.pipeTo(file.writable); const download_content = await Deno.readTextFile(local_download_path); asserts.assert(download_content); asserts.assertEquals(download_content, 'this is a test DELETE upload'); await Deno.remove(local_download_path); asserts.assert(!fs.existsSync(local_download_path)); const local_upload_path = path.join(Deno.cwd(), 'files', 'test_delete_upload.txt'); asserts.assert(fs.existsSync(local_upload_path)); const stat = await Deno.lstat(local_upload_path); asserts.assert(stat); asserts.assert(stat.isFile); asserts.assertEquals(stat.size, 28); asserts.assertEquals(stat.mode! & 0o777, 0o755); const delete_response = await fetch( `http://${test_server_info.hostname}:${test_server_info.port}/files/test_delete_upload.txt`, { method: 'DELETE' } ); asserts.assert(delete_response.ok); asserts.assert(!fs.existsSync(local_upload_path)); } finally { Deno.chdir(cwd); if (PREVIOUS_PUT_PATHS_ALLOWED) { Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', PREVIOUS_PUT_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_PUT_PATHS_ALLOWED'); } if (PREVIOUS_DELETE_PATHS_ALLOWED) { Deno.env.set('SERVERUS_DELETE_PATHS_ALLOWED', PREVIOUS_DELETE_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_DELETE_PATHS_ALLOWED'); } if (test_server_info) { await test_server_info?.server?.stop(); } } } }); Deno.test({ name: 'allow DELETE directory', permissions: { env: true, read: true, write: true, net: true }, sanitizeResources: false, sanitizeOps: false, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); const PREVIOUS_PUT_PATHS_ALLOWED = Deno.env.get('SERVERUS_PUT_PATHS_ALLOWED'); const PREVIOUS_DELETE_PATHS_ALLOWED = Deno.env.get('SERVERUS_DELETE_PATHS_ALLOWED'); try { Deno.chdir('./tests/www'); Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', path.join(Deno.cwd(), 'files')); Deno.env.set('SERVERUS_DELETE_PATHS_ALLOWED', path.join(Deno.cwd(), 'files')); test_server_info = await get_ephemeral_listen_server(); const put_body = new FormData(); let test_file: File | undefined = new File(['this is a test DELETE upload'], 'test_delete_directory_upload.txt'); put_body.append('file', test_file); const put_response = await fetch( `http://${test_server_info.hostname}:${test_server_info.port}/files/delete_directory_test/test_delete_directory_upload.txt`, { method: 'PUT', body: put_body } ); asserts.assert(put_response.ok); const put_response_body = await put_response.json(); asserts.assert(put_response_body); asserts.assert(put_response_body.written); asserts.assertEquals( put_response_body.written?.[0], `http://${test_server_info.hostname}:${test_server_info.port}/files/delete_directory_test/test_delete_directory_upload.txt` ); put_body.delete('file'); test_file = undefined; const local_upload_path = path.join(Deno.cwd(), 'files', 'delete_directory_test', 'test_delete_directory_upload.txt'); asserts.assert(fs.existsSync(local_upload_path)); const stat = await Deno.lstat(local_upload_path); asserts.assert(stat); asserts.assert(stat.isFile); asserts.assertEquals(stat.size, 28); asserts.assertEquals(stat.mode! & 0o777, 0o755); const delete_response = await fetch( `http://${test_server_info.hostname}:${test_server_info.port}/files/delete_directory_test`, { method: 'DELETE' } ); asserts.assert(delete_response.ok); asserts.assert(!fs.existsSync(local_upload_path)); asserts.assert(!fs.existsSync(path.dirname(local_upload_path))); } finally { Deno.chdir(cwd); if (PREVIOUS_PUT_PATHS_ALLOWED) { Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', PREVIOUS_PUT_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_PUT_PATHS_ALLOWED'); } if (PREVIOUS_DELETE_PATHS_ALLOWED) { Deno.env.set('SERVERUS_DELETE_PATHS_ALLOWED', PREVIOUS_DELETE_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_DELETE_PATHS_ALLOWED'); } if (test_server_info) { await test_server_info?.server?.stop(); } } } }); Deno.test({ name: 'allow overriding prechecks', permissions: { env: true, read: true, write: true, net: true }, sanitizeResources: false, sanitizeOps: false, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); const static_file_handler = await import('../handlers/static.ts'); const PREVIOUS_PRECHECKS = static_file_handler.PRECHECKS.PUT?.slice(0); const PREVIOUS_PUT_PATHS_ALLOWED = Deno.env.get('SERVERUS_PUT_PATHS_ALLOWED'); const PREVIOUS_DELETE_PATHS_ALLOWED = Deno.env.get('SERVERUS_DELETE_PATHS_ALLOWED'); try { Deno.chdir('./tests/www'); Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', path.join(Deno.cwd(), 'files')); Deno.env.set('SERVERUS_DELETE_PATHS_ALLOWED', path.join(Deno.cwd(), 'files')); test_server_info = await get_ephemeral_listen_server(); const PRECHECKS = static_file_handler.PRECHECKS.PUT = PREVIOUS_PRECHECKS ? [...PREVIOUS_PRECHECKS] : []; PRECHECKS.push((request: Request): Response | undefined => { const has_required_header = request.headers.get('x-required-header'); if (!has_required_header) { return Response.json({ error: { message: 'Missing required header.', cause: 'missing_required_header' } }, { status: 400 }); } }); const failed_put_body = new FormData(); failed_put_body.append( 'file', new File(['this is the test content for precheck overrides'], 'test_put_upload_that_should_fail.txt') ); const failed_put_response = await fetch( `http://${test_server_info.hostname}:${test_server_info.port}/files/test_put_upload_that_should_fail.txt`, { method: 'PUT', body: failed_put_body } ); asserts.assert(!failed_put_response.ok); const failed_body = await failed_put_response.json(); asserts.assert(failed_body); asserts.assert(failed_body.error); asserts.assertEquals(failed_body.error.cause, 'missing_required_header'); const successful_put_body = new FormData(); successful_put_body.append( 'file', new File(['this is the test content for precheck overrides'], 'test_put_upload_that_should_not_fail.txt') ); const successful_put_response = await fetch( `http://${test_server_info.hostname}:${test_server_info.port}/files/test_put_upload_that_should_not_fail.txt`, { method: 'PUT', headers: { 'x-required-header': 'true' }, body: successful_put_body } ); asserts.assert(successful_put_response.ok); const successful_body = await successful_put_response.json(); asserts.assert(successful_body); asserts.assert(successful_body.written); asserts.assertEquals( successful_body.written[0], `http://${test_server_info.hostname}:${test_server_info.port}/files/test_put_upload_that_should_not_fail.txt` ); const get_response = await fetch( `http://${test_server_info.hostname}:${test_server_info.port}/files/test_put_upload_that_should_not_fail.txt` ); asserts.assert(get_response.ok); asserts.assert(get_response.body); const local_download_path = path.join(Deno.cwd(), 'files', 'test_put_upload_that_should_not_fail.txt-downloaded'); await ensureFile(local_download_path); const file = await Deno.open(local_download_path, { truncate: true, write: true }); await get_response.body.pipeTo(file.writable); const download_content = await Deno.readTextFile(local_download_path); asserts.assert(download_content); asserts.assertEquals(download_content, 'this is the test content for precheck overrides'); await Deno.remove(local_download_path); asserts.assert(!fs.existsSync(local_download_path)); } finally { if (PREVIOUS_PRECHECKS) { static_file_handler.PRECHECKS.PUT = PREVIOUS_PRECHECKS; } if (PREVIOUS_PUT_PATHS_ALLOWED) { Deno.env.set('SERVERUS_PUT_PATHS_ALLOWED', PREVIOUS_PUT_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_PUT_PATHS_ALLOWED'); } if (PREVIOUS_DELETE_PATHS_ALLOWED) { Deno.env.set('SERVERUS_DELETE_PATHS_ALLOWED', PREVIOUS_DELETE_PATHS_ALLOWED); } else { Deno.env.delete('SERVERUS_DELETE_PATHS_ALLOWED'); } Deno.chdir(cwd); if (test_server_info) { await test_server_info?.server?.stop(); } } } }); Deno.test({ name: 'these methods should not work on static files', permissions: { env: true, read: true, write: true, net: true }, fn: async () => { let test_server_info: EPHEMERAL_SERVER | null = null; const cwd = Deno.cwd(); try { Deno.chdir('./tests/www'); test_server_info = await get_ephemeral_listen_server(); for await (const method of ['POST', 'PATCH']) { const response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/test.txt`, { method, body: method === 'TRACE' ? undefined : JSON.stringify({}) }); asserts.assert(!response.ok); const body = await response.json(); asserts.assert(body); asserts.assertEquals(body, { error: { cause: 'not_found', message: 'Not found' } }); } } finally { Deno.chdir(cwd); if (test_server_info) { await test_server_info?.server?.stop(); } } } });