vipnytt/robotstxtparser
A PHP library for parsing robots.txt files, with support for user-agent groups, Allow/Disallow rules, wildcards, crawl-delay, and sitemap directives. Lightweight and framework-agnostic, it helps determine whether a crawler may access a given URL.
Architecture fit — vipnytt/robotstxtparser is a framework-agnostic, PSR-4 composer package with two distinct concerns bundled together: a stateless parser (tokenizes a robots.txt payload into typed directive objects) and a client (fetches the file from a host). The parser half fits cleanly into a Laravel domain layer behind a service contract; it holds no state, does no I/O, and is trivially testable with fixture strings. The client half is the integration risk: it introduces transport concerns (HTTP client choice, timeouts, redirects) that Laravel already owns via the Http facade, so the recommended posture is to consume the parser directly and either bypass or wrap the client. The library's extensibility model — registering custom directive handlers — is its main architectural asset, because it lets us support non-standard directives (Clean-param, Request-rate, Noindex) without forking.
Integration feasibility — MIT license, composer-installable, no Laravel service provider or facade, so it requires a thin adapter (~50–100 LOC) to bind behind an interface. The real gate is version compatibility: the last release was April 2021, which predates PHP 8.1/8.2/8.3 deprecation cycles. Before committing, install it on the target PHP runtime and run the test suite plus a fixture corpus with E_ALL to surface implicit-nullable and dynamic-property warnings. This is a half-day spike, not a blocker.
Technical risk — concentrated in provenance and longevity, not in code quality. 25 stars, an unverified/unknown repository location, and no release in roughly four years means: bus factor of effectively one, no security response path, and no guarantee the source matches the Packagist artifact. The robots.txt spec itself is stable (RFC 9309), which mitigates the staleness risk considerably — the parsing rules are not moving targets. Extensibility means we can patch behavior by subclassing rather than forking, but any upstream defect is ours to fix permanently. Treat this as vendored code with a friendly license, not as a maintained dependency.
Key questions
composer.json PHP constraints, and does it run clean on our target runtime?file_get_contents)? Can we bypass it and feed the parser a body we fetched ourselves?Allow/Disallow longest-match precedence, * wildcards, and end-anchored $? Does it differentiate User-agent: * from specific agents correctly?Stack fit — Laravel 10/11/12 on PHP 8.2+. Register a RobotsTxtService contract in the container with two responsibilities kept deliberately separate: fetch(host): string (Laravel Http, retries, timeout, caching, SSRF allowlist) and parse(string, userAgent): RuleSet (this package). This gives us the library's parsing correctness without inheriting its transport opinions, and it keeps the package behind a seam we can swap for a maintained alternative or an in-house parser later with no call-site changes.
Migration path — Greenfield integration, no data migration. If an ad-hoc regex-based robots.txt check already exists (common in sitemap generators, crawlers, and SEO tooling), run both implementations in shadow mode across a sample of production hosts and diff the resulting rule sets before cutting over. Divergences are almost always wildcard/precedence edge cases and are the fastest way to validate the library against our real traffic.
Compatibility — Verify autoload and PHP constraint on day one. If the package emits deprecations, the cheapest fix is a pinned fork under an internal namespace (MIT permits it) rather than suppression via error handler. Confirm no transitive dependency conflicts with the framework's Guzzle/PHPUnit versions if you do pull in the client.
Sequencing
Http with per-host rate limiting, TTL cache, redirect cap, size cap, and an explicit host allowlist.Maintenance — Low ongoing effort but non-zero: budget roughly one small patch per PHP minor release. Because the upstream is dormant, maintenance is our responsibility regardless of activity. If usage becomes load-bearing (e.g., a crawler product surface), plan to fork into an internal namespace and own the test suite; if usage stays peripheral, vendor the pinned version and revisit annually.
Support — No commercial backing, minimal issue throughput. The escalation path is internal. Document that reality at adoption time so nobody assumes an upstream fix is coming.
Scaling — Parsing is CPU-trivial and stateless: it scales horizontally with the app tier and needs no special treatment. The scaling cost sits entirely in fetching, which is I/O-bound and per-host rate-limited. Push fetches onto queued jobs, key cached rule sets by host + user_agent, use a 12–24 hour TTL, and honor Crawl-delay/Request-rate directives to avoid getting the platform's egress IPs blocked. A single shared cache table prevents N workers from hammering the same origin.
Failure modes — Network timeout or DNS failure during fetch; redirect chains; oversized or gzip-corrupt payloads; mixed encodings; non-200 responses where the interpretation (allow-all vs. disallow-all) must match spec; wildcard and longest-match precedence bugs producing silently wrong crawl decisions; IP-literal or internal-network hosts creating an SSRF vector if fetching is ever driven by user input. Mitigate with a hard timeout, a redirect cap, a body size cap, an explicit host allowlist, and a documented fail-safe default policy applied whenever parsing or fetching raises — never let an exception become an implicit "allow everything."
Ramp-up — A day for a mid-level PHP developer to read the source and integrate the parser (the code is small and readable; the directive classes are self-describing). Two to three days more for the fetch/cache/SSRF layer, which is standard Laravel work and does not require specialized crawler knowledge. The only genuinely non-obvious area is robots.txt precedence semantics — worth a short internal write-up with fixtures so that behavior is documented rather than rediscovered during an incident.
How can I help you explore Laravel packages today?