Applying cors to a single path

1. Caddy version (caddy version):

2.3

2. How I run Caddy:

running at
staging.minty.art
docs.minty.art

a. System environment:

Ubuntu 18.04
Installed as service

b. Command:

sudo systemctl restart caddy.service

c. Service/unit/compose file:

paste full file contents here

d. My complete Caddyfile or JSON config:

(cors) {
	@origin header Origin {args.0}
	header @origin Access-Control-Allow-Origin "{args.0}"
}

docs.minty.art {

    basicauth * {
	developers  <hash>
   }
   reverse_proxy * localhost:8007
   log {
	output file /var/log/docs.log
   }

}


staging.minty.art {
   @back-end {
      path /api/*
   }
   @admin {
      path /admin/*
   }
   handle @back-end {
      reverse_proxy /api/* localhost:8082
   }
   handle @admin {
      reverse_proxy /admin/* localhost:8082
   }
   handle {
     root * /var/www
     file_server

     try_files {path} /index.html
   }
   import cors https://staging.minty.art/api/*
   log {
	output file /var/log/caddy.log
   }

}

3. The problem I’m having:

I am trying to cors enable the /api/ folder on staging.minty.art

e.g. POST /api/USER/read

{
    "address": "0x31EFd75bc0b5fbafc6015Bd50590f4fDab6a3F22"
}

4. Error messages and/or full log output:

Does not seem to send the cors headers

Works in postman but cors header not received.

Caddy sends a 200 OK

5. What I already tried:

import cors https://staging.minty.art/api/*
import cors /api/*

6. Links to relevant resources:

According to Origin - HTTP | MDN the Origin header never contains a path component, so I don’t think https://staging.minty.art/api/* will work. Instead I think you need to use https://staging.minty.art.

If you need to only set the header on a certain path, then you’ll want to change your @origin matcher to match on the request path.

So instead of @origin header Origin {args.0} which would be a tautology, you would instead do @origin path {args.1} and then invoke it with import cors https://staging.minty.art /api/*. The space before the path there is important since those are two separate args.

Here’s a quick tip to clean up your Caddyfile:

This can be reduced to:

   @backend path /api/* /admin/*
   handle @backend {
      reverse_proxy localhost:8082
   }
1 Like

Apologies - I was not clear in what I am trying to do.
I am trying to make the /api/* folders available for general consumption - not restricted to the local machine.

I was trying to restrict setting cors headers to just those API endpoints so I want to get a header of

Access-Control-Allow-Origin *

Ah ok, cause:

You’re using {args.0} for the header value there as well. You probably meant to set * there then.

But what I said still stands, Origin won’t contain a path, so your matcher won’t match.

I have tried this with
import cors *
and the version you see here and I am still getting no joy.

(cors) {
	@origin header Origin {args.0}
	header @origin Access-Control-Allow-Origin "*"
}

docs.minty.art {

    basicauth * {
	developers <hash>
   }
   reverse_proxy * localhost:8007
   log {
	output file /var/log/docs.log
   }

}

staging.minty.art {
   @back-end path /api/* /admin/*
   handle @back-end {
      reverse_proxy localhost:8082
   }
   handle {
     root * /var/www
     file_server
     try_files {path} /index.html
   }
   import cors https://staging.minty.art
   log {
	output file /var/log/caddy.log
   }
}

Does your request include Origin when you’re making it with postman as you said? I don’t think postman will include that by default, but browsers would.

I was also testing from

https://www.test-cors.org/

but I added it to Postman too and I still don’t get the header in the reply.

The log shows that the request was received

       "headers": {
            "Accept-Encoding": [
                "gzip, deflate, br"
            ],
            "Content-Length": [
                "63"
            ],
            "User-Agent": [
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Safari/537.36"
            ],
            "Origin": [
                "https://www.test-cors.org"
            ],

likewise from Postman

Ok - I found a really simple solution :slight_smile:

Back to the first version of separating the two paths and for the api path simply send the header!

   handle @back-end {
      reverse_proxy localhost:8082

      header Access-Control-Allow-Origin "*"
   }
1 Like

I would really like to thank you for your help here.

You helped me understand the Caddyfile better and I would not have got this working without it.

2 Likes

FYI you could write it like this probably, if you only want it for /api/*:

header /api/* Access-Control-Allow-Origin "*"

@back-end path /api/* /admin/*
handle @back-end {
	reverse_proxy localhost:8082
}

:blush:

1 Like

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