CORS Issues with zrok

Hi!

I have a problem with setting up a public share - would greatly appreciate some help!

I am running a FastAPI server in Docker and want to expose it using ZROK since my server is behind a firewall. I am using a free-tier service -- not self-hosting. Here is my docker-compose.yml (from the docs):

services:
  # set file ownership
  zrok-init:
    image: busybox
    # matches uid:gid of "ziggy" in zrok container image
    command: chown -Rc 2171:2171 /mnt/
    user: root
    volumes:
      - zrok_env:/mnt

  # enable zrok environment
  zrok-enable:
    image: ${ZROK_CONTAINER_IMAGE:-docker.io/openziti/zrok}
    depends_on:
      zrok-init:
        condition: service_completed_successfully
    entrypoint: zrok-enable.bash
    volumes:
      - zrok_env:/mnt
    environment:
      HOME: /mnt
      ZROK_ENABLE_TOKEN:
      ZROK_API_ENDPOINT:
      ZROK_ENVIRONMENT_NAME:

  # reserve zrok frontend subdomain and start sharing the target
  zrok-share:
    image: ${ZROK_CONTAINER_IMAGE:-docker.io/openziti/zrok}
    restart: unless-stopped
    entrypoint: zrok-share.bash
    depends_on:
      zrok-enable:
        condition: service_completed_successfully
    volumes:
      - zrok_env:/mnt
    environment:
      # internal configuration
      HOME: /mnt  # zrok homedir in container

      # most relevant options
      ZROK_UNIQUE_NAME:     # name is used to construct frontend domain name, e.g. "myapp" in "myapp.share.zrok.io"
      ZROK_BACKEND_MODE:    # web, caddy, drive, proxy
      ZROK_TARGET:          # backend target, is a path in container filesystem unless proxy mode
      ZROK_INSECURE:        # "--insecure" if proxy target has unverifiable TLS server certificate
      ZROK_OAUTH_PROVIDER:  # google, github
      ZROK_OAUTH_EMAILS:    # allow space-separated list of OAuth email address glob patterns
      ZROK_BASIC_AUTH:      # username:password, mutually-exclusive with ZROK_OAUTH_PROVIDER

      # least relevant options
      ZROK_VERBOSE:           # "--verbose"
      ZROK_SHARE_OPTS:        # additional arguments to "zrok reserve public" command
      ZROK_FRONTENDS:         # "public"
      PFXLOG_NO_JSON: "true"  # suppress JSON logging format

  web:
    # My FastAPI service...
    ports:
      - "8000:8000"

volumes:
  zrok_env:

Also, here is my .env:

ZROK_ENABLE_TOKEN="my-token"
ZROK_TARGET="http://web:8000"

ZROK_UNIQUE_NAME="my-anonymous-unique-name"
ZROK_INSECURE="--insecure"
ZROK_BACKEND_MODE="proxy"

Now, I have a JS frontend (Angular specifically) that is consuming my API. Unfortunately, I am running into CORS issues. I set up the FastAPI CORS middleware + I don't see a log indicating that request even reached the FastAPI. There is also no ZROK log I see when the request is sent. The endpoint works well when using curl or some other client. Only thing I see is the CORS issue in the browser.

Thank you for help in advance!

Are you sure you're not running into the interstitial with your JS frontend client? A public share accessed by a web browser on a free-tier share will encounter the interstitial page before it will hit your endpoint.

curl will not encounter the interstitial because it offers a User-Agent string that does not start with Mozilla/5.0.

Hi! I am quite sure, I am adding the header skip_zrok_interstitial: true to the request. I tried matching the headers (including User-Agent) with curl and it seems to work.

However, I think I am encountering the interstitial page with my OPTIONS request. I noticed that I get 200 back when OPTIONS is sent while I see no log on the server side. I am not sure how to bypass this since I can't modify the pre-flight request -- as far as I know?

EDIT:
I replicated the OPTIONS request with curl, getting the interstitial. It seems like there is no way to bypass this, since my browser sends these requests automatically. If this is the case, the free tier is not really usable/useful if you want to have a client app in JS since OPTIONS will always return interstitial? I really hope there exists a solution to this. :thinking:

@michael.quigley do you have any thoughts or ideas?

We'll do some investigation on our side and see what we can figure out.

Just ran a quick test in my local development environment, duplicating your findings. It looks like something is going on with OPTIONS and properly bypassing the interstitial.

Will see if I can put together a fix today.

I think that OPTIONS requests can't be modified, they are sent by the browser. Client can't modify this request.

I think it would make sense to disable the interstitial for OPTIONS requests, but I might be missing the full picture.

That's probably the fix. Investigating.

1 Like

The fix is committed and merged. Will come out with the v0.4.43 release, and will be available once that release is promoted to production.

Appreciate you reaching out...

1 Like