Skip to content

Fix /output/ URL leak for blog posts with version numbers in slug #178

Description

@kevinjqliu

Problem

Some blog post URLs redirect through an internal /output/ path that should never be exposed to users.

Working URLs (slugs without dots):

Broken URLs (slugs with version numbers):

Every blog post with a version number in its slug (e.g. datafusion-comet-0.15.0) is affected. The /output/ URL still serves the page, but is not the canonical URL and causes subtle issues — for example, giscus CSP was not applying correctly on the /output/ path (see #80 (comment)).

Root Cause

There is a mismatch between publish-site.yml and .asf.yaml:

  • .asf.yaml on asf-site declares subdir: blog, telling ASF infrastructure to serve content from a blog/ subdirectory.
  • publish-site.yml does not set output: 'blog', so the pelican action defaults to output: 'output', putting built content into output/ instead of blog/.
# .asf.yaml (expects blog/)
publish:
  whoami: asf-site
  subdir: blog

# publish-site.yml (produces output/)
- uses: apache/infrastructure-actions/pelican@main
  with:
    destination: 'asf-site'
    gfm: 'false'
    # output: 'blog'   <-- MISSING

The staging workflow (stage-site.yml) already has output: 'blog' and works correctly.

To bridge this mismatch, .htaccess on the asf-site branch has rewrite rules that internally map requests from blog/ to output/:

RewriteCond %{REQUEST_URI} !/output/
RewriteRule ^(.*)$ output/$1 [L]

These rules also add a trailing-slash redirect for extensionless URLs, but skip URLs that "look like files":

RewriteCond %1 !\.[^./]+$

The regex \.[^./]+$ matches any dot followed by non-dot/non-slash characters at the end of the URL. This incorrectly matches .0 in version-number slugs like datafusion-comet-0.15.0, causing the trailing-slash redirect to be skipped. Apache's mod_dir then adds the trailing slash itself, but exposes the internal output/ prefix in the redirect Location header.

Fix

Add output: 'blog' to publish-site.yml to match stage-site.yml:

- uses: apache/infrastructure-actions/pelican@main
  with:
    destination: 'asf-site'
    gfm: 'false'
    output: 'blog'

This puts build output into blog/ on the asf-site branch, matching what .asf.yaml expects. The .htaccess rewrite rules become unnecessary.

Follow-up (after deploy)

After the first successful deploy with this fix, a separate PR to the asf-site branch should:

  1. Remove the stale output/ directory (all content will now be in blog/).
  2. Simplify .htaccess to remove the rewrite rules, keeping only the CSP directive:
SetEnv CSP_PROJECT_DOMAINS "https://giscus.app"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions