puma / puma-dev

A tool to manage rack apps in development with puma

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CORS errors in development caused by puma-dev serving public files directly

Pezmc opened this issue · comments

When using a symlink, puma-dev serves files from the public directory that exist directly without proxying the request (added in 49fdcf3 to address #44):

puma-dev/dev/http.go

Lines 150 to 157 in 458cc5c

if app.Public && req.URL.Path != "/" {
safeURLPath := path.Clean(req.URL.Path)
path := filepath.Join(app.dir, "public", safeURLPath)
fi, err := os.Stat(path)
if err == nil && !fi.IsDir() {
if ofile, err := os.Open(path); err == nil {
http.ServeContent(w, req, req.URL.Path, fi.ModTime(), io.ReadSeeker(ofile))

Unfortunately, this is causing issues in development for any scripts loaded using type=module built by webpacker that are served from a different subdomain. When not running ./bin/webpack-dev-server, rails runs ./bin/webpack internally, which puts scripts in the public/packs/ folder. Puma-dev is serving these directly meaning any middleware that sets up CORS headers isn't running.

An option to turn off direct serving of files from public/ or another way to force those files to be served via rails (so middleware runs), is one option to resolve this issue.


For example our setup is as follows:

  • config/development.rb adds a middleware that sets Access-Control-Allow-Origin: * to all .js files
  • Assets are served from cache subdomain using config.action_controller.asset_host = 'cache.exampleapp.localhost'
  • A JS file, built by webpacker, is added to the page on a subdomain using type=module (javascript_pack_tag :script, type: 'module')
  • puma-dev is setup using puma-dev link in the exampleapp directory
  • On boot, rails runs ./bin/webpack which puts files under exampleapp/public/packs/
  • puma-dev serves those files directly, rather than them going via the middleware
  • app falls over with the below error:
Access to script at 'https://cache.exampleapp.localhost/packs/js/reports/script-9ba4a6d41b4d049ca1fa.js' from origin 'https://main.exampleapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
filter:1463 GET https://cache.exampleapp.com/packs/js/reports/script-9ba4a6d41b4d049ca1fa.js net::ERR_FAILED```

An option to turn off direct serving of files from public/ or another way to force those files to be served via rails (so middleware runs), is one option to resolve this issue.

A -no-serve-public flag to opt-out of serving seams straightforward enough, esp if you're ok with disabling it globally. Do you expect all apps running under puma-dev to behave this way?

@nonrational In our particular case, disabling globally is likely going to be fine; however I do wonder if more and more people are going to start hitting similar problems now webpacker is the default for Rails!

Maybe providing a matcher like -ignored-static-paths='/public/packs:/public/foo' would be better. We could decide to make the default value non-empty at a later date. And, you could disable it entirely with -ignored-static-paths='/public'

I think that's a great approach!

@nonrational Is there any way I can help here? The team impacted by the above is still a frustrating work around and I'd love to try and sort it out!

@Pezmc #262 will allow you to set -no-serve-public-paths='/packs'.

Are you able to build a binary from that branch and test it out?

Sorry for the delay I saw your PR but I've been away, looking into it now!

Hmm, I uninstalled the old binary using:

puma-dev -stop

Then built a binary of this branch with

make && make install

Then ran:

./puma-dev -install  -d test:localhost -no-serve-public-paths .

Checking ~/Library/LaunchAgents/io.puma.dev.plist I didn't see the argument added, so I modified the file to:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
   <key>Label</key>
   <string>io.puma.dev</string>
   <key>ProgramArguments</key>
   <array>
     <string>/Users/pezcuckow/Git/puma-dev/puma-dev</string>
     <string>-launchd</string>
     <string>-dir</string>
     <string>~/.puma-dev</string>
     <string>-d</string>
     <string>test:localhost</string>
     <string>-timeout</string>
     <string>15m0s</string>
     <string>-no-serve-public-paths</string>
     <string>.</string>
   </array>
...

And restarted the launch agent:

$ launchctl unload ~/Library/LaunchAgents/io.puma.dev.plist
$ ./puma-dev -stop
$ launchctl load ~/Library/LaunchAgents/io.puma.dev.plist

And I'm still seeing the same CORS errors where files in /public appear to be being served by Puma:

Screenshot 2020-10-26 at 19 05 55

Note no CORS headers, files served by Rails look like this:

Screenshot 2020-10-26 at 19 10 37

Note the Access-Control-Allow-Origin: *

Perhaps I've configured Puma-Dev wrong?

@Pezmc #262 will allow you to set -no-serve-public-paths='/packs'

You need to provide an argument (a : separated string of paths like /packs:/foo:/bar:/baz) to the flag.

However, I neglected to update the plist template to ensure that this config will be respected by -install. As is, It will only work in the foreground. 😅

Aah, I thought -no-serve-public-paths . would pass that, trying again!

I'm surprised it didn't work when I manually modified the plist though!

Confirmed working, I opened a PR to add the plist support and some simple logging of the new option: #263