jgraph / docker-drawio

Dockerized draw.io based on whichever is the most secure image at the time.
GNU General Public License v3.0
1.48k stars 359 forks source link

PlantUML rendering error in self-contained mode behind Traefik reverse proxy #138

Open sdreger opened 8 months ago

sdreger commented 8 months ago

Preflight Checklist

Describe the bug I'm running Drawio as a docker container in self-contained mode + PlantUML container. Containers are behind a reverse proxy (Traefik 2).

docker-compose.yaml

version: '3.9'

services:
  traefik:
    container_name: traefik
    image: "traefik:2.10.4"
    ports:
      - 80:80 # HTTP
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    command: # CLI arguments
      - --global.checkNewVersion=true
      - --global.sendAnonymousUsage=false
      - --entryPoints.http.address=:80
      - --entryPoints.traefik.address=:8080
      - --api=true
      - --api.dashboard=true 
      - --api.disabledashboardad=true
      - --ping=true
      - --log=true
      - --log.level=DEBUG
      - --accessLog=true
      - --providers.docker=true
      - --providers.docker.endpoint=unix:///var/run/docker.sock
      - --providers.docker.exposedByDefault=false
      - --providers.docker.network=reverse_proxy
      - --providers.docker.swarmMode=false
      - --providers.docker.allowEmptyServices=true
    labels:
      - traefik.enable=true
      - "traefik.http.routers.api.rule=Host(`traefik.${DOMAIN_NAME}`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" # Define the subdomain for the traefik dashboard.
      - traefik.http.routers.api.service=api@internal # Enable Traefik API.
      - traefik.http.routers.api.middlewares=basic-auth-dashboard # enable basic auth middleware
      - traefik.http.middlewares.basic-auth-dashboard.basicauth.users=${TRAEFIK_HTTP_BASIC_AUTH}
    networks:
      reverse_proxy:
        ipv4_address: $TRAEFIK_STATIC_IP

  drawio:
    image: jgraph/drawio:22.1.7
    container_name: drawio
    environment:
      DRAWIO_SELF_CONTAINED: 1
      DRAWIO_BASE_URL: http://drawio.${DOMAIN_NAME}
      DRAWIO_SERVER_URL: http://drawio.${DOMAIN_NAME}/
      DRAWIO_VIEWER_URL: http://drawio.${DOMAIN_NAME}/js/viewer.min.js
      DRAWIO_LIGHTBOX_URL: https://drawio.${DOMAIN_NAME}/
      PLANTUML_URL: http://plantuml:8080/
    networks:
      - reverse_proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.drawio.rule=Host(`drawio.${DOMAIN_NAME}`)
      - traefik.http.services.drawio.loadbalancer.server.port=8080
    depends_on:
      - plantuml

  plantuml:
    container_name: plantuml
    image: plantuml/plantuml-server:jetty-v1.2023.12
    networks:
       - reverse_proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.plantuml.rule=Host(`plantuml.${DOMAIN_NAME}`)
      - traefik.http.services.plantuml.loadbalancer.server.port=8080

When I try to insert/update a PlantUML diagram, I'm getting an error:

image

The request fails with 500 error:

GET: http://drawio.myhome.lan/service/1/svg/XSz12i9038NX_PmY5vWBY4Zh4Rn1RACDJfCwoU3r6zHLANJzFdvudJbMRtD9zc9PiE8CDk6e7vOdFB0OfRxmG90lSDNx2Vhc4udpWCugSADt8_CK6-GmNxoZR569rZOc6gu2xaT_-9ppWVx7Ev8nhgm0

Status: 500 Internal Server Error
Response payload: Internal Server Error

To Reproduce Steps to reproduce the behavior:

  1. Go to: Arrange > Insert > Advanced > PlantUML...
  2. Paste the following diagram text:
    @startuml
    skinparam shadowing false
    Alice -> Bob: Authentication Request
    Bob --> Alice: Authentication Response
    @enduml
  3. Choose: PlantUML (SVG)
  4. Click: Insert
  5. Observe the error

Expected behavior The diagram is rendered without errors.

draw.io version (In the Help->About menu of the draw.io editor):

Desktop (please complete the following information):

I tested the problem in incognito/private mode with all browser extensions switched off, write "yes" below:

Additional context

The PlantUML insertion flow works fine without the reverse proxy. So I decided to investigate the error deeply, and found out that the error comes from the Traefik, because of:

time="2023-12-10T11:54:21+02:00" level=debug msg="'500 Internal Server Error' caused by: net/http: HTTP/1.x transport connection broken: too many transfer encodings: [\"chunked\" \"chunked\"]"

This is the known issue, caused by a stricter check on the Transfer-Encoding header in Go v1.15 which was then brought in Traefik 2.3 (https://github.com/traefik/traefik/issues/8623).

After I inspected the network traffic, I found out that the response from the PlantUML server contains 1 Transfer-Encoding header:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: image/svg+xml
Expires: Fri, 15 Dec 2023 08:35:53 GMT
Date: Sun, 10 Dec 2023 08:35:53 GMT
Last-Modified: Fri, 20 Oct 2023 13:49:00 GMT
Cache-Control: public, max-age=432000
ETag: "dc6acd2768ae3525b13eb106d18a704eqA-ueZWsK496IHumWV4J9m00"
X-PlantUML-Diagram-Description: (2 participants)
X-Powered-By: PlantUML Version 1.2023.12
X-Patreon: Support us on https://plantuml.com/patreon
X-Donate: https://plantuml.com/paypal
Transfer-Encoding: chunked
Server: Jetty(11.0.15)

CD6
<?xml version="1.0" encoding="us-ascii" standalone="no"?>
...

But the response from the Drawio server contains 2 Transfer-Encoding headers:

HTTP/1.1 200
Transfer-Encoding: chunked
Server: Jetty(11.0.15)
Access-Control-Allow-Origin: *
X-Patreon: Support us on https://plantuml.com/patreon
Last-Modified: Fri, 20 Oct 2023 13:49:00 GMT
Date: Sun, 10 Dec 2023 08:35:53 GMT
Cache-Control: public, max-age=432000
ETag: "dc6acd2768ae3525b13eb106d18a704eqA-ueZWsK496IHumWV4J9m00"
Expires: Fri, 15 Dec 2023 08:35:53 GMT
X-Donate: https://plantuml.com/paypal
X-PlantUML-Diagram-Description: (2 participants)
X-Powered-By: PlantUML Version 1.2023.12
Content-Type: image/svg+xml
Transfer-Encoding: chunked

cd6
<?xml version="1.0" encoding="us-ascii" standalone="no"?>
...

Having two Transfer-Encoding headers in the PlantUML server response causes the Traefik proxy to fail, making it impossible to use self-contained Drawio instance to render PlantUML, when running behind a Traefik reverse proxy (v2.3+).