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

Docs on CORS? #285

Closed
jdkealy opened this issue Jan 3, 2017 · 3 comments
Closed

Docs on CORS? #285

jdkealy opened this issue Jan 3, 2017 · 3 comments

Comments

@jdkealy
Copy link

jdkealy commented Jan 3, 2017

Hello!

This is somewhat of a loaded question, but, I'm using a load balancer in production. To avoid the confusion of having clients connected to multiple different servers and having their UIDs stored in different atoms, I decided to make a single websocket server, and have the users connect to that server's websocket.

The code looks something like this:

(sente/make-channel-socket-client!
        "/chsk" ; Must match server Ring routing URL
        {:type   rand-chsk-type
         :host (host-url)
         :with-credentials? true
         :packer packer})

It's unclear to me though what else I'm supposed to be doing.
I changed nginx conf on my server and I keep getting

"Error during WebSocket handshake: Unexpected response code: 200"

Do you have any guidance on using CORS? Or generally about how to work with load balanced applications (if not using CORS)

Many thanks!

@danielcompton
Copy link
Collaborator

Hey, there's not enough information here to diagnose what's going on. The error message shown doesn't mention CORS at all, what makes you think CORS is the issue here? Can you share more details on your nginx configuration, screenshots of the attempted request from the browser, e.t.c.

Also, can you test this with the sample Sente app as it is a known-good application?

@jdkealy
Copy link
Author

jdkealy commented Jan 4, 2017

Hi!

Thanks for getting back to me :)

After tinkering all day, I've got this ALMOST working. My Nginx config is as follows. I'm using an upstream proxy.

upstream clj_proxy {
    server 0.0.0.0:3000;
}

server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        root /usr/share/nginx/html;
        index index.html index.htm;
        server_name localhost;

        location / {
            try_files $uri @my-app;
        }

        location /chsk {
          try_files $uri @my-app;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_set_header Host $host;
        }

        location @my-app {
                if ($request_method = 'OPTIONS') {
                        add_header 'Access-Control-Allow-Credentials' "true";
                        add_header 'Access-Control-Allow-Origin' 'http://my.com';
                        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
                        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Access-Control-Allow-Origin';
#
# Tell client that this pre-flight info is valid for 20 days
#
                        add_header 'Access-Control-Max-Age' 1728000;
                        add_header 'Content-Type' 'text/plain charset=UTF-8';
                        add_header 'Content-Length' 0;
                        return 204;
                }
                if ($request_method = 'POST') {
                        add_header 'Access-Control-Allow-Credentials' "true";
                        add_header 'Access-Control-Allow-Origin' 'http://my.com';
                        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Access-Control-Allow-Origin';
                }
                if ($request_method = 'GET') {
                        add_header 'Access-Control-Allow-Credentials' "true";
                        add_header 'Access-Control-Allow-Origin' 'http://my.com';
                        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Access-Control-Allow-Origin';
                }
                proxy_pass http://clj_proxy;
        }
}

For just a proof of concept -- since cross domain sessions are also tricky -- I've also tried just setting the user id in a get request during the initial handshake.

(let [;; For this example, select a random protocol:
      rand-chsk-type (if (>= (rand) 0.5) :ajax :auto)

      ;; Serializtion format, must use same val for client + server:
      packer :edn ; Default packer, a good choice in most cases
      ;; (sente-transit/get-transit-packer) ; Needs Transit dep

      {:keys [chsk ch-recv send-fn state]}
      (sente/make-channel-socket-client!
        "/chsk" ; Must match server Ring routing URL
        {:type   rand-chsk-type
         :params {:uid (-> @auth/c :db/id)}
         :host (host-url)
         :ajax-opts {:with-credentials? true}
         :packer packer})]

  (def chsk       chsk)
  (def ch-chsk    ch-recv) ; ChannelSocket's receive channel
  (def chsk-send! send-fn) ; ChannelSocket's send API fn
  (def chsk-state state)   ; Watchable, read-only atom
  )

The thing is that this response
"client-id=ac547d6e-cf64-452a-804a-5e559f1d0d91' failed: Error during WebSocket handshake: Unexpected response code: 200" is intermittent, sometimes working sometimes not, perhaps due to the line.

rand-chsk-type (if (>= (rand) 0.5) :ajax :auto)

Again this is just for proof of concept, I've modified the :user-id-fn to take whatever id is passed in as a GET param

(let [;; Serializtion format, must use same val for client + server:
      packer :edn ; Default packer, a good choice in most cases
      ;; (sente-transit/get-transit-packer) ; Needs Transit dep

      chsk-server
      (sente/make-channel-socket-server!
       (get-sch-adapter) {:user-id-fn (fn [{:keys [params]}]
                                        (if-let [uid (-> params
                                                         :uid)]
                                          (read-string uid)))
                          :packer packer})

      {:keys [ch-recv send-fn connected-uids
              ajax-post-fn ajax-get-or-ws-handshake-fn]}
      chsk-server]

  (def ring-ajax-post                ajax-post-fn)
  (def ring-ajax-get-or-ws-handshake ajax-get-or-ws-handshake-fn)
  (def ch-chsk                       ch-recv) ; ChannelSocket's receive channel
  (def chsk-send!                    send-fn) ; ChannelSocket's send API fn
  (def connected-uids                connected-uids) ; Watchable, read-only atom
  )

As the "200" error is intermittent, I've gotten it to a place where evaluating @connected-uids actually shows something

#atom[{:ws #{:taoensso.sente/nil-uid 17592186045662}, :ajax #{17592186045662}, :any #{:taoensso.sente/nil-uid 17592186045662}} 0x13f1721c]

But pushing to one of the connected ids times out

(chsk-send! 17592186045662 [:make/joke  "why did the chicken cross the road?"])

17-01-04 00:35:25 Johns-MacBook-Pro.local DEBUG [taoensso.sente:668] - close-timeout: :ajax 17592186045662 18da76 [false 1483490122338 1483490120672]17-01-04 00:35:25 Johns-MacBook-Pro.local DEBUG [taoensso.sente:668] - close-timeout: :ajax 17592186045662 fa5bb7 [false 1483490125380 1483490120672]17-01-04 00:35:25 Johns-MacBook-Pro.local DEBUG [taoensso.sente:668] - close-timeout: :ajax 17592186045662 17d96e [false 1483490122551 1483490120672]

I started with the example app and everything worked fine until I ran into load balancer issue and tried to go down the CORS route.

@ptaoussanis
Copy link
Member

Any updates on this issue? Can it be closed? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants