tobychui / zoraxy

A general purpose HTTP reverse proxy and forwarding tool. Now written in Go!
https://zoraxy.aroz.org
GNU Affero General Public License v3.0
3.09k stars 188 forks source link

[HELP] Using with odoo > problem with the websocket #314

Open eqms opened 2 months ago

eqms commented 2 months ago

What happened? I try to use zoraxy with the erp system odoo

Describe what have you tried This is the setting at nginx


#odoo server
upstream odoo {
  server 127.0.0.1:8069;
}
upstream odoochat {
  server 127.0.0.1:8072;
}
map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

# http -> https
server {
  listen 80;
  server_name odoo.mycompany.com;
  rewrite ^(.*) https://$host$1 permanent;
}

server {
  listen 443 ssl;
  server_name odoo.mycompany.com;
  proxy_read_timeout 720s;
  proxy_connect_timeout 720s;
  proxy_send_timeout 720s;

  # SSL parameters
  ssl_certificate /etc/ssl/nginx/server.crt;
  ssl_certificate_key /etc/ssl/nginx/server.key;
  ssl_session_timeout 30m;
  ssl_protocols TLSv1.2;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  # log
  access_log /var/log/nginx/odoo.access.log;
  error_log /var/log/nginx/odoo.error.log;

  # Redirect websocket requests to odoo gevent port
  location /websocket {
    proxy_pass http://odoochat;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
    proxy_cookie_flags session_id samesite=lax secure;  # requires nginx 1.19.8
  }

  # Redirect requests to odoo backend server
  location / {
    # Add Headers for odoo proxy mode
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_redirect off;
    proxy_pass http://odoo;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
    proxy_cookie_flags session_id samesite=lax secure;  # requires nginx 1.19.8
  }

  # common gzip
  gzip_types text/css text/scss text/plain text/xml application/xml application/json application/javascript;
  gzip on;
}

My problem is the location /websocket

I didn't find a way to configure this in zoraxy. (Zoraxy - Version 3.1.1) image

I am using docker

image

tobychui commented 2 months ago

@eqms Have you tried using Virtual Directory?

As shown here, this seems like a virtual directory to me

location /websocket {
    proxy_pass http://odoochat;
    ...
}

location / {
...
proxy_pass http://odoo;
}

You should add a Virtual Directory to your proxy rule and set /websocket to http://odoochat. Websocket protocol is switched automatically in Zoraxy when the Upgrade header is detected. So there should be no additional config required for websocket settings.

eqms commented 2 months ago

Thanks for the response.

I tried this also.
image Odoo runs in a docker container.
in this example 8069 will expose to 13000 and 8072 to 14000.
But it didn't work like with nginx.
image

eqms commented 2 months ago
CONTAINER ID   IMAGE                                                    COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
xxxxxxxxxx   odoo/test                                                "/app/bin/boot start"    13 minutes ago   Up 13 minutes   127.0.0.1:13000->8069/tcp, 127.0.0.1:14000->8072/tcp   test-odoo
│   RuntimeError: Couldn't bind the websocket. Is the connection opened on the evented port (8072)?                                                                                                  │
│   2024-09-24 10:06:33,154 13 ERROR ? longpolling: <gevent._socket3.socket at 0x7fdf0c2a25c0 object, fd=8, family=2, type=1, proto=0>: Invalid HTTP method: "\x16\x03\x01\x01\x00\x01\x00\x00ü\x    │
│   03\x03ìÈ®Ý!\x8cåt;ShÐ\x00µuÚ¦'2\x1dK{,g¦áb\x16[!\x11Ò öõ\x8d\x18Ò\x07\x96à \x08\x02TÀ\x0f\x14\x1fþ\x83\x8c\tÍÚ>¾>^â´Ïß\x7f!\x00&À+À/À,À0̨̩À\tÀ\x13À\n"                                         │
│   2024-09-24 10:06:33,155 13 INFO ? longpolling: 172.20.0.1 - - [2024-09-24 10:06:33] "üìÈ®Ý!åt;ShеuÚ¦'2K{,g¦áb[!Ò öõÒà TÀþÍÚ>¾>^â´Ïß                                                             │
│   !&À+À/À,À0̨̩ÀÀÀ" 400 - 0.000447                                                                                                                                                                │
│   2024-09-24 10:06:33,168 13 INFO hilo_test longpolling: 172.20.0.1 - - [2024-09-24 10:06:33] "HEAD /websocket HTTP/1.1" 400 126 0.012380                                                          │
│   2024-09-24 10:06:33,330 13 INFO hilo_test longpolling: 172.20.0.1 - - [2024-09-24 10:06:33] "GET /websocket HTTP/1.1" 400 318 0.012827                                                           │
│   2024-09-24 10:07:12,550 13 ERROR hilo_test odoo.http: Exception during request handling.                                                                                                         │
│   Traceback (most recent call last):                                                                                                                                                               │
│     File "/opt/odoo/odoo-server/odoo/http.py", line 1666, in _serve_ir_http                                                                                                                        │
│       rule, args = ir_http._match(self.httprequest.path)                                                                                                                                           │
│                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                           │
│     File "/opt/odoo/odoo-server/addons/website/models/ir_http.py", line 176, in _match                                                                                                             │
│       return super()._match(path)                                                                                                                                                                  │
│              ^^^^^^^^^^^^^^^^^^^^                                                                                                                                                                  │
│     File "/opt/odoo/odoo-server/addons/http_routing/models/ir_http.py", line 501, in _match                                                                                                        │
│       rule, args = super()._match(path)                                                                                                                                                            │
│                    ^^^^^^^^^^^^^^^^^^^^                                                                                                                                                            │
│     File "/opt/odoo/odoo-server/odoo/addons/base/models/ir_http.py", line 96, in _match                                                                                                            │
│       rule, args = cls.routing_map().bind_to_environ(request.httprequest.environ).match(path_info=path_info, return_rule=True)                                                                     │
│                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                     │
│     File "/usr/local/lib/python3.11/site-packages/werkzeug/routing.py", line 2041, in match                                                                                                        │
│       raise NotFound()                                                                                                                                                                             │
│   werkzeug.exceptions.NotFound: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.                            │
│   2024-09-24T10:07:12.551418409Z                                                                                                                                                                   │
│   During handling of the above exception, another exception occurred:                                                                                                                              │
│   2024-09-24T10:07:12.551422818Z                                                                                                                                                                   │
│   Traceback (most recent call last):                                                                                                                                                               │
│     File "/opt/odoo/odoo-server/odoo/http.py", line 2063, in __call__                                                                                                                              │
│       response = request._serve_db()                                                                                                                                                               │
│                  ^^^^^^^^^^^^^^^^^^^                                                                                                                                                               │
│     File "/opt/odoo/odoo-server/odoo/http.py", line 1651, in _serve_db                                                                                                                             │
│       return service_model.retrying(self._serve_ir_http, self.env)                                                                                                                                 │
│              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                 │
│     File "/opt/odoo/odoo-server/odoo/service/model.py", line 133, in retrying                                                                                                                      │
│       result = func()                                                                                                                                                                              │
│                ^^^^^^                                                                                                                                                                              │
│     File "/opt/odoo/odoo-server/odoo/http.py", line 1669, in _serve_ir_http                                                                                                                        │
│       response = ir_http._serve_fallback()                                                                                                                                                         │
│                  ^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                         │
│     File "/opt/odoo/odoo-server/addons/website/models/ir_http.py", line 337, in _serve_fallback                                                                                                    │
│       redirect = cls._serve_redirect()                                                                                                                                                             │
│                  ^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                             │
│     File "/opt/odoo/odoo-server/addons/website/models/ir_http.py", line 307, in _serve_redirect                                                                                                    │
│       req_page_with_qs = request.httprequest.environ['REQUEST_URI']                                                                                                                                │
│                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^                                                                                                                                │
│   KeyError: 'REQUEST_URI
tobychui commented 2 months ago

@eqms I never used odoo before so I am not sure what is the issue here. You should be asking the odoo community about this instead. You can find the Zoraxy proxy log under the log/ folder and it might be able to tell you (and the community) what is happening between your Zoraxy instance and the upstream server.

eqms commented 2 months ago

The problem is that nobody use zoraxy with odoo. I am working with nginx and odoo over 10 years. The log of zoraxy: [websocket] [system:error] Couldn't dial to remote backend url ws://127.0.0.1:14000: websocket: bad handshake

On apache the solution for that:

    ProxyPass /websocket ws://127.0.0.1:14000/websocket
    ProxyPassReverse /websocket ws://127.0.0.1:14000/websocket

on nginx:

    location /websocket {
        proxy_redirect off;
        proxy_pass http://127.0.0.1:14000;
    }

Is there a way to do that on zoraxy also in the configfile?

tobychui commented 2 months ago

@eqms Have you tried just let Zoraxy handle the auto-detection for websocket?

Like you can just create a proxy rule that points odoo.yourdomain.com to 127.0.0.1:14000 and just let Zoraxy figure out the websocket protocol negotiation, with no websocket settings or virtual directory of any kind.