i2group / notebook-sdk

Create plug-ins that expand and enhance the functionality of the i2 Notebook web client by using the i2 Notebook SDK. The SDK is comprised of documentation, tools, and sample code.
https://i2group.github.io/notebook-sdk/
MIT License
4 stars 1 forks source link

[HPM] WebSocket error: Error: write ECONNABORTED #16

Closed stvdo closed 7 months ago

stvdo commented 7 months ago

Good morning,

I created a React plugin (https://i2group.github.io/notebook-sdk/guide/tutorials/react-plugin.html) yesterday. This worked perfect at the end of the day, but when I now click on the plugin the ToolView is flashing and I get the errors below.

Do you have any suggestion to fix this?

PS D:\Projects\Analyse Studio\plugin-neovis-react> npx @i2analyze/notebook-sdk-plugin-proxy --config devproxy.json
@i2analyze/notebook-sdk-plugin-proxy 2.0.0
Development proxy listening on http://localhost:4001
 proxying /opal/ to https://i2analyze.eia:9443/opal/
 proxying /opal/plugins/react-neovis-plugin/ to http://localhost:5173/opal/plugins/react-neovis-plugin/
[HPM] WebSocket error: Error: write ECONNABORTED
    at afterWriteDispatched (node:internal/stream_base_commons:160:15)
    at writeGeneric (node:internal/stream_base_commons:151:3)
    at Socket._writeGeneric (node:net:952:11)
    at Socket._write (node:net:964:8)
    at writeOrBuffer (node:internal/streams/writable:564:12)
    at _write (node:internal/streams/writable:493:10)
    at Writable.write (node:internal/streams/writable:502:10)
    at IncomingMessage.ondata (node:internal/streams/readable:1007:22)
    at IncomingMessage.emit (node:events:518:28)
    at Readable.read (node:internal/streams/readable:780:10) {
  errno: -4079,
  code: 'ECONNABORTED',
  syscall: 'write'
}
[HPM] WebSocket error: Error: write ECONNABORTED
    at afterWriteDispatched (node:internal/stream_base_commons:160:15)
    at writeGeneric (node:internal/stream_base_commons:151:3)
    at Socket._writeGeneric (node:net:952:11)
    at Socket._write (node:net:964:8)
    at writeOrBuffer (node:internal/streams/writable:564:12)
    at _write (node:internal/streams/writable:493:10)
    at Writable.write (node:internal/streams/writable:502:10)
    at IncomingMessage.ondata (node:internal/streams/readable:1007:22)
    at IncomingMessage.emit (node:events:518:28)
    at Readable.read (node:internal/streams/readable:780:10) {
  errno: -4079,
  code: 'ECONNABORTED',
  syscall: 'write'
}
[HPM] WebSocket error: Error: write ECONNABORTED
    at afterWriteDispatched (node:internal/stream_base_commons:160:15)
    at writeGeneric (node:internal/stream_base_commons:151:3)
    at Socket._writeGeneric (node:net:952:11)
    at Socket._write (node:net:964:8)
    at writeOrBuffer (node:internal/streams/writable:564:12)
    at _write (node:internal/streams/writable:493:10)
    at Writable.write (node:internal/streams/writable:502:10)
    at IncomingMessage.ondata (node:internal/streams/readable:1007:22)
    at IncomingMessage.emit (node:events:518:28)
    at Readable.read (node:internal/streams/readable:780:10) {
  errno: -4079,
  code: 'ECONNABORTED',
  syscall: 'write'
}
[HPM] WebSocket error: Error: write ECONNABORTED
    at afterWriteDispatched (node:internal/stream_base_commons:160:15)
    at writeGeneric (node:internal/stream_base_commons:151:3)
    at Socket._writeGeneric (node:net:952:11)
    at Socket._write (node:net:964:8)
    at writeOrBuffer (node:internal/streams/writable:564:12)
    at _write (node:internal/streams/writable:493:10)
    at Writable.write (node:internal/streams/writable:502:10)
    at IncomingMessage.ondata (node:internal/streams/readable:1007:22)
    at IncomingMessage.emit (node:events:518:28)
    at Readable.read (node:internal/streams/readable:780:10) {
  errno: -4079,
  code: 'ECONNABORTED',
  syscall: 'write'
}
[HPM] WebSocket error: Error: read ECONNRESET
    at TCP.onStreamRead (node:internal/stream_base_commons:217:20) {
  errno: -4077,
  code: 'ECONNRESET',
  syscall: 'read'
}
[HPM] WebSocket error: Error: read ECONNRESET
    at TCP.onStreamRead (node:internal/stream_base_commons:217:20) {
  errno: -4077,
  code: 'ECONNRESET',
  syscall: 'read'
}
[HPM] WebSocket error: Error: read ECONNRESET
    at TCP.onStreamRead (node:internal/stream_base_commons:217:20) {
  errno: -4077,
  code: 'ECONNRESET',
  syscall: 'read'
}
Tim-Mawson-i2 commented 7 months ago

@sdorresteijn88 This sounds like the Vite dev server is having issues connecting its websocket to the page, could you try adding "connect-src": "http 'unsafe-inline'" to the plugin.json toolViewCsp block - forcing it to http has solved similar Vite connection issues for us.

e.g.

...
toolViewCsp: {
  "connect-src": "http 'unsafe-inline'",
}
...

Alternatively you could use a different local development server to serve up the built code, rather than using the Vite system (such as npx server, with some appropriate config).

stvdo commented 7 months ago

@Tim-Mawson-i2 thanks for your quick reply! That solved the issue indeed. Thanks very much!

stvdo commented 7 months ago

@Tim-Mawson-i2 I am struggling with one remaining issue about an invalid frame header. Do you have suggestions for solving this?

image

This is my plugin.json

{
    "$schema": "https://i2group.github.io/notebook-sdk/schemas/plugin-manifest.json",
    "name": "Neovis i2 Notebook plug-in",
    "pluginId": "4eb579fb-afee-4dbd-8106-7e3fc4e87ba9",
    "pluginVersion": "1.0.0",
    "entryPointUrl": "./entrypoint.js",
    "toolViewCsp": {
        "script-src": "'unsafe-inline'",
        "style-src": "'unsafe-inline'",
        "connect-src": "http 'unsafe-inline' ws: 'self'",
        "default-src": "self"
    }
}

And this my devproxy.json

{
    "$schema": "https://i2group.github.io/notebook-sdk/schemas/devproxy.json",
    "server": "https://i2analyze.eia:9443/opal/",
    "port": 4002,
    "plugins": ["http://localhost:5173/opal/plugins/react-neovis-plugin/"],
    "skipHttpsCertificateVerification": true
  }
Tim-Mawson-i2 commented 7 months ago

You could try forcing the Vite HMR websocket to connect to the same port as the Vite HTML server - try the adding the following to the config in vite.config.ts

export default defineConfig({
  ...
  server: {
    hmr: {
      protocol: 'ws',
      port: 5173
    }
  }
  ...
})
stvdo commented 7 months ago

@Tim-Mawson-i2 thanks that fixed that error indeed but the next one is popping up. Sorry for bothering you again.

Is there some learning path, it feels like I'm running from one wall into another..

image

Jaravee-Srilapan-i2 commented 7 months ago

Hi @sdorresteijn88, looking at the screenshot above, could you kindly review you connect-src directive for me please. If it still includes ws: it might be redundant since it has been set as protocol: 'ws' in vite.config.ts so could you try remove the ws: e.g. "connect-src": "http 'unsafe-inline'".

stvdo commented 7 months ago

@Jaravee-Srilapan-i2 I removed the ws: but than I get this error in the DevConsole

image

Jaravee-Srilapan-i2 commented 7 months ago

@sdorresteijn88 The error is to do with the browser's Content Security Policy (CSP), which restricts the establishment of a WebSocket connection that Vite development server is attempting to use for Hot Module Replacement (HMR).

While the error is present in the console, I believe it can be ignore and it won't stop the plugin from working.

stvdo commented 7 months ago

@Jaravee-Srilapan-i2 when I keep it open it keeps giving that error and the plugin page is flashing.

image plugin-neovis-react-Copy.zip

Jaravee-Srilapan-i2 commented 7 months ago

@sdorresteijn88 thank you for sharing the plugin code. I've been exploring various configurations from the Vite documentation, and I find it a bit confusing.

Here are the modifications I made based on the code you provided:

Approach 1 I set server.strictPort = true and ensured that server.hmr.clientPort is set to the same as server.port, which is explicitly set to 5173.

// In vite.config.ts
export default defineConfig({
  ...
  server: {
    port: 5173,
    strictPort: true,
    hmr: {
      clientPort: 5173,
      protocol: 'ws',
    }
  }
});

// In plugin.json
"toolViewCsp": {
    "script-src": "'unsafe-inline'",
    "style-src": "'unsafe-inline'",
    "connect-src": "ws://localhost:5173/opal/"
}

Approach 2 I set up the HMR to work on a separate port, specifically 5174, rather than sharing the same port as the server, which is 5173. I also adjusted the connect-src in the Content Security Policy to permit connections from ws://localhost:5174/opal/.

// In vite.config.ts
export default defineConfig({
  ...
  server: {
    hmr: {
      port: 5174,
      protocol: 'ws'
    }
  }
});

// In plugin.json
"toolViewCsp": {
    "script-src": "'unsafe-inline'",
    "style-src": "'unsafe-inline'",
    "connect-src": "ws://localhost:5174/opal/"
}

image

stvdo commented 7 months ago

@Jaravee-Srilapan-i2 thank you for the provided options! That solved my issues!

Maybe a question with is off topic. Below is my initial setup. The issue I had was that I couldn't import the i2 Notebook API in the popup.js (copyToChart function). Therefore I tried it with the React setup. Should it be possible to call the i2 Notebook API from the popup.js to add e.g. Person entities to the chart?

neovis-plugin - Copy.zip

Tim-Mawson-i2 commented 7 months ago

@sdorresteijn88 If your popup.js is part of your toolview, so you would normally call the getToolViewApi() function, which is provided by the SDK package and would normally be "bundled" into your output Javascript using the dev-environment (using webpack, or rollup etc.). As you're in a completely native "vanilla" environment, you'll need to grab the api object directly from the window object, using something like the following code:

function getToolViewApi() {
  return new Promise((resolve) => {
    function scan() {
      const api = window._i2GetToolViewApi;

      if (api) {
        clearInterval(handle);
        const result = api(apiVersion);
        resolve(result);
      }
    }
    const handle = setInterval(scan, 50);
    scan();
  });
}

This basically scans the window object for the api object, waiting for it to become available, and then returning it in a Promise.

stvdo commented 7 months ago

@Tim-Mawson-i2 thanks a lot for the detailed answer!