Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtual network part 2 #1126

Merged
merged 32 commits into from
Apr 15, 2024
Merged

Virtual network part 2 #1126

merged 32 commits into from
Apr 15, 2024

Conversation

ef4
Copy link
Contributor

@ef4 ef4 commented Mar 28, 2024

No description provided.

Copy link

github-actions bot commented Mar 28, 2024

Test Results

584 tests  ±0   580 ✔️ ±0   8m 8s ⏱️ -38s
    1 suites ±0       4 💤 ±0 
    1 files   ±0       0 ±0 

Results for commit 34bfedb. ± Comparison against base commit b89827b.

♻️ This comment has been updated with latest results.

@jurgenwerk
Copy link
Contributor

jurgenwerk commented Apr 2, 2024

@ef4 @lukemelia an update:

  1. Cleaned up the concepts of resolving, unresolving, url mapping from the loader (basically what Virtual network part 3 #1115 is trying to achieve - it seemed more convenient to do it here in this branch)

  2. While hosts and realm tests were passing, the realm dom tests were failing (this could easily be reprouced by going to http://localhost:4201 which was broken because the browser was trying to load assets from an unresolved url, i.e. cardstack.com/base). It was happening because the realm server middleware is doing redirections (rootRealmRedirect, assetRedirect) and in that logic it wants to know the resolved URL for the realm. For that reason I changed virtual network's resolveURLMapping from private to public, and used it in redirection logic: 6f74533

I feel that this change might not be aligned with the vision for the virtual network so I'd like to discuss this. Perhaps the realm server should not know about resolved urls and the mentioned redirection logic should be moved to the virtual network as handlers?

  1. At this point there are still test failures, this time in matrix tests. There seems to be an issue with fetching rooms from the matrix server where it doesn't return the chat room. It's puzzling how this is related to this refactor but I am checking it.

@jurgenwerk
Copy link
Contributor

jurgenwerk commented Apr 2, 2024

Follow up comments to issue described in (2), did some discussing with @lukemelia–a couple of ideas to make the resolveURLMapping back to being a private method:

  1. There could be an AssetRedirector that would receive the mapping in the constructor, and have a method to be plugged in the middleware (similarly to assetRedirect). It would respond with the real url in the location header by figuring it out from the url mapping config rather than calling resolveURLMapping

  2. We could explore mounting a handler for the redirection logic (as opposed to doing that in the koa middleware), mount it to virtual network, and add functionality in handle which would add special treatment if the response results in a redirect (making the location header url real, not virtual)

@jurgenwerk jurgenwerk marked this pull request as ready for review April 9, 2024 09:30
@jurgenwerk
Copy link
Contributor

jurgenwerk commented Apr 9, 2024

This PR leverages the virtual network in such a way that:

  1. All URL mapping is moved to the virtual network which is now fully responsible for mapping (also known as resolving, reverse resolving realm urls)
  2. All logic that depended on knowing the resolved url was moved to the virtual network
  3. Redirections (asset redirection, realm root redirection) were moved out of the realm server (to satisfy (1))

This refactor is an intermediate step towards having isolated loaders that share a virtual network.

@jurgenwerk jurgenwerk requested review from lukemelia and a team April 9, 2024 10:19
packages/host/app/services/message-service.ts Outdated Show resolved Hide resolved
packages/realm-server/main.ts Show resolved Hide resolved
packages/runtime-common/realm.ts Outdated Show resolved Hide resolved
packages/runtime-common/virtual-network.ts Show resolved Hide resolved
packages/runtime-common/virtual-network.ts Show resolved Hide resolved
Copy link
Contributor

@habdelra habdelra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

packages/realm-server/main.ts Show resolved Hide resolved

let body = null;
if (originalRequest.body) {
body = await getContentOfReadableStream(originalRequest.clone().body);
Copy link
Contributor

@jurgenwerk jurgenwerk Apr 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been trying to see if I can get rid of body stream reading to create a new request with a changed url but to no avail...

  1. Object.defineProperty(request, 'url', { value: mappedUrl }) will not work because the underlying url value really is immutable. Here is a demonstration - the request will still try to reach the original url even when trying to override it with defineProperty:
image
  1. I saw some hints online that tee could be used to copy the body, like so:
let copiedBody = null;
  if (originalRequest.body) {
    copiedBody = originalRequest.body.tee()[0];
  }

  return new Request(url, {
    method: originalRequest.method,
    headers: originalRequest.headers,
    body: copiedBody,
    referrer: originalRequest.referrer,
    referrerPolicy: originalRequest.referrerPolicy,
    mode: originalRequest.mode,
    credentials: originalRequest.credentials,
    cache: originalRequest.cache,
    redirect: originalRequest.redirect,
    integrity: originalRequest.integrity,
  });

But again, the error persists:

image
  1. clone()-ing the request and taking its body won't work either (failing with the same error):
return new Request(url, {
    method: originalRequest.method,
    headers: originalRequest.headers,
    body: originalRequest.clone().body,
    referrer: originalRequest.referrer,
    referrerPolicy: originalRequest.referrerPolicy,
    mode: originalRequest.mode,
    credentials: originalRequest.credentials,
    cache: originalRequest.cache,
    redirect: originalRequest.redirect,
    integrity: originalRequest.integrity,
  });

It is interesting because Safari gives a different error message:

image
  1. But what if we try adding the duplex property?
let requestInit: RequestInit = originalRequest.clone();

  if (originalRequest.body) {
    requestInit.duplex = 'half';
  }

  return new Request(url, requestInit);

The request will fail with net::ERR_H2_OR_QUIC_REQUIRED which is indicative of missing http2 support on the server:

image

Moreover, TypeScript doesn't recognize duplex property on the Request - looks like this is more of an experimental thing for now...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought would be to Proxy the request:

let proxiedRequest = new Proxy(originalRequest, {
  get(target, property, received) {
    if (property === 'url') {
      return mappedURL;
    }
    return Reflect.get(target, property, received);
  }
})

@ef4 ef4 merged commit 76bd4fd into main Apr 15, 2024
19 checks passed
@delete-merged-branch delete-merged-branch bot deleted the virtual-network-part-2 branch April 15, 2024 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants