Skip to content

Add URL validation to AddBlog function#18

Merged
JulienTant merged 2 commits intoJulienTant:mainfrom
sroecker:fix/url-validation
Apr 22, 2026
Merged

Add URL validation to AddBlog function#18
JulienTant merged 2 commits intoJulienTant:mainfrom
sroecker:fix/url-validation

Conversation

@sroecker
Copy link
Copy Markdown
Contributor

@sroecker sroecker commented Apr 7, 2026

Summary

Adds URL validation to prevent invalid URLs from being stored in the database, which could cause failures during scanning.

Changes

  • Added new type for validation errors
  • Validate blog URL format using and
  • Enforce http/https scheme for both blog URL and optional feed URL
  • Added comprehensive test cases for valid and invalid URLs

Validation Rules

  • URLs must have valid format (parsable by Go's url.Parse)
  • URLs must use http or https scheme (no ftp://, file://, etc.)
  • Empty URLs are rejected
  • Feed URL is validated only if provided (empty string is allowed)

Test Coverage

Added two new test functions:

  • : Tests rejection of empty URLs, non-http/https schemes, missing schemes, malformed URLs, and invalid feed URLs
  • : Tests acceptance of http:// and https:// URLs with and without feed URLs

Fixes

Resolves the security concern where invalid URLs could be stored, causing potential failures during the scanning process.

Summary by CodeRabbit

  • Bug Fixes

    • Stronger URL validation when adding blogs: only HTTP/HTTPS addresses are accepted for primary and feed URLs; invalid entries are rejected with clear feedback.
    • OPML import now skips invalid URLs instead of failing, reporting added vs skipped entries.
  • Tests

    • Added tests covering valid/invalid URL scenarios and OPML import skip behavior.

- Added InvalidURLError type for invalid URL errors
- Validate blog URL has valid format and http/https scheme
- Validate feed URL if provided
- Added comprehensive tests for valid and invalid URLs

Fixes issue where invalid URLs could be stored, causing failures during scanning.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 7, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6c028365-e562-47e4-becc-cf8007ae476d

📥 Commits

Reviewing files that changed from the base of the PR and between 61f1496 and e95da1e.

📒 Files selected for processing (2)
  • internal/controller/controller.go
  • internal/controller/controller_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/controller/controller.go

📝 Walkthrough

Walkthrough

Added explicit URL validation to AddBlog (renamed param to urlStr) with a new exported InvalidURLError; AddBlog now enforces http/https for both URL and optional feedURL. ImportOPML now treats InvalidURLError as a skipped entry. Tests added for valid/invalid URLs and OPML import skipping.

Changes

Cohort / File(s) Summary
Controller: URL validation & error type
internal/controller/controller.go
Added InvalidURLError type and Error() method. Renamed AddBlog parameter urlurlStr. Added URL parsing/validation for urlStr and feedURL, enforcing http/https schemes; returns InvalidURLError on invalid input. Adjusted DB lookup/storage to use urlStr. Updated ImportOPML to treat InvalidURLError as a skipped item.
Controller tests
internal/controller/controller_test.go
Added TestAddBlogInvalidURL (table-driven malformed/unsupported url/feedURL cases asserting InvalidURLError), TestAddBlogValidURL (accepted http/https cases, persistence checks, cleanup), and TestImportOPMLSkipsInvalidURLs (OPML fixture where invalid-scheme outline is skipped and valid one is added).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through code with careful cheer,
I checked each URL both far and near,
http and https earned a friendly grin,
Invalid schemes I nudged right out the bin,
Hooray — the blogs now welcome only kin! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change—adding URL validation to the AddBlog function, which is the core objective of the PR.
Description check ✅ Passed The description covers the summary, changes, validation rules, and test coverage, matching the repository template structure with all required sections addressed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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

🧹 Nitpick comments (1)
internal/controller/controller.go (1)

49-68: Extract duplicated URL validation logic into a helper function.

The URL validation logic is duplicated for urlStr and feedURL. Consider extracting to a helper:

func validateURL(urlStr string) error {
    if _, err := url.ParseRequestURI(urlStr); err != nil {
        return InvalidURLError{URL: urlStr}
    }
    parsedURL, err := url.Parse(urlStr)
    if err != nil || (parsedURL.Scheme != "http" && parsedURL.Scheme != "https") {
        return InvalidURLError{URL: urlStr}
    }
    return nil
}

Also, consider enhancing InvalidURLError to include a Reason field (e.g., "empty", "unsupported scheme", "malformed") to provide more actionable feedback to CLI users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/controller/controller.go` around lines 49 - 68, The AddBlog function
duplicates URL validation for urlStr and feedURL; extract that logic into a
helper function (e.g., validateURL(urlStr string) error) and call it from
AddBlog for both urlStr and feedURL, returning InvalidURLError on failure; also
modify the InvalidURLError type to include an optional Reason field ("empty",
"unsupported scheme", "malformed") and populate it in validateURL so callers of
AddBlog get clearer error details.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/controller/controller_test.go`:
- Around line 44-61: The test table in controller_test.go contains an invalid
case named "empty feed URL allowed" that expects an error but should succeed;
locate the testCases slice used by the failing test (the loop invoking
AddBlog(ctx, db, "Test"+tc.name, tc.url, tc.feedURL, "")) and remove or relocate
the entry {"empty feed URL allowed", "https://example.com", ""} from this
error-expecting test to the positive-test suite (e.g., TestAddBlogValidURL) so
AddBlog is asserted to succeed for an empty feedURL instead of asserting an
InvalidURLError.

---

Nitpick comments:
In `@internal/controller/controller.go`:
- Around line 49-68: The AddBlog function duplicates URL validation for urlStr
and feedURL; extract that logic into a helper function (e.g., validateURL(urlStr
string) error) and call it from AddBlog for both urlStr and feedURL, returning
InvalidURLError on failure; also modify the InvalidURLError type to include an
optional Reason field ("empty", "unsupported scheme", "malformed") and populate
it in validateURL so callers of AddBlog get clearer error details.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a6eb13a7-a890-4f65-9a1e-dba3bed0f9d8

📥 Commits

Reviewing files that changed from the base of the PR and between 529b171 and 61f1496.

📒 Files selected for processing (2)
  • internal/controller/controller.go
  • internal/controller/controller_test.go

Comment thread internal/controller/controller_test.go
@JulienTant
Copy link
Copy Markdown
Owner

Hey @sroecker thanks! Looking into this right now, just came back from vacation :)

With AddBlog now rejecting non-http(s) URLs, a single bad entry in an
OPML file would halt the whole import with earlier entries already
committed. Treat InvalidURLError like BlogAlreadyExistsError: count it
as skipped and keep going.

Also fix the "empty feed URL allowed" case that was asserting an error
on a valid input, and switch the errors.As assertion to ErrorAs per
testifylint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JulienTant
Copy link
Copy Markdown
Owner

JulienTant commented Apr 22, 2026

Hey @sroecker — thanks for this! I pushed one small commit directly (e95da1e) to fix a behavior regression I caught while reviewing:

With the new validation in place, a single OPML entry with a non-http(s) URL would abort the whole import mid-loop (with earlier entries already committed). I extended ImportOPML to treat InvalidURLError as "skipped" alongside BlogAlreadyExistsError, and added a test covering one bad + one good entry.

While I was in there I also fixed two small things in your test:

  • TestAddBlogInvalidURL had a case {"empty feed URL allowed", "https://example.com", ""} that was actually a valid input, so require.Error was failing on it. The positive path is already covered by TestAddBlogValidURL, so I removed the misplaced row.
  • Swapped require.True(t, errors.As(...))require.ErrorAs(t, ...) to satisfy the testifylint linter (project forbids //nolint).

There are still a couple of follow-ups I'd like to land in a separate PR of my own — https:// and http:///path sneak past the scheme check because Host isn't validated, and the double url.ParseRequestURI/url.Parse can collapse to one call. Happy to handle those myself so we can get this merged.

Thanks so much for your contribution!

@JulienTant JulienTant merged commit 24759df into JulienTant:main Apr 22, 2026
2 checks passed
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.

2 participants