URL Parts
Level: Intermediate 30–60 minConcepts: ParsingStrings
Solutions: C# | TypeScript | Python
Decomposes a given URL into its parts.
For example when the URL https://www.tddbuddy.com is decomposed into its parts.
| Part | Value |
|---|---|
| Protocol | http |
| Subdomain | www |
| Domain | tddbuddy.com |
| Port | 80 (Default for HTTP) |
| Path | ” (Empty in our case) |
Please be sure to handle the following:
- Only top level domains like .com or .net.
- Do not worry second level domains like .co.uk or co.za
- Only the protocols specified in the default ports section below.
- Be sure to deal with local network hostname only cases. E.g. http://localhost
Do not use built-in classes like Uri to solve this.
Default Ports
http: 80, https: 443, ftp: 21, sftp: 22
Examples
| Examples |
|---|
|
URL: http://foo.bar.com/foobar.html Protocol: http Subdomain: foo Domain name: bar.com Port: 80 Path: foobar.html |
|
URL: https://www.foobar.com:8080/download/install.exe Protocol: https Subdomain: www Domain name: foobar.com Port: 8080 Path: download/installer.exe |
|
URL: ftp://foo.com:9000/files Protocol: ftp Subdomain: '' (empty string) Domain name: foo.com Port: 9000 Path: files |
|
URL: https://localhost/index.html#footer Protocol: https Subdomain: '' (empty string) Domain name: localhost Port: 443 Path: index.html |
Hints
Exclude the leading / when handling path. E.g. /download becomes download.
URL Grammar
Below is a EBNF like grammar for a URL as per this kata.
url = protocol ”://” [subdomain] host [top-level-domain] [”:” port] [path] [”?” parameters] [”#” anchor]
protocol = “http” | “https” | “ftp” | “sftp”
subdomain = alphanumeric string starting with alpha
host = alphanumeric string
top-level-domain = “.com” | “.net” | “.org” | “.int” | “.edu” | “.gov” | “.mil”
port = numeric
path = alphanumeric string
parameters = alphanumeric string
anchor = alphanumeric string
Reference Walkthrough
Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/url-parts. Ten shared scenarios cover the four protocols (http, https, ftp, sftp) with their default ports, explicit ports, paths with and without query strings, fragments, and the bare localhost host — satisfied identically across all three languages.
- C# (.NET 8, xUnit, FluentAssertions 6.12.0) — walkthrough
- TypeScript (Node 20, Vitest 1.6, TS 5 strict) — walkthrough
- Python (3.11, pytest) — walkthrough
This kata ships in Agent Full-Bake mode at high gear (F1 tier): the algorithm is small enough to land as one commit per language. There are no builders — the parse returns a typed UrlParts record (C# record, TS interface, Python @dataclass(frozen=True)) which is a data shape, not a fluent construction API. No regex and no built-in URL classes (System.Uri, new URL, urllib.parse) per the prompt: each language hand-rolls a left-to-right peel — anchor, then parameters, then path, then port, then host — so the order of operations stays visible in the code. See the repo’s Gears section for when high gear is the right call.
Related reading
- Katas Are Rehearsal, Not Performance
You don't practice TDD on production code. You practice on katas and bring the muscle memory to production. The gap between knowing TDD and doing TDD is reps. - Test Deletion Is a Privileged Operation
The cheapest way for an agent to make a failing test pass is to delete it. That is logical for the agent and catastrophic for the codebase. Tests are append-only by default. Deletion needs a human author, a separate commit, and a separate review. - Refactor Was Always Where Compounding Lived
Red and green were the visible two thirds of TDD. Refactor was the optional polish. Codebases that compound did the refactor pass; codebases that accrete did not. Agents skip refactor by default because it has no green-bar reward, and a year of skipped refactors is how a codebase loses its shape.