diff --git a/src/storage/utils/object.js b/src/storage/utils/object.js index a095e8a8..3f605e6f 100644 --- a/src/storage/utils/object.js +++ b/src/storage/utils/object.js @@ -15,9 +15,9 @@ export async function invalidateCollab(api, url, env) { return; } - const invPath = `/api/v1/${api}?doc=${url}`; + const { DA_COLLAB } = env; - // Use dacollab service binding, hostname is not relevant - const invURL = `https://localhost${invPath}`; - await env.dacollab.fetch(invURL); + const invURL = `${DA_COLLAB}/api/v1/${api}?doc=${url}`; + + await fetch(invURL); } diff --git a/test/routes/source.test.js b/test/routes/source.test.js index 52538b2e..2fd68a80 100644 --- a/test/routes/source.test.js +++ b/test/routes/source.test.js @@ -15,13 +15,9 @@ import esmock from 'esmock'; import { getAclCtx } from '../../src/utils/auth.js'; describe('Source Route', () => { - it('Test invalidate using service binding', async () => { - const sb_callbacks = []; - const dacollab = { - fetch: async (url) => sb_callbacks.push(url) - }; + it('Test invalidate using direct fetch', async () => { + const fetch_callbacks = []; const env = { - dacollab, DA_COLLAB: 'http://localhost:4444' }; @@ -39,17 +35,26 @@ describe('Source Route', () => { } }); - const headers = new Map(); - headers.set('x-da-initiator', 'blah'); + const savedFetch = globalThis.fetch; + try { + globalThis.fetch = async (url) => { + fetch_callbacks.push(url); + }; - const req = { - headers, - url: 'http://localhost:9876/source/somedoc.html' - }; + const headers = new Map(); + headers.set('x-da-initiator', 'blah'); - const resp = await postSource({ req, env, daCtx }); - assert.equal(200, resp.status); - assert.deepStrictEqual(['https://localhost/api/v1/syncadmin?doc=http://localhost:9876/source/somedoc.html'], sb_callbacks); + const req = { + headers, + url: 'http://localhost:9876/source/somedoc.html' + }; + + const resp = await postSource({ req, env, daCtx }); + assert.equal(200, resp.status); + assert.deepStrictEqual(['http://localhost:4444/api/v1/syncadmin?doc=http://localhost:9876/source/somedoc.html'], fetch_callbacks); + } finally { + globalThis.fetch = savedFetch; + } }); it('Test postSource from collab does not trigger invalidate callback', async () => { diff --git a/test/storage/object/copy.test.js b/test/storage/object/copy.test.js index 2305ba9b..2879deea 100644 --- a/test/storage/object/copy.test.js +++ b/test/storage/object/copy.test.js @@ -176,12 +176,7 @@ describe('Object copy', () => { }; const collabcalls = []; - const dacollab = { - fetch: (url) => { - collabcalls.push(url); - } - } - const env = { dacollab }; + const env = { DA_COLLAB: 'https://localhost' }; const ctx = { bucket: 'root-bucket', env, @@ -196,37 +191,44 @@ describe('Object copy', () => { destination: 'mydir/newdir', }; - const copyObjectWithMock = await esmock( - '../../../src/storage/object/copy.js', { - '../../../src/storage/object/get.js': { - default: mockGetObject, - }, - } - ); - - await copyObjectWithMock.default(env, ctx, details, false); - - assert.strictEqual(s3Sent.length, 3); + const savedFetch = globalThis.fetch; + try { + globalThis.fetch = async (url) => { + collabcalls.push(url); + }; - // Make the order in s3Sent predictable - s3Sent.sort((a, b) => a.Key.localeCompare(b.Key)); - - const input = s3Sent[2]; - assert.strictEqual(input.Bucket, 'root-bucket'); - assert.strictEqual(input.CopySource, 'root-bucket/foo/mydir/xyz.html'); - assert.strictEqual(input.Key, 'foo/mydir/newdir/xyz.html'); - assert.strictEqual(input.ContentType, 'text/html'); - - const md = input.Metadata; - assert(md.ID, "ID should be set"); - assert(md.Version, "Version should be set"); - assert.strictEqual(typeof (md.Timestamp), 'string', 'Timestamp should be set as a string'); - assert.strictEqual(md.Users, '[{"email":"haha@foo.com"}]'); - assert.strictEqual(md.Path, 'mydir/newdir/xyz.html'); - - assert.strictEqual(1, collabcalls.length); - assert.deepStrictEqual(collabcalls, - ['https://localhost/api/v1/syncAdmin?doc=somehost.sometld/source/foo/mydir/newdir/xyz.html']); + const copyObjectWithMock = await esmock( + '../../../src/storage/object/copy.js', { + '../../../src/storage/object/get.js': { + default: mockGetObject, + }, + } + ); + + await copyObjectWithMock.default(env, ctx, details, false); + + assert.strictEqual(s3Sent.length, 3); + // Make the order in s3Sent predictable + s3Sent.sort((a, b) => a.Key.localeCompare(b.Key)); + + const input = s3Sent[2]; + assert.strictEqual(input.Bucket, 'root-bucket'); + assert.strictEqual(input.CopySource, 'root-bucket/foo/mydir/xyz.html'); + assert.strictEqual(input.Key, 'foo/mydir/newdir/xyz.html'); + + const md = input.Metadata; + assert(md.ID, "ID should be set"); + assert(md.Version, "Version should be set"); + assert.strictEqual(typeof (md.Timestamp), 'string', 'Timestamp should be set as a string'); + assert.strictEqual(md.Users, '[{"email":"haha@foo.com"}]'); + assert.strictEqual(md.Path, 'mydir/newdir/xyz.html'); + + assert.strictEqual(1, collabcalls.length); + assert.deepStrictEqual(collabcalls, + ['https://localhost/api/v1/syncAdmin?doc=somehost.sometld/source/foo/mydir/newdir/xyz.html']); + } finally { + globalThis.fetch = savedFetch; + } }); it('Copies a file for rename', async () => { @@ -258,12 +260,7 @@ describe('Object copy', () => { }; const collabcalls = []; - const dacollab = { - fetch: (url) => { - collabcalls.push(url); - } - } - const env = { dacollab }; + const env = { DA_COLLAB: 'https://localhost' }; const ctx = { bucket: 'root-bucket', org: 'testorg', key: 'mydir/dir1', origin: 'http://localhost:3000' }; ctx.aclCtx = await getAclCtx(env, ctx.org, ctx.users, '/'); const details = { @@ -271,30 +268,37 @@ describe('Object copy', () => { destination: 'mydir/dir2', }; - const copyObjectWithMock = await esmock( - '../../../src/storage/object/copy.js', { - '../../../src/storage/object/get.js': { - default: mockGetObject, - }, - } - ); + const savedFetch = globalThis.fetch; + try { + globalThis.fetch = async (url) => { + collabcalls.push(url); + }; - await copyObjectWithMock.default(env, ctx, details, true); + const copyObjectWithMock = await esmock( + '../../../src/storage/object/copy.js', { + '../../../src/storage/object/get.js': { + default: mockGetObject, + }, + } + ); - assert.strictEqual(s3Sent.length, 3); + await copyObjectWithMock.default(env, ctx, details, true); - // Make the order in s3Sent predictable - s3Sent.sort((a, b) => a.Key.localeCompare(b.Key)); + assert.strictEqual(s3Sent.length, 3); + // Make the order in s3Sent predictable + s3Sent.sort((a, b) => a.Key.localeCompare(b.Key)); - const input = s3Sent[2]; - assert.strictEqual(input.Bucket, 'root-bucket'); - assert.strictEqual(input.CopySource, 'root-bucket/testorg/mydir/dir1/myfile.html'); - assert.strictEqual(input.Key, 'testorg/mydir/dir2/myfile.html'); - assert.strictEqual(input.ContentType, 'text/html'); - assert.ifError(input.Metadata); + const input = s3Sent[2]; + assert.strictEqual(input.Bucket, 'root-bucket'); + assert.strictEqual(input.CopySource, 'root-bucket/testorg/mydir/dir1/myfile.html'); + assert.strictEqual(input.Key, 'testorg/mydir/dir2/myfile.html'); + assert.ifError(input.Metadata); - assert.deepStrictEqual(collabcalls, - ['https://localhost/api/v1/syncAdmin?doc=http://localhost:3000/source/testorg/mydir/dir2/myfile.html']); + assert.deepStrictEqual(collabcalls, + ['https://localhost/api/v1/syncAdmin?doc=http://localhost:3000/source/testorg/mydir/dir2/myfile.html']); + } finally { + globalThis.fetch = savedFetch; + } }); it('Adds copy condition', async () => { @@ -335,9 +339,7 @@ describe('Object copy', () => { const collabCalled = []; const env = { - dacollab: { - fetch: (x) => { collabCalled.push(x); }, - }, + DA_COLLAB: 'https://localhost', }; const daCtx = { bucket: 'root-bucket', @@ -350,7 +352,11 @@ describe('Object copy', () => { source: 'mysrc', destination: 'mydst', }; - const resp = await copyFile({}, env, daCtx, 'mysrc/abc/def.html', details, false); + + const savedFetch = globalThis.fetch; + try { + globalThis.fetch = async (x) => { collabCalled.push(x); }; + const resp = await copyFile({}, env, daCtx, 'mysrc/abc/def.html', details, false); assert.strictEqual(resp.constructor.name, 'CopyObjectCommand'); assert.strictEqual(resp.input.Bucket, 'root-bucket'); @@ -388,6 +394,9 @@ describe('Object copy', () => { assert.deepStrictEqual(collabCalled, ['https://localhost/api/v1/syncAdmin?doc=https://blahblah:7890/source/myorg/mydst/abc/def.html']); + } finally { + globalThis.fetch = savedFetch; + } }); it('Copy content when destination already exists', async () => { @@ -434,9 +443,7 @@ describe('Object copy', () => { const collabCalled = []; const env = { - dacollab: { - fetch: (x) => { collabCalled.push(x); }, - }, + DA_COLLAB: 'https://localhost', }; const daCtx = { bucket: 'mybucket', org: 'xorg' }; daCtx.aclCtx = await getAclCtx(env, daCtx.org, daCtx.users, '/'); @@ -444,17 +451,24 @@ describe('Object copy', () => { source: 'xsrc', destination: 'xdst', }; - const resp = await copyFile({}, env, daCtx, 'xsrc/abc/def.html', details, false); - assert.strictEqual(resp, 'beuaaark!'); - - assert.strictEqual(puwv.length, 1); - assert.strictEqual(puwv[0].c, daCtx); - assert.strictEqual(puwv[0].e, env); - assert.strictEqual(puwv[0].u.body, 'original body'); - assert.strictEqual(puwv[0].u.contentLength, 42); - assert.strictEqual(puwv[0].u.key, 'xdst/abc/def.html'); - assert.strictEqual(puwv[0].u.org, 'xorg'); - assert.strictEqual(puwv[0].u.type, 'text/html'); + + const savedFetch = globalThis.fetch; + try { + globalThis.fetch = async (x) => { collabCalled.push(x); }; + const resp = await copyFile({}, env, daCtx, 'xsrc/abc/def.html', details, false); + assert.strictEqual(resp, 'beuaaark!'); + + assert.strictEqual(puwv.length, 1); + assert.strictEqual(puwv[0].c, daCtx); + assert.strictEqual(puwv[0].e, env); + assert.strictEqual(puwv[0].u.body, 'original body'); + assert.strictEqual(puwv[0].u.contentLength, 42); + assert.strictEqual(puwv[0].u.key, 'xdst/abc/def.html'); + assert.strictEqual(puwv[0].u.org, 'xorg'); + assert.strictEqual(puwv[0].u.type, 'text/html'); + } finally { + globalThis.fetch = savedFetch; + } }); it('Copy content when origin does not exists', async () => { @@ -494,9 +508,7 @@ describe('Object copy', () => { const collabCalled = []; const env = { - dacollab: { - fetch: (x) => { collabCalled.push(x); }, - }, + DA_COLLAB: 'https://localhost', }; const daCtx = { bucket: 'test-bucket', org: 'qqqorg', origin: 'http://qqq' }; daCtx.aclCtx = await getAclCtx(env, daCtx.org, daCtx.users, '/'); @@ -504,10 +516,17 @@ describe('Object copy', () => { source: 'qqqsrc', destination: 'qqqdst', }; - const resp = await copyFile({}, env, daCtx, 'qqqsrc/abc/def.html', details, false); - assert.strictEqual(resp.$metadata.httpStatusCode, 404); - assert.deepStrictEqual(collabCalled, - ['https://localhost/api/v1/syncAdmin?doc=http://qqq/source/qqqorg/qqqdst/abc/def.html']); + + const savedFetch = globalThis.fetch; + try { + globalThis.fetch = async (x) => { collabCalled.push(x); }; + const resp = await copyFile({}, env, daCtx, 'qqqsrc/abc/def.html', details, false); + assert.strictEqual(resp.$metadata.httpStatusCode, 404); + assert.deepStrictEqual(collabCalled, + ['https://localhost/api/v1/syncAdmin?doc=http://qqq/source/qqqorg/qqqdst/abc/def.html']); + } finally { + globalThis.fetch = savedFetch; + } }); }); @@ -522,27 +541,27 @@ describe('Object copy', () => { s3Sent.push(input); })); - // Mock getObject to return content type for HEAD requests - const mockGetObject = async (env, { bucket, org, key }, head) => { - if (head && bucket === 'root-bucket' && org === 'foo') { - if (key === 'mydir/xyz.html') { - return { - contentType: 'text/html', - status: 200, - contentLength: 100, - }; - } else if (key === 'mydir' || key === 'mydir.props') { - return { - contentType: 'text/html', - status: 200, - contentLength: 100, - }; + // Mock getObject to return content type for HEAD requests + const mockGetObject = async (env, { bucket, org, key }, head) => { + if (head && bucket === 'root-bucket' && org === 'foo') { + if (key === 'mydir/xyz.html') { + return { + contentType: 'text/html', + status: 200, + contentLength: 100, + }; + } else if (key === 'mydir' || key === 'mydir.props') { + return { + contentType: 'text/html', + status: 200, + contentLength: 100, + }; + } } - } - return null; - }; + return null; + }; - const env = { dacollab: { fetch: () => {} } }; + const env = { DA_COLLAB: 'https://localhost' }; const ctx = { bucket: 'root-bucket', org: 'foo', @@ -577,7 +596,7 @@ describe('Object copy', () => { DA_JOBS[key] = value; } }, - dacollab: { fetch: () => {} } + DA_COLLAB: 'https://localhost' } s3Mock.on(ListObjectsV2Command) .resolves({ @@ -662,7 +681,7 @@ describe('Object copy', () => { return DA_JOBS[key]; } }, - dacollab: { fetch: () => {} } + DA_COLLAB: 'https://localhost' } // Mock getObject to return content type for HEAD requests @@ -724,7 +743,7 @@ describe('Object copy', () => { delete DA_JOBS[key]; } }, - dacollab: { fetch: () => {} } + DA_COLLAB: 'https://localhost' } // Mock getObject to return content type for HEAD requests diff --git a/test/storage/object/delete.test.js b/test/storage/object/delete.test.js index 1c5572cf..d67b07ac 100644 --- a/test/storage/object/delete.test.js +++ b/test/storage/object/delete.test.js @@ -25,10 +25,8 @@ describe('Object delete', () => { describe('single context', () => { it('Delete a file', async () => { const collabCalled = [] - const dacollab = { fetch: (u) => collabCalled.push(u) }; - const client = {}; - const env = { dacollab }; + const env = { DA_COLLAB: 'https://localhost' }; const daCtx = { origin: 'https://admin.da.live', org: 'testorg', @@ -64,18 +62,23 @@ describe('Object delete', () => { const savedFetch = globalThis.fetch; try { globalThis.fetch = async (url, opts) => { - assert.equal(deleteURL, url); - assert.equal('DELETE', opts.method); - return { status: 204 }; + if (url === deleteURL) { + assert.equal('DELETE', opts.method); + return { status: 204 }; + } else { + // This is the collab invalidation call + collabCalled.push(url); + return { status: 200 }; + } }; const resp = await deleteObject(client, daCtx, 'foo/bar.html', env); assert.equal(204, resp.status); // assert.deepStrictEqual(['postObjectVersionWithLabel'], postObjVerCalled); - // assert.deepStrictEqual( - // ['https://localhost/api/v1/deleteadmin?doc=https://admin.da.live/source/testorg/foo/bar.html'], - // collabCalled - // ); + assert.deepStrictEqual( + ['https://localhost/api/v1/deleteadmin?doc=https://admin.da.live/source/testorg/foo/bar.html'], + collabCalled + ); } finally { globalThis.fetch = savedFetch; } @@ -234,10 +237,7 @@ describe('Object delete', () => { aclCtx: { pathLookup: new Map() }, }; const env = { - dacollab: { - fetch: () => { - } - }, + DA_COLLAB: 'https://localhost', }; const mockPostObjectVersion = async () => ({ status: 201 }); const mockSignedUrl = async () => 'http://localhost:8080/test/'; @@ -264,10 +264,7 @@ describe('Object delete', () => { aclCtx: { pathLookup: new Map() }, }; const env = { - dacollab: { - fetch: () => { - } - }, + DA_COLLAB: 'https://localhost', }; const mockPostObjectVersion = async () => ({ status: 201 }); const mockSignedUrl = async () => 'http://localhost:8080/test/'; diff --git a/test/storage/utils/object.test.js b/test/storage/utils/object.test.js index 52a1e9cc..078fa670 100644 --- a/test/storage/utils/object.test.js +++ b/test/storage/utils/object.test.js @@ -17,31 +17,44 @@ import { invalidateCollab } from '../../../src/storage/utils/object.js'; describe('Storage Object Utils tests', () => { function setupEnv() { const called = []; - const dacollab = { - fetch: async (url) => { - console.log(`invalidate called with ${url}`); - called.push(url); - }, - }; - const env = { dacollab }; + const env = { DA_COLLAB: 'https://localhost' }; return { called, env }; } it('Should invalidate', async () => { const { called, env } = setupEnv(); - assert.strictEqual(called.length, 0, 'precondition'); - await invalidateCollab('syncAdmin', 'https://admin.da.live/source/a/b/c.html', env); - assert.strictEqual(called.length, 1); - assert.strictEqual(called[0], 'https://localhost/api/v1/syncAdmin?doc=https://admin.da.live/source/a/b/c.html'); + const savedFetch = globalThis.fetch; + try { + globalThis.fetch = async (url) => { + console.log(`invalidate called with ${url}`); + called.push(url); + }; + + assert.strictEqual(called.length, 0, 'precondition'); + await invalidateCollab('syncAdmin', 'https://admin.da.live/source/a/b/c.html', env); + assert.strictEqual(called.length, 1); + assert.strictEqual(called[0], 'https://localhost/api/v1/syncAdmin?doc=https://admin.da.live/source/a/b/c.html'); + } finally { + globalThis.fetch = savedFetch; + } }); it('Should not invalidate non-html documents', async () => { const { called, env } = setupEnv(); - assert.strictEqual(called.length, 0, 'precondition'); - await invalidateCollab('syncAdmin', 'https://admin.da.live/source/a/b/c.jpg', env); - await invalidateCollab('syncAdmin', 'https://admin.da.live/source/a/b/c/d', env); - assert.strictEqual(called.length, 0, 'should not have invalidated anything'); + const savedFetch = globalThis.fetch; + try { + globalThis.fetch = async (url) => { + called.push(url); + }; + + assert.strictEqual(called.length, 0, 'precondition'); + await invalidateCollab('syncAdmin', 'https://admin.da.live/source/a/b/c.jpg', env); + await invalidateCollab('syncAdmin', 'https://admin.da.live/source/a/b/c/d', env); + assert.strictEqual(called.length, 0, 'should not have invalidated anything'); + } finally { + globalThis.fetch = savedFetch; + } }); }); diff --git a/wrangler.toml b/wrangler.toml index 88b30f7e..018934c3 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -3,11 +3,7 @@ main = "src/index.js" compatibility_date = "2024-11-11" keep_vars = true -vars = { DA_COLLAB = "https://collab.da.page", AEM_BUCKET_NAME = "aem-content" } - -services = [ - { binding = "dacollab", service = "da-collab" } -] +vars = { DA_COLLAB = "https://da-collab.adobeaem.workers.dev", AEM_BUCKET_NAME = "aem-content" } kv_namespaces = [ { binding = "DA_AUTH", id = "f8978fd2270f4c4fbcc8c9f04248a034" }, @@ -20,11 +16,7 @@ r2_buckets = [ ] [env.stage] -vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://collab.da.page", AEM_BUCKET_NAME = "aem-content-stage" } - -services = [ - { binding = "dacollab", service = "da-collab-stage" } -] +vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://da-collab-stage.adobeaem.workers.dev", AEM_BUCKET_NAME = "aem-content-stage" } kv_namespaces = [ { binding = "DA_AUTH", id = "f5cc4d0150ac48d5b56948b5d147c77e" }, @@ -39,10 +31,6 @@ r2_buckets = [ [env.dev] vars = { ENVIRONMENT = "dev", DA_COLLAB = "http://localhost:4711", AEM_BUCKET_NAME = "aem-content-dev" } -services = [ - { binding = "dacollab", service = "da-collab-local" } -] - kv_namespaces = [ { binding = "DA_AUTH", id = "f5cc4d0150ac48d5b56948b5d147c77e" }, { binding = "DA_CONFIG", id = "3f6f6db5c27348fabee7c2a8ed39be17" },