Skip to content

Conversation

@mttjohnson
Copy link
Collaborator

@mttjohnson mttjohnson commented Jul 3, 2025

I recreated the same behavior that I was seeing in changelog.com.vcl, and by manually testing the Fastly CDN (currently www.changelog.com).

In the VCL used at Fastly it was performing a 308 redirect and included the query string in the redirected url.

Covered redirects:

  • various news mp3
  • http to https
  • www to non-www

Added acceptance tests for all URL redirects. They run across both CDNs.

Summary by CodeRabbit

  • New Features

    • Introduced permanent redirects for legacy podcast MP3 URLs to new canonical locations, preserving query parameters.
    • Enforced HTTPS by redirecting HTTP requests to their HTTPS equivalents.
    • Added automatic redirection from "www." subdomains to non-www HTTPS URLs.
    • Added new speed test commands for various cities.
  • Bug Fixes

    • Updated acceptance and test scripts to use fully qualified URLs with protocol variables for improved accuracy.
  • Documentation

    • Improved local development and README documentation, including roadmap updates and protocol usage examples.
  • Tests

    • Added new acceptance and Varnish tests to verify redirect logic, HTTPS enforcement, and asset handling.
  • Chores

    • Enhanced configuration for environment variables and streamlined test command structures.

@coderabbitai
Copy link

coderabbitai bot commented Jul 3, 2025

Walkthrough

This update introduces new Varnish VCL files and acceptance tests to implement and verify HTTP-to-HTTPS, non-www, and news MP3 redirect logic. It mounts the entire VCL directory in the container, adds speedtest utilities, updates local and CI test runners to use protocol and host variables, and expands test coverage for new redirect behaviors.

Changes

File(s) / Group Change Summary
dagger/main.go Mounts VCL directory, adds speedtest-go tool, updates test variables, and service bindings for acceptance tests.
container.justfile, justfile, just/_config.just Adds speedtest targets, refines purge token handling, updates test variables, and expands acceptance test patterns.
README.md Marks Fastly VCL redirects as complete and adds a "What next?" section about VCL includes.
docs/local_dev.md Cleans up formatting and updates test examples to use protocol variable in URLs.
varnish/vcl/default.vcl Adds include directives for http.vcl, www.vcl, and news-mp3.vcl.
varnish/vcl/http.vcl, varnish/vcl/www.vcl, varnish/vcl/news-mp3.vcl New VCL files implementing HTTP-to-HTTPS, non-www, and news MP3 redirect logic.
test/acceptance/*.hurl, test/acceptance/fastly/*.hurl, test/acceptance/pipedream/*.hurl, test/acceptance/local/http.hurl, test/acceptance/news-mp3.hurl, test/acceptance/www.hurl Updates all test URLs to use protocol variable; adds new tests for HTTP, www, and news MP3 redirects.
test/vtc/http.vtc, test/vtc/news-mp3.vtc, test/vtc/www.vtc Adds Varnish test cases for HTTP redirect, news MP3 redirect, and www redirect.
test/vtc/client-ip.vtc Minor test name change for clarity.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Varnish
    participant Backend

    Client->>Varnish: HTTP request (any host/path)
    alt Host starts with "www."
        Varnish->>Client: 301 Redirect to https://{host without www}/
    else x-forwarded-proto is "http"
        Varnish->>Client: 301 Redirect to https://{host}{url}
    else Request matches news MP3 legacy URL
        Varnish->>Client: 308 Redirect to new /uploads/news/{n}/changelog-news-{n}.mp3
    else
        Varnish->>Backend: Forward request
        Backend->>Varnish: Response
        Varnish->>Client: Response
    end
Loading

Possibly related PRs

  • #16: Adds purge token authentication to Varnish and acceptance test infrastructure, related to updates in test runners and configuration.
  • #18: Updates Varnish config mounting and local development tooling, overlapping changes in dagger/main.go and container setup.

Suggested reviewers

  • mttjohnson
  • jamesarosen

Poem

🐇
New VCL files, redirects in tow,
HTTP to HTTPS, away you must go!
"www." drops for a cleaner domain,
Old news MP3s find new paths again.
Tests abound, speed checks too,
This bunny cheers the work you do!
🥕


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6db18e and 2e6fb68.

📒 Files selected for processing (30)
  • README.md (2 hunks)
  • container.justfile (2 hunks)
  • dagger/main.go (5 hunks)
  • docs/local_dev.md (10 hunks)
  • just/_config.just (1 hunks)
  • justfile (3 hunks)
  • test/acceptance/assets.hurl (7 hunks)
  • test/acceptance/fastly/admin.hurl (1 hunks)
  • test/acceptance/fastly/feed.hurl (2 hunks)
  • test/acceptance/fastly/feeds.hurl (1 hunks)
  • test/acceptance/fastly/homepage.hurl (2 hunks)
  • test/acceptance/feeds.hurl (2 hunks)
  • test/acceptance/http.hurl (1 hunks)
  • test/acceptance/local/http.hurl (1 hunks)
  • test/acceptance/news-mp3.hurl (1 hunks)
  • test/acceptance/pipedream/admin.hurl (1 hunks)
  • test/acceptance/pipedream/assets.hurl (3 hunks)
  • test/acceptance/pipedream/feed.hurl (4 hunks)
  • test/acceptance/pipedream/feeds.hurl (1 hunks)
  • test/acceptance/pipedream/health.hurl (1 hunks)
  • test/acceptance/pipedream/homepage.hurl (3 hunks)
  • test/acceptance/www.hurl (1 hunks)
  • test/vtc/client-ip.vtc (1 hunks)
  • test/vtc/http.vtc (1 hunks)
  • test/vtc/news-mp3.vtc (1 hunks)
  • test/vtc/www.vtc (1 hunks)
  • varnish/vcl/default.vcl (1 hunks)
  • varnish/vcl/http.vcl (1 hunks)
  • varnish/vcl/news-mp3.vcl (1 hunks)
  • varnish/vcl/www.vcl (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • varnish/vcl/www.vcl
  • test/vtc/www.vtc
  • test/acceptance/local/http.hurl
🚧 Files skipped from review as they are similar to previous changes (27)
  • test/acceptance/fastly/feed.hurl
  • test/acceptance/pipedream/assets.hurl
  • docs/local_dev.md
  • test/acceptance/pipedream/feeds.hurl
  • test/vtc/client-ip.vtc
  • test/acceptance/pipedream/admin.hurl
  • test/acceptance/pipedream/health.hurl
  • test/acceptance/fastly/feeds.hurl
  • README.md
  • test/acceptance/feeds.hurl
  • test/acceptance/www.hurl
  • test/acceptance/fastly/admin.hurl
  • varnish/vcl/default.vcl
  • test/acceptance/fastly/homepage.hurl
  • test/vtc/http.vtc
  • test/acceptance/pipedream/feed.hurl
  • just/_config.just
  • test/acceptance/news-mp3.hurl
  • test/acceptance/pipedream/homepage.hurl
  • test/acceptance/assets.hurl
  • test/acceptance/http.hurl
  • varnish/vcl/http.vcl
  • varnish/vcl/news-mp3.vcl
  • test/vtc/news-mp3.vtc
  • dagger/main.go
  • container.justfile
  • justfile
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: on-github / run
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
varnish/pipedream-redirects.changelog.com.vcl (1)

16-22: Consider using a more maintainable approach for multiple redirects.

While the current implementation works correctly, consider using a more scalable approach if more redirects are expected in the future:

-    if (req.url ~ "^/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3($|\?)") {
-        set req.http.X-Redirect = "/uploads/news/1/changelog-news-1.mp3";
-    } else if (req.url ~ "^/uploads/podcast/news-2022-07-04/the-changelog-news-2022-07-04.mp3($|\?)") {
-        set req.http.X-Redirect = "/uploads/news/2/changelog-news-2.mp3";
-    } else if (req.url ~ "^/uploads/podcast/news-2022-07-11/the-changelog-news-2022-07-11.mp3($|\?)") {
-        set req.http.X-Redirect = "/uploads/news/3/changelog-news-3.mp3";
-    }
+    # Alternative approach using a single regex with capture groups
+    if (req.url ~ "^/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3($|\?)") {
+        set req.http.X-Redirect = "/uploads/news/1/changelog-news-1.mp3";
+    } else if (req.url ~ "^/uploads/podcast/news-2022-07-04/the-changelog-news-2022-07-04.mp3($|\?)") {
+        set req.http.X-Redirect = "/uploads/news/2/changelog-news-2.mp3";
+    } else if (req.url ~ "^/uploads/podcast/news-2022-07-11/the-changelog-news-2022-07-11.mp3($|\?)") {
+        set req.http.X-Redirect = "/uploads/news/3/changelog-news-3.mp3";
+    }

However, the current approach is perfectly acceptable for this specific use case with a small number of redirects.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3c6f2e and 6621a17.

📒 Files selected for processing (3)
  • dagger/main.go (1 hunks)
  • varnish/pipedream-redirects.changelog.com.vcl (1 hunks)
  • varnish/pipedream.changelog.com.vcl (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: on-github / run
🔇 Additional comments (4)
varnish/pipedream.changelog.com.vcl (1)

13-13: LGTM! Include directive is properly placed.

The include directive is correctly positioned after module imports and before backend configuration, following VCL best practices. The file path matches the container setup in dagger/main.go.

dagger/main.go (1)

227-230: LGTM! Container configuration properly updated.

The chained WithFile call correctly adds the redirects VCL file to the container. The file paths are consistent with the include directive in the main VCL configuration.

varnish/pipedream-redirects.changelog.com.vcl (2)

1-27: LGTM! Well-implemented redirect logic in vcl_recv.

The URL matching and redirect setup is correctly implemented:

  • Regex patterns properly handle URLs with and without query strings using ($|\?)
  • Custom X-Redirect header is a good practice for passing data between VCL subroutines
  • 308 Permanent Redirect is the appropriate status code for this use case
  • Clear documentation with test examples

29-40: LGTM! Query string preservation correctly implemented.

The redirect response handling is well-designed:

  • Location header construction is syntactically correct
  • Query string preservation logic using regsub(req.url, "^[^?]*", "") correctly extracts the query portion
  • Conditional logic ensures query strings are only appended when present

Copy link
Member

@gerhard gerhard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great start @mttjohnson!

Apart from the below mentions, the following are needed before we can consider merging this:

  • VTC tests (my recommendation would be to duplicate test/vtc/feeds.vtc and adapt it for this config)
  • acceptance tests (my recommendation would be to duplicate test/acceptance/feeds.hurl and adapt it to this change)

Appreciate the contribution 🙏

Comment on lines 16 to 22
if (req.url ~ "^/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3($|\?)") {
set req.http.X-Redirect = "/uploads/news/1/changelog-news-1.mp3";
} else if (req.url ~ "^/uploads/podcast/news-2022-07-04/the-changelog-news-2022-07-04.mp3($|\?)") {
set req.http.X-Redirect = "/uploads/news/2/changelog-news-2.mp3";
} else if (req.url ~ "^/uploads/podcast/news-2022-07-11/the-changelog-news-2022-07-11.mp3($|\?)") {
set req.http.X-Redirect = "/uploads/news/3/changelog-news-3.mp3";
}
Copy link
Member

@gerhard gerhard Jul 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of setting up an req.http.X-Redirect, could we just modify the req.url instead? I'm thinking something along the lines of:

if (req.url ~ "^/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3") {
  set req.url = "/uploads/news/1/changelog-news-1.mp3" + regsub(req.url, "^[^?]*(\?.*)?$", "\1");
}

What I'm not sure about is if Varnish 4+ will append the args automatically - I would test that before adding the regsub.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Varnish does not automatically apply the query string to the URL, it is part of the req.url value. Overwriting the req.url would lose any value in the originally request query string of the URL, which we end up adding back to the response in vcl_synth from req.url. I'd have to test if that could be all done in the vcl_recv sub.

Retaining the original requested URL may be a better practice overall and may make some things more difficult to identify how a request originally came in. I'm not sure how this might impact any of the logging.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, in which case I think that we should try to do it all in one place, something along the lines of the snippet that I posted above.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of setting up an req.http.X-Redirect, could we just modify the req.url instead?

I generally follow the following reasoning:

  1. I modify req.url if I want to affect how the object is cached. Example: normalize query-parameters so /foo?bar&baz and /foo?baz&bar are cached together.
  2. I modify req.url if I want to modify how upstream layers handle the request. Example: change /foo to /bar without a redirect.
  3. I avoid modifying req.url to store data. If I do, I save off req.http.original-url. Without that, it can be very difficult to diagnose issues.

In this case, though, you don't actually need either. You can "pass" the redirect with the synth call:

sub vcl_recv {
    if (req.url ~ "^/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3($|\?)") {
        return (synth(308, "/uploads/news/1/changelog-news-1.mp3"));
    } else if (req.url ~ "^/uploads/podcast/news-2022-07-04/the-changelog-news-2022-07-04.mp3($|\?)") {
        return (synth(308, req.http.X-Redirect = "/uploads/news/2/changelog-news-2.mp3"));
    } else if (req.url ~ "^/uploads/podcast/news-2022-07-11/the-changelog-news-2022-07-11.mp3($|\?)") {
        return (synth(308, req.http.X-Redirect = "/uploads/news/3/changelog-news-3.mp3"));
    }
}

sub vcl_synth {
    if (resp.status == 308 && resp.reason) {
        set resp.http.Location = "https://" + req.http.Host + resp.reason;
        set resp.reason = "Permanent Redirect";

        # If a query string exists, append it to the new path
        if (req.url ~ "\?.+") {
            set resp.http.Location += regsub(req.url, "^[^?]*", "");
        }

        return (deliver);
    }
}

If you don't like abusing resp.reason for the redirect URL, I recommend using req.http.X-Redirect to store the variable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I just realized that resp.reason is read-only. I was thinking that synth() worked like error(), but it doesn't. I've often used the above pattern with vcl_error, but never with synth(). For this, I recommend req.http.X-Redirect. Otherwise, you'll get HTTP 308 /uploads/news/3/changelog-news-3.mp3, which conforms to the spec, but isn't very friendly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
test/vtc/news-redirects.vtc (2)

13-13: Remove unused import.

The std module is imported but not used anywhere in the VCL configuration.

-  import std;

24-24: Clarify purpose of backend header.

The x-backend header is set but not used in the test assertions. Is this for debugging purposes or should it be validated in the tests?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6621a17 and 571291b.

📒 Files selected for processing (2)
  • test/acceptance/news-redirects.hurl (1 hunks)
  • test/vtc/news-redirects.vtc (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • test/acceptance/news-redirects.hurl
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: on-github / run
🔇 Additional comments (4)
test/vtc/news-redirects.vtc (4)

1-2: LGTM: Clear test title and setup.

The varnishtest title clearly describes the purpose of the test file.


3-7: LGTM: Appropriate mock server setup.

The mock server configuration correctly returns a 404 response for all requests, which will be used to validate that non-redirect URLs are passed through to the backend.


42-69: LGTM: Comprehensive redirect test coverage.

The test cases effectively cover:

  • Basic redirect functionality (HTTP 308 status)
  • Query string preservation
  • Multiple redirect entries
  • Correct Location header generation

The test structure properly validates the redirect behavior described in the PR objectives.


47-47: Ignore hardcoded domain in test expectations

The VCL’s redirect logic dynamically builds the Location header using req.http.host. In the varnishtest environment that host is 127.0.0.1, so the test’s expectation

expect resp.http.Location == "https://127.0.0.1/uploads/news/1/changelog-news-1.mp3"

correctly mirrors production behavior under test. No change needed.

Likely an incorrect or invalid review comment.

@mttjohnson
Copy link
Collaborator Author

I was able to run the vtc and hurl tests and build test that cover the news redirects in the Varnish VCL.

Locally, all the VTC tests passed, and the acceptance tests passed except a few tests relating to PURGE operations on the following test files:
test/acceptance/pipedream/assets.hurl
test/acceptance/pipedream/homepage.hurl
test/acceptance/pipedream/feed.hurl

Executed files: 9
Executed requests: 47 (4.1/s)
Succeeded files: 6 (66.7%)
Failed files: 3 (33.3%)
Duration: 11558 ms

I wasn't sure if the local environment (just local-run) was fully functional for running the PURGE requests or if it's expecting some kind of token set somewhere for authentication, because it was getting 401 responses back.

@gerhard
Copy link
Member

gerhard commented Jul 4, 2025

PURGE should just work in local acceptance tests. I am assuming that you ran them via just test (or just test-acceptance-local):

Screen.Recording.2025-07-04.at.20.07.46.mp4

They run in CI the same way, and that always starts from the same deterministic place, so I would be curious to know what is different about your environment - or are you running the command differently? Maybe you ran the command from within the container? Trying that now...

Screen.Recording.2025-07-04.at.20.11.17.mp4

Found it! Pushing a commit on this branch that will fix it for you.

@gerhard
Copy link
Member

gerhard commented Jul 4, 2025

That last commit fixed it. Want to give it a try @mttjohnson?

@gerhard gerhard added this to the 1.0 milestone Jul 4, 2025
@mttjohnson
Copy link
Collaborator Author

That last commit fixed it. Want to give it a try @mttjohnson?

That fixed the test running from inside the container for me.
CleanShot 2025-07-04 at 14 42 09@2x

I also tried running them from the host (though once it's done flashing a bunch of text on the screen, I don't see the same output that everything was successful, so I have to assume that since it didn't throw an error that it was successful)
CleanShot 2025-07-04 at 14 41 21@2x
...oh I guess it spits out an HTML report when run from the host, so the same command operates differently when run from the host. The HTML report indicated everything was happy when run from the host.
CleanShot 2025-07-04 at 14 48 57@2x

@mttjohnson mttjohnson requested a review from gerhard July 4, 2025 19:50
Comment on lines 7 to 10
HTTP 308 # expect permanent redirect response
[Asserts]
header "Content-Length" == "0"
header "Location" contains "/uploads/news/1/changelog-news-1.mp3"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend adding an assertion that you get Permanent Redirect as the HTTP status message. Not having it won't break anything, but it's nice for debugging.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's the role of the HTTP 308 right after the GET request: https://hurl.dev/docs/asserting-response.html

image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the role of the HTTP 308 right after the GET request

That's testing the status code (number), not the status message (string). synth(308, "Waffles Are Tasty") would return a 308 Waffles Are Tasty.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jamesarosen I added the recommended http status text / reason phrase to news-redirect responses in the vcl return (synth(308, "Permanent Redirect"));

Once I had the text in place on the status line I tried to see if it was possible to have hurl perform an assertion on the status text, but it seems that hurl is only evaluating the status code portion, and I'm not finding a way to check the reason phrase portion of the status line.

I also cleaned up the hurl assertions where it was duplicating the assertion on the status code, as @gerhard pointed out, it is already performing an implicit assert via the HTTP 308 line.

be98430

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
varnish/pipedream-redirects.changelog.com.vcl (1)

19-101: Consider data-driven approach for better maintainability.

The long if-else chain works correctly but could become unwieldy as more redirects are added. Consider using a data structure or lookup table approach for better maintainability.

Additionally, there's an inconsistency in the target URL naming:

  • Line 37-38: changelog-news-9-j2g.mp3 (with hyphen)
  • Line 85-86: changelog-news-32p883.mp3 (missing hyphen)
  • Line 91-92: changelog-news-34-XXXL.mp3 (with hyphen)

Please verify if the missing hyphen in changelog-news-32p883.mp3 is intentional or should be changelog-news-32-p883.mp3 for consistency.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bda147f and b245260.

📒 Files selected for processing (2)
  • test/acceptance/news-redirects.hurl (1 hunks)
  • varnish/pipedream-redirects.changelog.com.vcl (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/acceptance/news-redirects.hurl
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: on-github / run
🔇 Additional comments (3)
varnish/pipedream-redirects.changelog.com.vcl (3)

16-17: Good security practice for preventing header injection.

The proactive removal of the X-Redirect header from client requests effectively prevents header injection attacks.


103-106: Redirect trigger logic is correct.

The condition properly checks for the presence of the X-Redirect header and triggers a 308 Permanent Redirect response, which is appropriate for permanent URL changes.


108-119: Query string preservation logic is well implemented.

The redirect response handling correctly:

  • Constructs the Location header with HTTPS scheme and original host
  • Preserves query strings using regex substitution
  • Returns the response properly

This follows the requirements from the PR objectives to maintain consistent redirect behavior with query string preservation.

# Remove X-Redirect header from client requests to prevent header injection
unset req.http.X-Redirect;

if (req.url ~ "^/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3($|\?)") {
Copy link
Collaborator

@nabsul nabsul Jul 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we don't lose the conversation we had: Would it be more performant to wrap this chain of reg-ex's with a simple prefix check, so that they all get skipped if the prefix makes it impossible?

@gerhard gerhard changed the title separate include for news redirects Add redirects from Fastly VCL Jul 5, 2025
@gerhard
Copy link
Member

gerhard commented Jul 7, 2025

Note

TL;DR Varnish peaks at 120k req/s AFTER this change. The network on Fly.io side peaks at 3k req/s

One thing that we discussed during our July 6, 2025 recording was the impact of this change (all those regexes) on performance.

The answer is negligible, specifically 0.002% fewer req/s with a .25ms difference. This is margin of error difference (I simply took the best out of 3 runs).

Before this change - 120k req/s @ 1.399ms

image

After this change - 120k req/s @ 1.425ms

image

FWIW, our bottleneck is networking, specifically on the Fly.io side. https://pipedream.changelog.com maxes out at 3k req/s (or 300Mbps) - first screenshot below - which is mildly surprising considering that the host running the benchmark is capable of 4Gbps+ (second screenshot below).

Let's benchmark https://pipedream.changelog.com:
image

Let's try a speedtest-go:
image

mttjohnson added a commit to mttjohnson/pipedream that referenced this pull request Jul 9, 2025
using WithDirectory() instead of multiple WithFile()
resolves thechangelog#19 (comment)

Signed-off-by: Matt Johnson <m@ttjohnson.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
varnish/vcl/news-redirects.vcl (1)

19-101: Consider refactoring for better maintainability.

The long chain of if-else statements works correctly but presents maintainability challenges. While VCL has limitations for data-driven approaches, consider these improvements:

  1. Regex Pattern Consistency: All patterns correctly use ($|\?) to match either end-of-string or query parameters - this is implemented correctly.

  2. Maintainability Concern: Adding new redirects requires manual code changes to this long chain.

For better maintainability, consider extracting the URL-to-redirect mappings into a more structured format if VCL supports it, or document the pattern for future additions:

# Pattern for new redirects:
# if (req.url ~ "^/uploads/podcast/news-YYYY-MM-DD/the-changelog-news-YYYY-MM-DD.mp3($|\?)") {
#     set req.http.X-Redirect = "/uploads/news/N/changelog-news-N.mp3";
# }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc7bea7 and 65f1eb4.

📒 Files selected for processing (4)
  • dagger/main.go (1 hunks)
  • test/vtc/news-redirects.vtc (1 hunks)
  • varnish/vcl/default.vcl (1 hunks)
  • varnish/vcl/news-redirects.vcl (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • varnish/vcl/default.vcl
  • dagger/main.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/vtc/news-redirects.vtc
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: on-github / run
🔇 Additional comments (3)
varnish/vcl/news-redirects.vcl (3)

16-17: Good security practice for header injection prevention.

Unsetting the X-Redirect header from client requests prevents potential header injection attacks. This is a solid security measure.


103-106: Redirect logic implementation is correct.

The logic properly checks for the presence of the X-Redirect header and returns a 308 Permanent Redirect status, which is the appropriate HTTP status code for preserving the original request method.


108-119: Verify HTTPS hardcoding aligns with deployment requirements.

We searched your config files for any http:// references or flags disabling SSL/TLS and found no matches, but absence of evidence isn’t evidence of absence. Please:

  • Manually confirm that all deployment environments support HTTPS-only redirects.
  • If any environment requires HTTP, consider making the protocol configurable or deriving it from a header (e.g., X-Forwarded-Proto).

@mttjohnson
Copy link
Collaborator Author

@gerhard, I believe all the concerns raised in this pull request have been addressed. Is there anything else that I should look at? Are you wanting to re-review the pull request and merge it, or would you want me to merge it?

@gerhard
Copy link
Member

gerhard commented Jul 9, 2025

I need to re-review & merge. It will have to be tomorrow most likely 🌊

import std;

# include the separate redirects vcl file
include "/etc/varnish/news-redirects.vcl";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a neat trick! It saves on copy-pasting configs between tests and the config that gets deployed. The other tests could do with a similar refactor. Adding this to the post 1.0 list.

Comment on lines +226 to +228
WithDirectory(
"/etc/varnish",
m.Source.Directory("varnish/vcl"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
docs/local_dev.md (1)

238-260: Update CLI example to match new {{proto}} + {{host}} pattern.

The examples below use {{proto}}://{{host}}, but the earlier CLI invocation
(--variable host="https://127.0.0.1") still embeds the scheme inside host.
This will fail at runtime because {{proto}} is undefined and {{host}}
contains a scheme.

Recommend updating the command around line 218:

-hurl --test --color --report-html tmp --insecure --variable host="https://127.0.0.1" test/*.hurl
+hurl --test --color --report-html tmp --insecure \
+     --variable proto=https \
+     --variable host=127.0.0.1 \
+     test/*.hurl
🧹 Nitpick comments (7)
docs/local_dev.md (6)

116-118: Fix typo in the NOTE block.
custome nginx configcustom nginx config.

-> a custome nginx config based on the included template file
+> a custom nginx config based on the included template file

131-133: Correct spelling/grammar in container-startup comment.
ipv6 brdigeIPv6 bridge, and tighten wording to one sentence.

-# Start up nginx connecting it to the ipv6 brdige
-# This may produce a couple errors that can be ignored if there isn't an
-# existing container running that it tries to stop or remove, but it should
+# Start nginx on the IPv6 bridge. You can ignore any “container not found”
+# errors emitted while the old container is being stopped/removed.

169-170: Capitalise acronym for consistency.
dns resolverDNS resolver.

-# Start the varnish container and change dns resolver to use localhost
+# Start the Varnish container and change the DNS resolver to localhost

179-180: Minor spelling fix.
bacckendbackend.

-# Update the /etc/dnsmasq.conf file if environment variables passed into the
-# container are different from the ones set by default in the container
+# Update /etc/dnsmasq.conf if the environment variables differ from those set
+# by default in the container image's dev-varnish.Dockerfile.

299-299: Quote variable to guard against word-splitting.
Although $TIME is unlikely to contain spaces, quoting is a good habit.

-varnishadm vcl.use varnish_$TIME
+varnishadm vcl.use "varnish_${TIME}"

312-314: Tighten comment wording & fix article.
Use “an ACL” and avoid line break in the middle of the sentence.

-# acl for only allowing IPv6 addresses, you will see errors when it gets an IPv4
+# If an ACL only allows IPv6 addresses you will see errors when Varnish
+# receives an IPv4 response from the DNS query.
test/vtc/news-mp3-redirects.vtc (1)

47-47: Consider using a dynamic host variable instead of hardcoded IP.

The tests use hardcoded 127.0.0.1 in the Location header expectations. Consider using ${s1_addr} or a variable that matches the actual test environment to make tests more portable across different setups.

-  expect resp.http.Location == "https://127.0.0.1/uploads/news/1/changelog-news-1.mp3"
+  expect resp.http.Location == "https://${s1_addr}/uploads/news/1/changelog-news-1.mp3"
-  expect resp.http.Location == "https://127.0.0.1/uploads/news/1/changelog-news-1.mp3?this=is&a=query&string"
+  expect resp.http.Location == "https://${s1_addr}/uploads/news/1/changelog-news-1.mp3?this=is&a=query&string"

Also applies to: 55-55

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be98430 and 6afb7c3.

📒 Files selected for processing (25)
  • README.md (2 hunks)
  • container.justfile (1 hunks)
  • dagger/main.go (3 hunks)
  • docs/local_dev.md (10 hunks)
  • justfile (4 hunks)
  • test/acceptance/assets.hurl (7 hunks)
  • test/acceptance/fastly/admin.hurl (1 hunks)
  • test/acceptance/fastly/feed.hurl (2 hunks)
  • test/acceptance/fastly/feeds.hurl (1 hunks)
  • test/acceptance/fastly/homepage.hurl (2 hunks)
  • test/acceptance/feeds.hurl (2 hunks)
  • test/acceptance/http.hurl (1 hunks)
  • test/acceptance/local/http.hurl (1 hunks)
  • test/acceptance/news-mp3-redirects.hurl (1 hunks)
  • test/acceptance/pipedream/admin.hurl (1 hunks)
  • test/acceptance/pipedream/assets.hurl (3 hunks)
  • test/acceptance/pipedream/feed.hurl (4 hunks)
  • test/acceptance/pipedream/feeds.hurl (1 hunks)
  • test/acceptance/pipedream/health.hurl (1 hunks)
  • test/acceptance/pipedream/homepage.hurl (3 hunks)
  • test/acceptance/www.hurl (1 hunks)
  • test/vtc/client-ip.vtc (1 hunks)
  • test/vtc/news-mp3-redirects.vtc (1 hunks)
  • varnish/vcl/default.vcl (1 hunks)
  • varnish/vcl/news-mp3-redirects.vcl (1 hunks)
✅ Files skipped from review due to trivial changes (12)
  • test/vtc/client-ip.vtc
  • test/acceptance/pipedream/assets.hurl
  • test/acceptance/pipedream/feed.hurl
  • test/acceptance/fastly/homepage.hurl
  • test/acceptance/fastly/admin.hurl
  • test/acceptance/fastly/feed.hurl
  • test/acceptance/fastly/feeds.hurl
  • test/acceptance/pipedream/homepage.hurl
  • test/acceptance/www.hurl
  • test/acceptance/local/http.hurl
  • test/acceptance/feeds.hurl
  • test/acceptance/news-mp3-redirects.hurl
🚧 Files skipped from review as they are similar to previous changes (5)
  • varnish/vcl/default.vcl
  • README.md
  • container.justfile
  • dagger/main.go
  • justfile
🔇 Additional comments (12)
test/acceptance/assets.hurl (1)

1-1: LGTM: Consistent URL formatting refactoring.

The systematic change from {{host}}/path to {{proto}}://{{host}}/path standardizes URL construction across all test requests. This improves test portability across different environments and protocols.

Also applies to: 11-11, 21-21, 25-25, 35-35, 47-47, 59-59, 72-72

test/acceptance/http.hurl (1)

1-9: LGTM: Well-designed HTTP to HTTPS redirect test.

The test correctly validates redirect behavior with appropriate status code expectations and Location header assertions. The comments clearly explain the testing approach for different environments (local vs. Fastly vs. Fly.io).

test/acceptance/pipedream/feeds.hurl (1)

1-1: LGTM: Consistent with URL formatting standards.

The URL change follows the same pattern applied across all acceptance test files for consistent protocol handling.

test/acceptance/pipedream/admin.hurl (1)

2-2: LGTM: Maintains test integrity while standardizing URL format.

The URL formatting change is consistent with the broader refactoring while preserving the admin redirect test logic.

test/acceptance/pipedream/health.hurl (1)

1-1: LGTM: Comprehensive URL standardization across health endpoints.

All health check endpoints consistently updated to use the standardized {{proto}}://{{host}}/path format while maintaining existing test logic and assertions.

Also applies to: 8-8, 16-16, 24-24

docs/local_dev.md (1)

3-4: No substantive change – safe to ignore.
The line just trims trailing whitespace after the admonition marker.

test/vtc/news-mp3-redirects.vtc (2)

1-32: Well-structured test setup.

The VTC configuration properly includes the redirect VCL file and sets up appropriate mock backend behavior for testing redirects.


34-56: Comprehensive test coverage for redirect scenarios.

The test cases effectively verify non-redirected paths, basic redirects with 308 status, and query string preservation - covering the core redirect functionality requirements.

varnish/vcl/news-mp3-redirects.vcl (4)

16-17: Excellent security practice.

Removing the X-Redirect header from client requests prevents header injection attacks and ensures the redirect logic controls this header exclusively.


103-105: Correct redirect implementation.

The logic properly checks for the presence of X-Redirect header and returns the appropriate 308 Permanent Redirect status.


108-119: Excellent query string preservation logic.

The implementation correctly constructs the Location header with the host and new path, and properly preserves query strings using regex substitution. The 308 status handling is also correct.


19-101: Regex patterns are correct — no changes needed

I’ve verified that all ($|\?) patterns in varnish/vcl/news-mp3-redirects.vcl are consistent, compile without errors, and successfully match both bare .mp3 URLs and those with query strings (e.g. ?param=value). URL fragments (the #… part) are never sent to the server and thus don’t appear in req.url, so there’s no need to adjust the regex for fragment support.

Comment on lines +1 to +4
GET {{proto}}://www.{{host}}/
HTTP 301 # expect moved permanently response
[Asserts]
header "Location" == "https://{{host}}/"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be testing that www. redirects to the apex. That's fine. But it seems under-specified. Do you want https://www.{{host}}/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3 to redirect to https://www.{{host}}/uploads/news/1/changelog-news-1.mp3 or to https://{{host}}/uploads/news/1/changelog-news-1.mp3?

The answer to that determines where and when you do this redirect.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's exactly right - just www. to apex.

So https://www.{{host}}/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3 should redirect to https://{{assets_host}}/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as you're OK with multiple redirects: (1) www. to apex, then (2) old news URL to new.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's fine considering that these will be hit rarely. To be honest, I want to double-check with @jerodsanto why we need these news mp3 redirects. The original URLs work, so this must be done to keep things consistent. We are squarely in the make it work phase now, I'm thinking make it better & faster in follow-ups so that we ship 1.0-rc.1 and start routing some production traffic through it 🧑‍🔧

@gerhard gerhard force-pushed the reimplementing-table-news-redirects branch from 6afb7c3 to 3c4bac9 Compare July 13, 2025 14:39
Comment on lines 1 to 5
GET {{proto}}://{{host}}/uploads/podcast/news-2022-06-27/the-changelog-news-2022-06-27.mp3
Host: {{assets_host}}
HTTP 308 # expect permanent redirect response
[Asserts]
header "Location" == "https://{{assets_host}}/uploads/news/1/changelog-news-1.mp3"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend adding some of the following:

  • http://{{old-news-url}} redirects to https://{{new-news-url}} -- change protocol
  • https://www.{{old-news-url}} redirects to https://{{new-news-url}} -- remove subdomain
  • http://www.{{old-news-url}} redirects to https://{{new-news-url}} -- change protocol and remove subdomain

Copy link
Member

@gerhard gerhard Jul 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, will add more acceptance tests for http -> https redirects, not just for the root domain.

www only applies to the app domain (changelog.com) not to the assets domain (cdn.changelog.com) which is where all the news mp3 redirects are going.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6afb7c3 and 3c4bac9.

📒 Files selected for processing (27)
  • README.md (2 hunks)
  • container.justfile (1 hunks)
  • dagger/main.go (3 hunks)
  • docs/local_dev.md (10 hunks)
  • justfile (4 hunks)
  • test/acceptance/assets.hurl (7 hunks)
  • test/acceptance/fastly/admin.hurl (1 hunks)
  • test/acceptance/fastly/feed.hurl (2 hunks)
  • test/acceptance/fastly/feeds.hurl (1 hunks)
  • test/acceptance/fastly/homepage.hurl (2 hunks)
  • test/acceptance/feeds.hurl (2 hunks)
  • test/acceptance/http.hurl (1 hunks)
  • test/acceptance/local/http.hurl (1 hunks)
  • test/acceptance/news-mp3-redirects.hurl (1 hunks)
  • test/acceptance/pipedream/admin.hurl (1 hunks)
  • test/acceptance/pipedream/assets.hurl (3 hunks)
  • test/acceptance/pipedream/feed.hurl (4 hunks)
  • test/acceptance/pipedream/feeds.hurl (1 hunks)
  • test/acceptance/pipedream/health.hurl (1 hunks)
  • test/acceptance/pipedream/homepage.hurl (3 hunks)
  • test/acceptance/www.hurl (1 hunks)
  • test/vtc/client-ip.vtc (1 hunks)
  • test/vtc/news-mp3.vtc (1 hunks)
  • test/vtc/www.vtc (1 hunks)
  • varnish/vcl/default.vcl (1 hunks)
  • varnish/vcl/news-mp3.vcl (1 hunks)
  • varnish/vcl/www.vcl (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • docs/local_dev.md
  • test/acceptance/local/http.hurl
🚧 Files skipped from review as they are similar to previous changes (21)
  • test/acceptance/fastly/admin.hurl
  • test/acceptance/assets.hurl
  • test/vtc/client-ip.vtc
  • test/acceptance/www.hurl
  • test/acceptance/pipedream/feed.hurl
  • varnish/vcl/default.vcl
  • test/acceptance/fastly/homepage.hurl
  • test/acceptance/pipedream/assets.hurl
  • test/acceptance/fastly/feed.hurl
  • test/acceptance/pipedream/admin.hurl
  • test/acceptance/pipedream/health.hurl
  • test/acceptance/fastly/feeds.hurl
  • README.md
  • test/acceptance/feeds.hurl
  • container.justfile
  • test/acceptance/pipedream/feeds.hurl
  • test/acceptance/http.hurl
  • test/acceptance/pipedream/homepage.hurl
  • dagger/main.go
  • test/acceptance/news-mp3-redirects.hurl
  • justfile
🔇 Additional comments (5)
varnish/vcl/www.vcl (1)

1-14: The www redirect logic is correct, but X-Redirect handler needs documentation.

The www to non-www redirect implementation is sound - the regex pattern correctly matches the www prefix, and the regsub operation properly removes it. However, the X-Redirect header handling on lines 11-13 lacks context or documentation about its intended use case.

Could you clarify the purpose of the X-Redirect header handling? Is this part of the Fastly VCL behavior being replicated?

test/vtc/www.vtc (1)

19-25: Test assertions are correct and comprehensive.

The client test properly validates both the redirect status code (301) and the correct Location header construction. The test covers the core functionality effectively.

test/vtc/news-mp3.vtc (1)

42-56: Good test coverage for redirect scenarios.

The tests properly cover both basic redirects and query string preservation, which are critical for maintaining URL functionality. The test expectations align correctly with the VCL implementation.

varnish/vcl/news-mp3.vcl (2)

1-3: Good security practice with header injection prevention.

Removing the X-Redirect header from client requests prevents potential header injection attacks.


94-105: Correct implementation of redirect response handling.

The vcl_synth subroutine properly:

  • Constructs the Location header with HTTPS scheme
  • Preserves the original host
  • Appends query strings when present using appropriate regex patterns

The regex pattern "\?.+" correctly matches query strings, and regsub(req.url, "^[^?]*", "") properly extracts the query string portion.

@jamesarosen
Copy link
Collaborator

The existing vcl_deliver has an unconditional

set resp.http.Strict-Transport-Security = "max-age=31557600";

That's not allowed on HTTP requests.

Note: The host must send the Strict-Transport-Security header over HTTPS only, not insecure HTTP. Browsers ignore the header if sent over HTTP to prevent a manipulator-in-the-middle (MITM) from altering the header to expire prematurely or adding it for a host that doesn't support HTTPS.

@gerhard
Copy link
Member

gerhard commented Jul 13, 2025

@jamesarosen considering that's the existing Fastly VCL which has been in use for years, do you think that we should change this?

@jamesarosen
Copy link
Collaborator

considering that's the existing Fastly VCL which has been in use for years, do you think that we should change this?

Nah. Maybe later. It's a tiny optimization.

But it has me thinking about how to do that declaratively in a future version where we're not writing VCL directly. We'll want a way to indicate "modify the redirect-to URL, but continue processing for more redirects" separately from "modify the redirect-to URL, stop processing, and return a redirect."

@gerhard gerhard force-pushed the reimplementing-table-news-redirects branch from 3c4bac9 to e6db18e Compare July 13, 2025 19:03
Copy link
Member

@gerhard gerhard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now looks complete to me.

Want to give it another pass @jamesarosen @mttjohnson @nabsul before I merge it later today?

@mttjohnson if you want to rebase on top of main, go for it, otherwise I'll get it done before merging.


FWIW, I took another benchmark after the latest rewrites. There was a slow decrease in throughput (~3%), but we're still looking good (the bottleneck remains the network):

image

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
varnish/vcl/http.vcl (1)

1-14: LGTM! Clean HTTP to HTTPS redirect implementation.

The VCL logic correctly implements HTTP to HTTPS redirects by:

  1. Detecting HTTP requests via the x-forwarded-proto header
  2. Triggering a 301 redirect response
  3. Constructing the HTTPS URL using the original host and path

The implementation is clean and follows VCL best practices.

Consider adding validation for edge cases:

  • What if req.http.host is missing or malformed?
  • Should there be any sanitization of the host header to prevent redirect attacks?

For now, this implementation aligns with typical CDN behavior where the host header is trusted.

test/acceptance/news-mp3.hurl (1)

1-252: Excellent comprehensive test coverage for news MP3 redirects.

The acceptance tests thoroughly cover:

  • Multiple date-based podcast URLs from 2022-2023
  • Query string preservation (lines 7-11)
  • Special file variants like "j2g", "p883", "XXXL" (lines 61-65, 205-209, 223-227)
  • Proper HTTP 308 permanent redirect responses
  • Canonical URL structure mapping to /uploads/news/{number}/

The test structure is consistent and uses appropriate templated variables for environment flexibility.

For maintainability, consider if this extensive list could be generated programmatically or parameterized, though comprehensive explicit testing has its merits for critical redirect functionality.

test/vtc/http.vtc (1)

20-24: Fix client naming conflict.

Both test scenarios use client c3, which should be sequential for clarity.

Apply this diff to fix the client naming:

-# no x-forwarded-proto
-client c3 {
+# no x-forwarded-proto  
+client c1 {
   txreq -url "/"
   rxresp
   expect resp.status == 200
 } -run

Otherwise, the test logic correctly validates all three scenarios: no header (200), HTTPS header (200), and HTTP header (301 redirect).

Also applies to: 34-39

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c4bac9 and e6db18e.

📒 Files selected for processing (29)
  • README.md (2 hunks)
  • container.justfile (2 hunks)
  • dagger/main.go (5 hunks)
  • docs/local_dev.md (10 hunks)
  • justfile (4 hunks)
  • test/acceptance/assets.hurl (7 hunks)
  • test/acceptance/fastly/admin.hurl (1 hunks)
  • test/acceptance/fastly/feed.hurl (2 hunks)
  • test/acceptance/fastly/feeds.hurl (1 hunks)
  • test/acceptance/fastly/homepage.hurl (2 hunks)
  • test/acceptance/feeds.hurl (2 hunks)
  • test/acceptance/http.hurl (1 hunks)
  • test/acceptance/local/http.hurl (1 hunks)
  • test/acceptance/news-mp3.hurl (1 hunks)
  • test/acceptance/pipedream/admin.hurl (1 hunks)
  • test/acceptance/pipedream/assets.hurl (3 hunks)
  • test/acceptance/pipedream/feed.hurl (4 hunks)
  • test/acceptance/pipedream/feeds.hurl (1 hunks)
  • test/acceptance/pipedream/health.hurl (1 hunks)
  • test/acceptance/pipedream/homepage.hurl (3 hunks)
  • test/acceptance/www.hurl (1 hunks)
  • test/vtc/client-ip.vtc (1 hunks)
  • test/vtc/http.vtc (1 hunks)
  • test/vtc/news-mp3.vtc (1 hunks)
  • test/vtc/www.vtc (1 hunks)
  • varnish/vcl/default.vcl (1 hunks)
  • varnish/vcl/http.vcl (1 hunks)
  • varnish/vcl/news-mp3.vcl (1 hunks)
  • varnish/vcl/www.vcl (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • test/acceptance/assets.hurl
🚧 Files skipped from review as they are similar to previous changes (23)
  • test/vtc/client-ip.vtc
  • test/acceptance/fastly/homepage.hurl
  • test/acceptance/pipedream/health.hurl
  • test/acceptance/fastly/admin.hurl
  • test/acceptance/pipedream/assets.hurl
  • test/acceptance/pipedream/feed.hurl
  • test/acceptance/fastly/feeds.hurl
  • README.md
  • test/acceptance/pipedream/feeds.hurl
  • test/acceptance/fastly/feed.hurl
  • test/acceptance/pipedream/admin.hurl
  • test/acceptance/feeds.hurl
  • test/acceptance/www.hurl
  • test/acceptance/http.hurl
  • test/acceptance/pipedream/homepage.hurl
  • docs/local_dev.md
  • test/vtc/www.vtc
  • test/acceptance/local/http.hurl
  • varnish/vcl/www.vcl
  • justfile
  • dagger/main.go
  • test/vtc/news-mp3.vtc
  • varnish/vcl/news-mp3.vcl
🔇 Additional comments (4)
varnish/vcl/default.vcl (1)

13-15: LGTM! Well-positioned include directives.

The include directives are correctly placed after module imports and before backend declarations. This positioning ensures that the included VCL files have access to imported modules while allowing their subroutines to be available to the main VCL logic.

test/vtc/http.vtc (1)

1-17: Well-structured Varnish test setup.

The test configuration correctly:

  • Sets up a backend server with appropriate repetition for multiple clients
  • Includes the http.vcl file being tested
  • Disables caching to ensure fresh responses during testing
  • Uses appropriate VCL version 4.1

The test design effectively validates the HTTP redirect functionality.

container.justfile (2)

43-52: Improved test configuration with better variable separation.

The updates enhance the acceptance test setup by:

  • Separating protocol and host variables for cleaner URL construction
  • Using consistent Justfile environment variable syntax for purge_token
  • Adding local test pattern for expanded coverage
  • Aligning with the standardized URL format used across other acceptance tests

This makes the test configuration more maintainable and consistent.


98-134: Comprehensive speedtest infrastructure added.

The new speedtest targets provide valuable network performance testing capabilities across multiple geographic locations. The organization is clean with descriptive target names and appropriate server IDs for each region.

This addition supports the performance benchmarking mentioned in the PR objectives.

mttjohnson and others added 9 commits July 13, 2025 22:33
I tried to recreate the same behavior I was seeing from the changelog.com.vcl and from sending requests to the Fastly CDN (currently www.changelog.com).

In the VCL used at Fastly it was performing a 308 redirect and included the query string in the redirected url.

I added a WithFile() section in main.go to make sure the new included VCL file gets copied into the container along side the default vcl when the container is built.

Signed-off-by: Matt Johnson <m@ttjohnson.com>
Signed-off-by: Matt Johnson <m@ttjohnson.com>
using contains keeps it simple and avoids trying to use matches which can have unexpected behavior when trying to match query string special characters thinking they relate to regular expression syntax

Signed-off-by: Matt Johnson <m@ttjohnson.com>
Signed-off-by: Gerhard Lazu <gerhard@changelog.com>
- include assertions for http status code being 308 in hurl acceptance tests
- add the rest of the redirects from fastly (changelog.com.vcl) table news_redirects
- defend against header injection attacks

Signed-off-by: Matt Johnson <m@ttjohnson.com>
Signed-off-by: Gerhard Lazu <gerhard@changelog.com>
using WithDirectory() instead of multiple WithFile()
resolves thechangelog#19 (comment)

Signed-off-by: Matt Johnson <m@ttjohnson.com>
- added recommended http status text / reason phrase to news-redirect responses
- removed redundant assertion on status code

Signed-off-by: Matt Johnson <m@ttjohnson.com>
So that we compare the behaviour of both CDNs. The idea is that they
should be identical by the time we are ready to roll out 1.0

Also add acceptance tests + redirects for:
- http -> https
- www -> non-ww

Also added speedtest benchmarks. Especially useful when running with
`--cloud` 🤫

Signed-off-by: Gerhard Lazu <gerhard@changelog.com>
Signed-off-by: Gerhard Lazu <gerhard@hannibal.localdomain>
@gerhard gerhard force-pushed the reimplementing-table-news-redirects branch from e6db18e to 2e6fb68 Compare July 13, 2025 21:35
@gerhard gerhard merged commit 09d8699 into thechangelog:main Jul 13, 2025
4 checks passed
gerhard added a commit that referenced this pull request Jul 13, 2025
Follow-up to:
- #19

Signed-off-by: Gerhard Lazu <gerhard@changelog.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants