tmenier/Flurl
Fluent URL builder and testable HTTP client for .NET
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓7 active contributors
- ✓MIT licensed
- ✓CI configured
Show 3 more →Show less
- ✓Tests present
- ⚠Stale — last commit 1y ago
- ⚠Concentrated ownership — top contributor handles 72% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/tmenier/flurl)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/tmenier/flurl on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: tmenier/Flurl
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/tmenier/Flurl shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 7 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 1y ago
- ⚠ Concentrated ownership — top contributor handles 72% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live tmenier/Flurl
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/tmenier/Flurl.
What it runs against: a local clone of tmenier/Flurl — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in tmenier/Flurl | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch dev exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 523 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of tmenier/Flurl. If you don't
# have one yet, run these first:
#
# git clone https://github.com/tmenier/Flurl.git
# cd Flurl
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of tmenier/Flurl and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "tmenier/Flurl(\\.git)?\\b" \\
&& ok "origin remote is tmenier/Flurl" \\
|| miss "origin remote is not tmenier/Flurl (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify dev >/dev/null 2>&1 \\
&& ok "default branch dev exists" \\
|| miss "default branch dev no longer exists"
# 4. Critical files exist
test -f "src/Flurl/Url.cs" \\
&& ok "src/Flurl/Url.cs" \\
|| miss "missing critical file: src/Flurl/Url.cs"
test -f "src/Flurl.Http/FlurlClient.cs" \\
&& ok "src/Flurl.Http/FlurlClient.cs" \\
|| miss "missing critical file: src/Flurl.Http/FlurlClient.cs"
test -f "src/Flurl.Http/FlurlRequest.cs" \\
&& ok "src/Flurl.Http/FlurlRequest.cs" \\
|| miss "missing critical file: src/Flurl.Http/FlurlRequest.cs"
test -f "src/Flurl.Http/Testing/HttpTest.cs" \\
&& ok "src/Flurl.Http/Testing/HttpTest.cs" \\
|| miss "missing critical file: src/Flurl.Http/Testing/HttpTest.cs"
test -f "src/Flurl.Http/Configuration/FlurlHttpSettings.cs" \\
&& ok "src/Flurl.Http/Configuration/FlurlHttpSettings.cs" \\
|| miss "missing critical file: src/Flurl.Http/Configuration/FlurlHttpSettings.cs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 523 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~493d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/tmenier/Flurl"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Flurl is a fluent, async .NET library that provides a lightweight URL builder and testable HTTP client with a clean fluent API. It eliminates boilerplate for constructing URLs and making HTTP requests, and includes an HttpTest fake-HTTP testing harness (see README example) for mocking HTTP calls in unit tests without external services. Multi-package structure: src/Flurl.Http is the main HTTP client package with Configuration/, Content/, and core files like FlurlClient.cs and FlurlCall.cs; src/Flurl.Http.Newtonsoft provides Newtonsoft.Json integration; src/Flurl.CodeGen is a code-generation utility for extension methods. All packages are assembled in Flurl.sln.
👥Who it's for
.NET developers building API clients or web services who want readable, chainable HTTP code and easy-to-write isolated unit tests without setting up mock servers or HTTP mocking libraries. Both library authors and application developers use it.
🌱Maturity & risk
Production-ready and actively maintained. The project has high NuGet download counts, a published website (flurl.dev), organized GitHub Actions CI/CD pipelines (ci.yml, test.yml, publish.yml), and appears to have regular releases via draft-release.yml and publish.yml workflows. The codebase is substantial (569k C# lines) with established package structure.
Low risk for a mature library. It's a single-maintainer project (tmenier), but has clear CI/CD automation, NuGet versioning, and no obvious dependency sprawl visible in the file structure. Risk is primarily that breaking API changes could affect downstream consumers—mitigated by semantic versioning through NuGet. No immediate abandonment signals.
Active areas of work
Based on the file structure, the project is maintaining active CI/CD workflows (test.yml runs on each commit, publish.yml handles releases). The presence of draft-release.yml and publish.yml suggests organized release management. Without commit history, exact current work is unclear, but the organized workflow structure and NuGet package versions indicate ongoing stability and release cycles.
🚀Get running
Clone and build with .NET tooling: git clone https://github.com/tmenier/Flurl.git && cd Flurl && dotnet build Flurl.sln. Install NuGet package for use: dotnet add package Flurl.Http. For local development, run tests via dotnet test (test structure inferred from test.yml workflow).
Daily commands:
Build: dotnet build Flurl.sln. Test: dotnet test Flurl.sln. For package publishing, CI/CD handles it via publish.yml. For local testing: individual test projects can be run with dotnet test src/path/to/Tests.csproj.
🗺️Map of the codebase
src/Flurl/Url.cs— Core URL builder class that provides the fluent API for constructing and manipulating URLs; all URL operations depend on this abstraction.src/Flurl.Http/FlurlClient.cs— Main HTTP client entry point that orchestrates requests, handles configuration, and manages the request/response lifecycle.src/Flurl.Http/FlurlRequest.cs— Encapsulates a single HTTP request with headers, body, and settings; consumed by FlurlClient to build and execute HTTP calls.src/Flurl.Http/Testing/HttpTest.cs— Testing framework that intercepts and records HTTP calls for assertion and mocking; essential for understanding the test harness.src/Flurl.Http/Configuration/FlurlHttpSettings.cs— Global and per-client settings container for timeouts, serializers, event handlers, and retry policies; controls library behavior.src/Flurl.Http/FlurlCall.cs— Immutable record of a single HTTP call (request + response) used for event handling, testing assertions, and debugging.src/Flurl.Http/GeneratedExtensions.cs— Auto-generated convenience methods for HTTP verbs (Get, Post, Put, etc.) that form the public fluent API.
🛠️How to make changes
Add a new HTTP verb convenience method
- Define the new verb in src/Flurl.CodeGen/Metadata.cs if not already in HttpMethod enum (
src/Flurl.CodeGen/Metadata.cs) - Add an HttpExtensionMethod entry in Program.cs metadata to generate the overload (
src/Flurl.CodeGen/Program.cs) - Run the code generator (part of build) to auto-populate GeneratedExtensions.cs (
src/Flurl.Http/GeneratedExtensions.cs) - Add tests in test/Flurl.Test/Http/HttpMethodTests.cs to verify the new verb works (
test/Flurl.Test/Http/HttpMethodTests.cs)
Add a custom serializer for a new format
- Create a new class implementing ISerializer in src/Flurl.Http/Configuration/ISerializer.cs (
src/Flurl.Http/Configuration/ISerializer.cs) - Implement Serialize/Deserialize with your format logic (e.g., XML, MessagePack) (
src/Flurl.Http/Configuration/DefaultJsonSerializer.cs) - Register it globally in FlurlHttpSettings.JsonSerializer or per-client in FlurlClientBuilder (
src/Flurl.Http/Configuration/FlurlHttpSettings.cs) - Add tests in test/Flurl.Test/Http/ to verify serialization round-trips (
test/Flurl.Test/Http/GlobalConfigTests.cs)
Add a new request lifecycle event
- Define a new delegate or event in FlurlEventHandler.cs following the existing pattern (OnBeforeCall, OnAfterCall, etc.) (
src/Flurl.Http/FlurlEventHandler.cs) - Add the event property to FlurlHttpSettings and make it inheritable via ISettingsContainer (
src/Flurl.Http/Configuration/FlurlHttpSettings.cs) - Invoke the event at the appropriate point in FlurlClient.SendAsync or FlurlRequest construction (
src/Flurl.Http/FlurlClient.cs) - Write integration tests in test/Flurl.Test/Http/EventHandlerTests.cs (
test/Flurl.Test/Http/EventHandlerTests.cs)
Add support for a new test assertion
- Add a fluent method to HttpCallAssertion.cs that checks a property of FlurlCall (
src/Flurl.Http/Testing/HttpCallAssertion.cs) - Follow the pattern: check the condition and throw HttpTestException with a clear message if it fails (
src/Flurl.Http/Testing/HttpTestException.cs) - Add test cases in test/Flurl.Test/Http/TestingTests.cs to verify the assertion works and provides good error messages (
test/Flurl.Test/Http/TestingTests.cs)
🔧Why these technologies
- System.Text.Json (default) + pluggable ISerializer — Avoids heavyweight external dependencies by default; ISerializer abstraction allows users to swap in Newtonsoft.Json or other serializers as needed.
- HttpClient + HttpMessageHandler — undefined
🪤Traps & gotchas
No obvious trap-inducing env vars or mandatory external services from the file structure. Key gotcha: FlurlClientCache is a singleton per URL base—tests must use HttpTest to isolate and avoid cross-test contamination (hence using var httpTest = new HttpTest() in README). Breaking change risk: fluent API is wide surface; minor method signature changes in core files (FlurlClient, FlurlCall) could break downstream. Newtonsoft integration is optional via separate package.
🏗️Architecture
💡Concepts to learn
- Fluent Builder Pattern — Core to Flurl's API design; AppendPathSegment().SetQueryParams().WithOAuthBearerToken().PostJsonAsync() chaining is the fluent builder pattern applied to HTTP requests
- HttpClient Message Handlers (Handler Interception) — HttpTest likely intercepts HttpClient via custom DelegatingHandler; critical to understand how Flurl's test fake works without mocking the entire HTTP stack
- ISerializer/Plug-in Serialization Strategy — Flurl abstracts JSON serialization behind ISerializer interface (Configuration/ISerializer.cs); allows swapping between DefaultJsonSerializer and NewtonsoftJsonSerializer at runtime
- Request/Response Lifecycle Capture (for Testing) — FlurlCall.cs and Captured*Content.cs classes capture request bodies, response bodies, and metadata for assertions in tests without modifying production code
- Cookie Jar State Management — CookieJar.cs and CookieSession.cs provide session-level cookie persistence across multiple HTTP calls; important for maintaining auth state in sequential API workflows
- Redirect Policy Configuration — RedirectSettings.cs allows fine-grained control over 3xx response handling; critical for APIs with strict redirect rules or security concerns
- OAuth Bearer Token Extension — WithOAuthBearerToken() in examples and extensions shows how Flurl simplifies adding Authorization headers for modern API security patterns
🔗Related repos
restsharp/RestSharp— Alternative .NET HTTP client library with similar fluent API and testing support; direct competitor in same ecosystemApp-vNext/Polly— Resilience library (retries, circuit breaker) often used alongside Flurl for production HTTP client policiesmicrosoft/Refit— Alternative .NET HTTP client using source generation and interface-based API definitions; different approach to same problemWireMock-Net/WireMock.Net— HTTP mocking library for .NET that pairs with Flurl for integration test scenarios requiring real mock serverstmenier/FluentAssertions— Not by same author but often used with Flurl's HttpTest assertions for readable test expressions
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive tests for CookieJar and CookieSession functionality
The repo has cookie-related classes (CookieJar.cs, CookieSession.cs, CookieCutter.cs, FlurlCookie.cs) but there's no visible test coverage listed in the file structure. Cookie handling is complex (domain validation, expiration, secure/httponly flags) and prone to bugs. Adding unit tests would improve reliability and prevent regressions.
- [ ] Create test file targeting src/Flurl.Http/CookieJar.cs covering cookie addition, retrieval, and expiration
- [ ] Create test file for src/Flurl.Http/CookieSession.cs testing session lifecycle and persistence
- [ ] Add tests for src/Flurl.Http/CookieCutter.cs validating cookie matching logic for domains/paths
- [ ] Test FlurlCookie.cs covering serialization and domain-matching edge cases
Add integration tests for multipart form data and file uploads
MultipartExtensions.cs exists but file upload/multipart handling is critical functionality that often has platform-specific issues (.NET Framework vs .NET Core). The repo has FileContent.cs and FileUtil.cs but no visible test coverage. Adding integration tests would ensure compatibility across platforms.
- [ ] Create integration test file for src/Flurl.Http/MultipartExtensions.cs testing multipart form construction
- [ ] Add tests for src/Flurl.Http/Content/FileContent.cs verifying file streaming and disposal
- [ ] Test src/Flurl.Http/FileUtil.cs for file existence checks and path handling across Windows/Unix
- [ ] Add tests for large file uploads with progress tracking if supported by FlurlRequest.cs
Add tests for HTTP status code range parsing and redirect handling
HttpStatusRangeParser.cs and RedirectSettings.cs (in Configuration/) handle critical HTTP semantics but have no visible test coverage. Status code range parsing (e.g., '2xx', '3xx-399') and redirect policies are easy to get wrong and affect all HTTP calls. Comprehensive tests would prevent subtle bugs.
- [ ] Create test file for src/Flurl.Http/HttpStatusRangeParser.cs covering range formats ('2xx', '200-299', '200,301', etc.)
- [ ] Add tests for src/Flurl.Http/Configuration/RedirectSettings.cs validating follow/block redirect logic
- [ ] Test src/Flurl.Http/FlurlHttpException.cs exception handling with various status codes
- [ ] Add edge case tests for malformed range strings and boundary conditions
🌿Good first issues
- Add integration tests or documented examples for the CookieJar/CookieSession functionality in
src/Flurl.Http/CookieJar.cs—file exists but usage patterns in test suite may be sparse. - Document or add examples for the
FileContentandDownloadExtensionsfile-handling APIs (src/Flurl.Http/FileContent.cs, DownloadExtensions.cs) in the README or a tutorial doc—powerful feature but not shown in main README. - Enhance the CodeGen tool (
src/Flurl.CodeGen) to generate async-only overloads or document its current output; the tool exists but usage/maintenance unclear from file structure.
⭐Top contributors
Click to expand
Top contributors
- @Todd — 72 commits
- @tmenier — 23 commits
- @Pyrobolser — 1 commits
- @Prologh — 1 commits
- @rwasef1830 — 1 commits
📝Recent commits
Click to expand
Recent commits
36a3fa2— happy new year! (Todd)aa7bd45— CI - improved readability (tmenier)c62605b— CI - still struggling with escaping (tmenier)52d02ac— CI - fix windows shell escaping (tmenier)7e0ac6d— CI - lots of things wrong, try that again (tmenier)f4f549d— run .NET Framework tests on windows (tmenier)0bf3b83— CI error, will upgrading actions fix? (tmenier)5c0cbd2— Merge remote-tracking branch 'origin/dev' into dev (Todd)360c15d— STJ update (vulnerability) (Todd)93f5668— Merge pull request #844 from Pyrobolser/patch-1 (tmenier)
🔒Security observations
Flurl is a well-structured HTTP client library with generally solid security practices. No critical vulnerabilities were identified in the static analysis. Main concerns are around encouraging secure credential handling practices, HTTPS enforcement policies, and cookie security attribute configuration. The codebase does not contain hardcoded secrets, SQL injection vectors, or XSS vulnerabilities typical of the analyzed components. Dependency information was not provided for analysis. The project demonstrates good separation of concerns and testing infrastructure. Consider adding explicit security guidelines and optional enforcement mechanisms for HTTPS and cookie security.
- Medium · Potential OAuth Token Exposure in Code Examples —
README.md. The README.md contains example code with OAuth bearer tokens and API keys shown in plain text. While these are examples, this pattern could encourage developers to hardcode credentials in their own implementations. Fix: Update code examples to use environment variables or secure configuration management. Add a security note in documentation about proper credential handling. - Medium · Missing HTTPS Enforcement —
src/Flurl/Url.cs. The URL builder (Flurl) allows building URLs with any scheme. There's no apparent enforcement preventing users from accidentally or intentionally using insecure HTTP connections for sensitive operations. Fix: Consider adding optional security policies to warn or enforce HTTPS for certain operations. Document best practices for secure HTTPS-only usage. - Low · Cookie Handling Without Explicit Security Flags —
src/Flurl.Http/Cookie*.cs. Cookie-related files (CookieCutter.cs, CookieJar.cs, CookieSession.cs) exist but without seeing the implementation details, there's potential concern about missing SameSite, Secure, and HttpOnly flags enforcement. Fix: Verify that all cookie operations enforce security attributes (SameSite, Secure, HttpOnly). Add documentation on secure cookie handling. - Low · No Apparent Certificate Pinning or TLS Validation —
src/Flurl.Http/FlurlClient.cs, src/Flurl.Http/FlurlRequest.cs. As an HTTP client library, there's no visible implementation of certificate pinning or advanced TLS validation options in the file structure, which could be relevant for high-security scenarios. Fix: Add optional support for certificate pinning and custom TLS validation callbacks. Document TLS best practices. - Low · Testing Framework Could Mask Security Issues —
src/Flurl.Http/Testing/HttpTest.cs. The HttpTest framework (src/Flurl.Http/Testing/) allows mocking HTTP calls, which could encourage testing without proper security validation if not used carefully. Fix: Add documentation and examples showing how to test security features properly. Warn against using test mocks to bypass security checks.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.