Strange issue with json when reverse proxying between two Caddy instances

1. The problem I’m having:

I have encountered a strange issue when reverse proxying between two Caddy instances. It only affects some of my hosted services, specifically progressive web apps that use a manifest.json.

I have two Caddy instances - one of the instances is internet facing and the other is on an internal network. When accessing a service from the outside, the internet-facing Caddy instance reverse proxies to the internal Caddy instance. The hostname for a particular service is the same for both internal and external and this is accomplished using a split-horizon DNS. Anyhow, without getting into too many details, let me just get right to the issue.

Let’s say I have two services, and for the sake of this example, we will call service one: Compact-JSON, and service two: Formatted-Json. On the internet-facing Caddy instance, they would appear as following in the Caddyfile:

https://compact-json.example.com {
  import safe-header
  reverse_proxy https://compact-json.example.com {
    import sn-resolver
  }
}

https://formatted-json.example.com/ {
  import safe-header
  reverse_proxy https://formatted-json.example.com {
    import sn-resolver
  }
}

If I run a curl https://compact-json.example.com/manifest.json on the internal Caddy instance, I get the following:

{"name":"Compact-JSON","short_name":"Compact-JSON","icons":[{"src":"https://compact-json.example.com/packs/media/icons/android-chrome-36x36-4c61fdb42936428af85afdbf8c6a45a8.png","sizes":"36x36","type":"image/png","purpose":"any maskable"},{"src":"https://compact-json.example.com/packs/media/icons/android-chrome-48x48-2027aead76dc906c981043d658a8258d.png","sizes":"48x48","type":"image/png","purpose":"any maskable"},{"src":"https://compact-json.example.com/packs/media/icons/android-chrome-72x72-799d90b81f5b28cea7355a0c0b356381.png","sizes":"72x72","type":"image/png","purpose":"any maskable"},{"src":"https://compact-json.example.com/packs/media/icons/android-chrome-96x96-c2dfcfa1268c56e59edddfe20d818b91.png","sizes":"96x96","type":"image/png","purpose":"any maskable"},{"src":"https://compact-json.example.com/packs/media/icons/android-chrome-144x144-ff3110f7772743bdd0c1c47fb7b2d4e0.png","sizes":"144x144","type":"image/png","purpose":"any maskable"},{"src":"https://compact-json.example.com/packs/media/icons/android-chrome-192x192-eddc1ed540e97b926202b7b857989d60.png","sizes":"192x192","type":"image/png","purpose":"any maskable"},{"src":"https://compact-json.example.com/packs/media/icons/android-chrome-256x256-7b2b43926019259f7c9ddee627d80a0f.png","sizes":"256x256","type":"image/png","purpose":"any maskable"},{"src":"https://compact-json.example.com/packs/media/icons/android-chrome-384x384-72068ed50b02828fc505a8d69b321dea.png","sizes":"384x384","type":"image/png","purpose":"any maskable"},{"src":"https://compact-json.example.com/packs/media/icons/android-chrome-512x512-ccb53c9fcbb5f61bf741cc54998318f0.png","sizes":"512x512","type":"image/png","purpose":"any maskable"}],"theme_color":"#191b22","background_color":"#191b22","display":"standalone","start_url":"/home","scope":"/","share_target":{"url_template":"share?title={title}\u0026text={text}\u0026url={url}","action":"share","method":"GET","enctype":"application/x-www-form-urlencoded","params":{"title":"title","text":"text","url":"url"}},"shortcuts":[{"name":"Compose new post","url":"/publish"},{"name":"Notifications","url":"/notifications"}]}

If I run a curl https://formatted-json.example.com/manifest.json on the internal Caddy instance, I get the following:

{
  "name": "Formatted-Json",
  "short_name": "Formatted-Json",
  "icons": [
    {
      "src": "/android-icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/android-icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff", 
  "theme_color": "#000000"
}

As you can see, with the Compact-JSON service, the json result is one single line with no spaces or carriage returns. However, with the Formatted-Json service, the json result has spacing and carriage returns, i.e. it comes through formatted.

In both cases, everything works great internally, the services render correctly in the browser.

When I run the same two curl commands externally, the Compact-JSON returns the same result, a compacted json just like internally. The service works via external access and everything renders correctly in the browser.

However, when I run it on the Formatted-Json service externally, the curl command returns nothing.

How can I configure the external Caddy instance to pass the formatted json through the same way? My guess is that it is encountering a carriage return and terminating the request.

I have tried putting

  header "/*.json" {
    Content-Type application/json
  }

on both internal and external, but it did not change anything for the Formatted-Json service. It still returns nothing.

2. Error messages and/or full log output:

N/A

3. Caddy version:

2.7.6 for both instances.

4. How I installed and ran Caddy:

a. System environment:

Docker, Linux Ubuntu 22.04

b. Command:

N/A

c. Service/unit/compose file:

N/A

d. My complete Caddy config:

See above

5. Links to relevant resources:

Okay, nevermind, I am a complete idiot. I spent a half hour writing up this message, and after reading back through it, I found my issue… :person_facepalming:

There was a trailing slash on the formatted json service. It works fine after cleaning that up.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.