aisstream / issues

7 stars 3 forks source link

WebSocket never opens in browser #6

Closed MatrixFrog closed 1 year ago

MatrixFrog commented 1 year ago

I was able to get data from the API pretty easily by running the javascript example from the examples repo. But when I try to do the same thing in the browser (the only major difference being using the native WebSocket object instead of the ws npm package), the WebSocket never seems to open. I added another example that runs in-browser at https://github.com/aisstream/example/pull/3 , with lots of console.logs. The logging shows that the socket does get created, but its onopen never seems to run. I think I must be missing something obvious but I'm not sure what.

aisstream commented 1 year ago

Currently we do not support cross origin resource sharing (an overview on CORS found here https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). Browsers often require that the API you are accessing to support the CORS protocol if you are making a request/connection to a domain that is not the domain from which you are making the request. In your likely case the requesting domain localhost is not aisstream.io and thus it is a cross origin call. In addition we also filter and close cross origin requests at the gateway level which means disabling CORS in the browser will not cause the call to succeed. This explains why the connections are not opening in the browser as our service currently does not support CORS and thus does not support the browser.

It is our mistake for not documenting this as I am sure you are not the first person to run into this issue. We will work to rectify this issue shortly.

The obvious next question you likely have is why we would not want access from the browser. Our original reasons can be outlined below:

  1. API Keys were not meant to be shared on the open internet. If a user creates a site which connects directly to aisstream.io via their api key this key is now available on the internet to all consumers of their site to use and abuse. Our desired design pattern is if a user wants to use aisstream.io in a web application, they consume the websocket on their backend and deliver the data to their clients via connections they control. This keeps the api key away from the open internet.

  2. We have throttling at the api key and user level. Your users may be throttled if your app becomes popular and have many concurrent connections with the same api key.

We also understand this places some restrictions on the user who want's to consume aisstream.io in the browser for their own personal use. However, to avoid the issues above we are concurrently configured to not allow browser based connections.

We will reflect on this use case a bit and see if we can find other solutions that address the issues noted above. Is running the connection in the browser a requirement of your use case ?

MatrixFrog commented 1 year ago

Okay that makes sense. I can find a way to make it work without trying to connect from the browser directly. Thanks!

aisstream commented 1 year ago

Thank you for bringing this to our attention, this will be added to the documentation shortly.

Your PR with a browser example is a good idea, just currently your example will need to be enhanced with a proxy/backend of some sort. We will ensure you get credit when a browser example is created.

MatrixFrog commented 1 year ago

In addition to updating documentation, it would be great if trying to connect from the browser resulted in a clear error message instead of it just seeming to be broken.

aisstream commented 1 year ago

Documentation has been updated.

In terms of an error message when a cross origin request is blocked we return a 401 Status Code and brief error message. Reviewing the message it does appear to not mention browser access and thus we will change it.

I tried your CR which access asistream.io from the browser.It appears that since the websocket is sending a upgrade requests (upgrading the http connection to websocket) it is not expecting to receive http headers back and thus is failing to display the message. We will investigate further to see how we can improve this.

aisstream commented 1 year ago

Action items:

SpencerMartel commented 1 year ago

Jumping off of this as I also experienced the silent fail, it makes sense that the API key wouldn't be available on a public browser. If I want to use AISStream to feed a stream of data to a client how do you suggest I do it? Create a backend that handles the websocket to AISStream and another to then send that stream to the client? Or is this not an intended use case for the service?

aisstream commented 1 year ago

Sorry for the late reply this notification slipped through.

Yes, creating your own backend that consumes aisstream.io's websocket feed and then delivering it to your clients however you wish (websocket, http, grpc, or what ever method you can think of) from said backend is how we intend applications to use aisstream.io.