Docly Developers
DocsUpdated 23 Oct 2026

Setting up CORS for a Docly website

This document provides a step-by-step guide on how to configure Cross-Origin Resource Sharing (CORS) for your Docly website, enabling secure interactions with resources from different origins.

Understanding CORS and Its Importance

CORS is essential for web applications that need to make controlled cross-origin requests. For example, when you are creating an API that a website/webapp on another domain wants to access.

  • Security: CORS helps protect users by preventing malicious websites from making unauthorized requests to your domain

  • Controlled access: You can explicitly define which origins can access your resources

  • API integration: Allows your Docly site to securely interact with external APIs

Below is a reference table of the key CORS HTTP headers and their purposes:

HTTP Header

Purpose

Access-Control-Allow-Origin

Controls which origins can access your resources

Access-Control-Allow-Methods

Specifies which HTTP methods are permitted

Access-Control-Allow-Headers

Defines which headers can be included in requests

Prerequisite: Where CORS headers are set

CORS headers are ordinary response headers. For a single site, put them in the headers property of #/site.json. In an app, or for headers every site on a template should share, use #/headers.json. Both take the same header names and values; if a header is set in both, headers.json wins. See Security Headers in the headers.json file.

{
    "headers": {
        "X-Custom-Header": "My custom value"
    }
}

Each key is a header name and its value is the header value. The headers are added to every response from the site, including Docly's answer to preflight requests (see Troubleshooting below).

Step-by-Step: Configuring CORS Headers in Docly

Add the CORS headers to the headers property in #/site.json (or to #/headers.json). Below are common configurations to suit different security needs.

>

Example 1: Allowing requests from a specific origin

This is the most secure approach if you know which domain(s) will be accessing your resources.

{
    "headers": {
        "Access-Control-Allow-Origin": "https://your-client-domain.com",
        "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
        "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With",
        "Access-Control-Max-Age": "86400",
        "Vary": "Origin"
    }
}

Explanation of this configuration:

  • Access-Control-Allow-Origin: "https://your-client-domain.com": Only allows requests originating from https://your-client-domain.com.

  • Access-Control-Allow-Methods: "GET, POST, OPTIONS": Permits GET, POST, and preflight OPTIONS requests.

  • Access-Control-Allow-Headers: "Content-Type, Authorization, X-Requested-With": Allows requests that include these headers.

  • Access-Control-Max-Age: "86400": Allows the browser to cache the preflight (OPTIONS) response for 24 hours.

  • Vary: "Origin": Advises caches that the response may differ based on the Origin request header, which is important for CORS.

The headers are static: every response gets the same value, so Access-Control-Allow-Origin can name only one origin.

>

Example 2: Allowing requests from any origin (use with extreme caution)

This configuration is less secure and should generally be avoided unless your resources are explicitly public and pose no security risk. If you need to support credentials (cookies, HTTP authentication), Access-Control-Allow-Origin: "*" is incompatible with Access-Control-Allow-Credentials: true.

{
    "headers": {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "GET, OPTIONS",
        "Access-Control-Allow-Headers": "Content-Type"
    }
}

If the headers property already contains other headers, add the CORS headers as new entries in the same object.

Verifying and Troubleshooting Your CORS Setup

After implementing CORS headers, it's crucial to test your configuration to ensure it works as intended and doesn't inadvertently block legitimate requests or expose resources too broadly.

>

Using Browser Developer Tools:

  • Make a cross-origin request from your client application (or a test page) to your Docly site.

  • Open your browser's Developer Tools (usually F12) and navigate to the 'Network' tab.

  • Examine the request that was made to your Docly site. Check its 'Response Headers' section. You should see the Access-Control-Allow-Origin and other CORS headers you configured.

  • Check the 'Console' tab for any CORS-related error messages. Browsers provide descriptive errors if a CORS request is blocked (e.g., "No 'Access-Control-Allow-Origin' header is present on the requested resource.").

>
  1. Using curl or similar tools:

You can send a request with a specific Origin header to simulate a cross-origin request:

curl -H "Origin: https://your-client-domain.com" -I https://your-docly-site.com/some-resource

Replace https://your-client-domain.com with the origin you intend to allow, and https://your-docly-site.com/some-resource with a URL on your Docly site.

The -I flag fetches headers only. Inspect the output for the CORS headers.

Common Troubleshooting Points:

  • Typos: Double-check header names and values in #/site.json or #/headers.json.

  • Specificity of Access-Control-Allow-Origin: If not using *, ensure the domain, protocol, and port (if non-standard) exactly match the Origin header sent by the client.

  • Preflight (OPTIONS) requests: Docly answers them itself with 204 No Content and the headers from #/headers.json and #/site.json, before any page or API script runs. The methods and headers the browser asks for must therefore be in those static headers - a header set with docly.setHeader() in an API function is not part of the preflight answer.

  • Caching: Browser or server-side caching might serve stale headers. Clear caches or use a private/incognito browsing window for testing. Remember the Access-Control-Max-Age directive for preflight response caching.

  • Proxies: If a CDN or reverse proxy sits in front of Docly, make sure it passes the CORS headers through and does not answer OPTIONS requests itself.