Add FlareSolverr bypass settings#24
Conversation
There was a problem hiding this comment.
Code Review
This pull request integrates FlareSolverr to bypass Cloudflare challenges when fetching tracker data, adding frontend settings, database schema updates, migrations, and backend adapter logic. Feedback on the changes highlights a critical runtime crash caused by using the non-existent z.url() method in Zod, an issue with URL resolution discarding subpaths due to leading slashes, and an opportunity to simplify a convoluted try-catch block in the tracker adapter's error handling.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| import { handleStandardValidation } from '@server/lib/validation'; | ||
|
|
||
| const verifySchema = z.object({ | ||
| flaresolverrUrl: z.url({ message: 'FlareSolverr URL is required' }).trim(), |
There was a problem hiding this comment.
The z.url() method does not exist in standard Zod. Chaining .trim() on it will also fail. This will cause a runtime crash when the module is loaded. It should be corrected to use z.string().trim().url() instead.
| flaresolverrUrl: z.url({ message: 'FlareSolverr URL is required' }).trim(), | |
| flaresolverrUrl: z.string().trim().url({ message: 'FlareSolverr URL is required' }), |
| timeout: number; | ||
| cookies: string; | ||
| }): Promise<FlareSolverrSolution> { | ||
| const endpoint = new URL('/v1', normalizeServerUrl(params.serverUrl)); |
There was a problem hiding this comment.
Using a leading slash in the input path ('/v1') with new URL() causes the resolution to be relative to the host root, discarding any subpath configured in the base URL (e.g., http://localhost:8191/proxy/ would resolve to http://localhost:8191/v1 instead of http://localhost:8191/proxy/v1). Removing the leading slash ('v1') ensures correct resolution when FlareSolverr is hosted behind a subpath proxy.
| const endpoint = new URL('/v1', normalizeServerUrl(params.serverUrl)); | |
| const endpoint = new URL('v1', normalizeServerUrl(params.serverUrl)); |
| serverUrl: string; | ||
| timeout: number; | ||
| }): Promise<void> { | ||
| const endpoint = new URL('/v1', normalizeServerUrl(params.serverUrl)); |
There was a problem hiding this comment.
Using a leading slash in the input path ('/v1') with new URL() causes the resolution to be relative to the host root, discarding any subpath configured in the base URL. Removing the leading slash ('v1') ensures correct resolution when FlareSolverr is hosted behind a subpath proxy.
| const endpoint = new URL('/v1', normalizeServerUrl(params.serverUrl)); | |
| const endpoint = new URL('v1', normalizeServerUrl(params.serverUrl)); |
| try { | ||
| assertNotCloudflareChallenge(root); | ||
| } catch (error) { | ||
| if (!(error instanceof CloudflareChallengeError)) { | ||
| throw error; | ||
| } | ||
| } |
There was a problem hiding this comment.
This try-catch block is unnecessarily convoluted. It calls assertNotCloudflareChallenge which always throws an error, only to catch it and rethrow if it's not a CloudflareChallengeError. Since isCloudflareChallenge is already imported, you can simplify this to a direct check, which is much cleaner and easier to read.
if (!isCloudflareChallenge(root)) {
throw new Error('Server responded with 403');
}There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e92861305d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| timeout: number; | ||
| cookies: string; | ||
| }): Promise<FlareSolverrSolution> { | ||
| const endpoint = new URL('/v1', normalizeServerUrl(params.serverUrl)); |
There was a problem hiding this comment.
Preserve FlareSolverr base paths when building endpoint
When a user configures FlareSolverr behind a reverse-proxy subpath such as http://host/flaresolverr, new URL('/v1', ...) discards the configured path and posts to http://host/v1 instead of http://host/flaresolverr/v1. In that deployment both the bypass request and connection test fail even though the configured service is reachable; build the API URL relative to the normalized base without a leading slash or otherwise preserve the pathname.
Useful? React with 👍 / 👎.
Summary
Rationale
Some tracker topic pages can be blocked by Cloudflare checks. This adds an opt-in browser-solving fallback without slowing down the normal tracker fetch path.
Changes
/api/flaresolverr/verifyusing FlareSolverrsessions.list.flaresolverr_enabled,flaresolverr_url,flaresolverr_timeout_seconds.Validation
bun run lintpassed with existing warnings only.bun run testpassed.bun run buildpassed.