XmlHttpRequest open() is implicitly sync in Revit 2022.1 CefSharp because of journal overrides

XmlHttpRequest open() is implicitly sync in Revit 2022.1 CefSharp because of journal overrides

J.Glasbergen
Explorer Explorer
1,165 Views
2 Replies
Message 1 of 3

XmlHttpRequest open() is implicitly sync in Revit 2022.1 CefSharp because of journal overrides

J.Glasbergen
Explorer
Explorer

In a Revit addin that I'm working on I'm using the Revit CefSharp instance to display a Web UI. In this Web UI I'm using the Angular HttpClient to send the HTTP requests. After upgrading Revit 2022 to Revit 2022.1 the following error occurred: 'Failed to set the 'responseType' property on 'XMLHttpRequest' The response type cannot be changed for synchronous requests made from a document'

The Angular HTTPClient uses the XMLHttpRequest to send a request to the server. I am able to reproduce the error in a simple add-in which loads a browser instance with the following testscript:

 

function run() {
  const xhr = new XMLHttpRequest();
  xhr.open("GET", "/api/GetApiTest");
  xhr.responseType = "json";
}

 

In Revit 2022.1 it crashes on the line: xhr.responseType = "json";.


The issue seems to be caused by an addition to the CefSharp of Revit 2022.1 in which a script related to the Journal is injected. This script file overrides the `open()` method on the XMLHttpRequest, does some logging and calls the original `open()` method:

 

// call original open()
XMLHttpRequest_open.call(this, method, url, async, user, password);

 

This approach works fine when another script uses the overload with all parameters: 'open(method: string, url: string | URL, async: boolean, username?: string | null, password?: string | null): void;'

 

In the case of the Angular HTTP client the simplified overload: 'open(method: string, url: string | URL)' is being used, so recalling with the full overload implicitly sets the async parameter to false causing the error.

 

It looks like this is a bug in the injected journal scripts, as the correct overload will never be called. In my test script the issue can be solved by explicitly setting the async parameter to true. But I don't have the opportunity to explicitly set the async parameter to true in the Angular HttpClient. So I will need to override the XMLHttpRequest.open in my scripts to add the async true parameter and recall the original method.

 

I'm wondering if anyone else has encountered this issue before and if there any plans to fix this in upcoming Revit versions.

1,166 Views
2 Replies
Replies (2)
Message 2 of 3

jeremy_tammik
Alumni
Alumni

Wow. Interesting deep observations. If worst comes to worst, you can decouple your add-in from Revit using IPC:

  

https://thebuildingcoder.typepad.com/blog/2019/04/set-floor-level-and-use-ipc-for-disentanglement.ht...

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 3

ryzhykh
Explorer
Explorer

In our team, we solved this problem by adding http interceptor.

 

intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return new Observable((r) => {
      const req = new XMLHttpRequest();
      req.addEventListener("load", function (data) {
        let i = new HttpResponse({body: JSON.parse(this.responseText)});
        r.next(i);
        r.complete();
      });
      req.open(request.method, request.urlWithParams, true);
      if(request.method === 'POST') {
        let body = request.serializeBody();
        req.setRequestHeader("Content-type", "application/json")
        req.send(body);
      } else req.send();
    })
  }

 

0 Likes