Skip to content

Kévin Dunglas

Founder of Les-Tilleuls.coop (worker-owned cooperative). Creator of API Platform, Mercure.rocks, Vulcain.rocks and of some Symfony components.

Menu
  • Talks
  • Resume
  • Sponsor me
  • Contact
Menu

PHP 7: Introducing a domain name validator and making the URL validator stricter

Posted on November 28, 2014November 28, 2014 by Kévin Dunglas

PHP Origami

DNS comes with a set of rules defining valid domain names. A domain name cannot exceed 255 octets (RFC 1034) and each label cannot exceed 63 octets (RFC 1035). It can contain any character (RFC 2181) but extra rules apply for hostnames (A and MX records, data of SOA and NS records): only alphanumeric ASCII characters and hyphens are allowed in labels (we’ll talk about IDNs at the end of this post), and they cannot start nor end with a hyphen.

Until now, there was no PHP’s filter validating that a given a string is a valid domain name (or hostname). Worst, FILTER_VALIDATE_URL was not fully enforcing domain name validity (this is mandatory for schemes such as http and https) and was allowing invalid URLs. FILTER_VALIDATE_URL was also lacking IPv6 host support.

<?php

// PHP 5.6.3

// Label ends with a hyphen
var_dump(filter_var('http://a-.bc.com', FILTER_VALIDATE_URL));
// string(16) "http://a-.bc.com"

// Label is more than 63 octets
var_dump(filter_var('http://toolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolong.com', FILTER_VALIDATE_URL));
// string(81) "http://toolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolong.com"

// Lack of IPv6 support
var_dump(filter_var('http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]', FILTER_VALIDATE_URL));
// bool(false)

These limitations will be fixed in PHP 7. I’ve introduced a new FILTER_VALIDATE_DOMAIN filter checking domain name and hostname validity. This new filter is now used internally by the URL validator. I also added IPv6 host support in URL validation:

<?php

// PHP 7.0.0-dev

// Validate a domain name
var_dump(filter_var('mandrill._domainkey.mailchimp.com', FILTER_VALIDATE_DOMAIN));
// string(33) "mandrill._domainkey.mailchimp.com"

// Validate an hostname (here, the underscore is invalid)
var_dump(filter_var('mandrill._domainkey.mailchimp.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
// bool(false)

// Label ends with a hyphen
var_dump(filter_var('http://a-.bc.com', FILTER_VALIDATE_URL));
// bool(false)

// Label is more than 63 octets
var_dump(filter_var('http://toolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolong.com', FILTER_VALIDATE_URL));
// bool(false)

// Lack of IPv6 support
var_dump(filter_var('http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]', FILTER_VALIDATE_URL));
// string(48) "http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]"

There is still a big lack in PHP’s domain names and URLs handling: internationalized domain names are not supported at all in the core. I’ve already blogged about an userland workaround, but as IDNs becomes more and more popularsa core support by PHP in streams and validation is necessary. For instance, almost all french registrars support them, and even TLDs – such as the Chinese one – are available in the wild in a non-ASCII form). I’ve started a patch enabling IDN support in PHP’s streams. It works on Unix but still lacks a Windows build system. As it requires making ICU a dependency of PHP, I’ll publish a PHP RFC on this topic soon!

Related posts:

  1. Internationalized Domain Name (IDN) and PHP
  2. Introducing the phpdoc-to-typehint Converter: add scalar type hints and return type declarations to your projects
  3. Making the Sonata Project better
  4. Making the Symfony PropertyAccess Component 84% faster in 2.8… and counting

6 thoughts on “PHP 7: Introducing a domain name validator and making the URL validator stricter”

  1. Pingback: Дайджест интересных новостей и материалов из мира PHP № 52 (16 – 30 ноября 2014) | [email protected]
  2. zanechua says:
    January 25, 2019 at 7:30 am

    Would like to mention that the following filter works well however it even works for domains without TLDs. So if you use this ‘a’ or ‘hello’ without a tld is still considered as valid domain/host names.

    I wonder if it’s possible to introduce a flag to require at least a TLD or perhaps one “subdonm” level

    Reply
    1. Kévin Dunglas says:
      January 25, 2019 at 8:00 am

      Hi, indeed it’s intended because both `a` and `hello` are valid domain name (and useful when configuring a local network). You can check if the domain has a TLD by checking if it contains a dot. Why not adding a flag for that! If you open a PR for that, please ping me!

      Reply
      1. zanechua says:
        January 25, 2019 at 3:11 pm

        I was actually thinking of adding a flag for that but not too sure how to contribute to the php source at the moment but will definitely go check it out and see if I can do it. hahaha!

        I am using this simple check at the moment:

        (bool) (filter_var($value, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) && preg_match(‘@\.(.*[A-Za-z])@’, $value))

        Reply
  3. Vikash kumar singh says:
    August 28, 2019 at 1:46 pm

    Very helpful tutorial. Can you share a tutorial on FQDNs validation in PHP.?

    Reply
  4. Terry Lin says:
    January 31, 2020 at 10:36 am

    Thanks. This is useful artcile. Does it work on IDNs?

    Reply

Leave a Reply Cancel reply

Follow me on Twitter

My Tweets

Subscribe to this blog

Recent Posts

  • Symfony ImportMaps: Manage Your JavaScript Dependencies Without Node
  • Read the Linux Manual Pages on Mac and BSD, Directly From the Terminal
  • Ne vous lamentez pas, organisez-vous !
  • FrankenPHP: The Modern Php App Server, written in Go
  • API Platform 3 Is Released!

Top Posts & Pages

  • Symfony ImportMaps: Manage Your JavaScript Dependencies Without Node
  • Securely Access Private Git Repositories and Composer Packages in Docker Builds
  • JSON Columns and Doctrine DBAL 3 Upgrade
  • Preventing CORS Preflight Requests Using Content Negotiation
  • Generate a Symfony password hash from the command line
  • Goroutines, threads, and thread IDs
  • API Platform 3 Is Released!
  • FrankenPHP: The Modern Php App Server, written in Go
  • Symfony's New Native Docker Support (Symfony World)
  • Symfony UX Turbo: Do You Still Need JavaScript?! (SymfonyWorld)

Persistence in PHP with the Doctrine ORM

Persistence in PHP with the Doctrine ORM

Tags

Apache API API Platform Buzz Caddy Docker Doctrine Go Google GraphQL HTTP/2 Hydra hypermedia Hébergement Javascript JSON-LD Kubernetes La Coopérative des Tilleuls Les-Tilleuls.coop Lille Linux Mac Mercure Messagerie Instantanée MySQL PHP Punk Rock Python React REST Rock'n'Roll RSS Schema.org Security SEO SEO Symfony Symfony Live Sécurité Twitter Ubuntu Web 2.0 Wordpress XHTML XML

Archives

Categories

  • DevOps (25)
  • Mercure (4)
  • Opinions (91)
  • Programming (186)
    • Android (5)
    • Go (13)
    • JavaScript (44)
    • PHP (144)
      • API Platform (65)
      • Symfony (90)
    • Python (14)
      • Django (5)
  • Security (15)
  • SEO (24)
  • Talks (39)
  • Ubuntu (68)
  • Wordpress (6)

Social

  • Mastodon
  • Twitter
  • LinkedIn
  • YouTube
  • GitHub

Links

  • API Platform
  • Les-Tilleuls.coop
  • Mercure.rocks
  • Vulcain.rocks
© 2023 Kévin Dunglas | Powered by Minimalist Blog WordPress Theme