In our error capturing software we started getting errors like this:
PHP Warning: Undefined array key “host” in /home/…/public_html/wp-includes/canonical.php on line 699
PHP Warning: Undefined array key “scheme” in /home/…/public_html/wp-includes/canonical.php on line 720
An odd little error as whilst it is just a warning, it does have some impact. Although generally not an impact that would be concerning. HTTP comes in a few versions, with the original being HTTP 1.0 from a long time ago. HTTP 1.0 was simple, but functional, but had one particularly limiting issue. You could only host one web site on each server. It’s successor HTTP 1.1 added a mechanism where the client could specify which website it wanted to talk to, known as a Host header, allowing a server to operate multiple websites. Because of the obvious advantages of this, virtually every web server nowadays speaks at least HTTP 1.1.
Looking at the offending WordPress file we see the following piece of code further up in the file than the reported errors:
if ( ! $requested_url && isset( $_SERVER['HTTP_HOST'] ) ) {
// Build the URL in the address bar.
$requested_url = is_ssl() ? 'https://' : 'http://';
$requested_url .= $_SERVER['HTTP_HOST'];
$requested_url .= $_SERVER['REQUEST_URI'];
}
$_SERVER[‘HTTP_HOST’] is testing for the HTTP 1.1 or later host header. If it’s there than it does some work to build the “requested url”. That’s all well and good, but it assumes then that the request is HTTP 1.1 or later. As we discussed, older HTTP 1.0 requests won’t have this because it wasn’t in the specification at the time.
How do we fix this? Given it’s an older request then it makes sense to use the server’s address where the host header isn’t present. We decided to correct it like this:
if ( ! $requested_url && ( isset( $_SERVER['HTTP_HOST'] ) || isset ( $_SERVER['SERVER_ADDR'] ) ) ) {
// Build the URL in the address bar.
$requested_url = is_ssl() ? 'https://' : 'http://';
$requested_url .= $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_ADDR'];
$requested_url .= $_SERVER['REQUEST_URI'];
}
Initial tests seem promising but we need to see what happens when it is live (if it works we’ll submit the change). The reason we need to test it some more is that these are rare requests. HTTP 1.0 is barely used anymore.
In fact it’s used so little that the cause of these errors showing up are almost certainly either hackers or scammers running scripts to probe the internet. Our reporting shows they used http (a non encrypted connection) and the HTTP 1.0 protocol is simpler, both making it easier for the script kiddies. We plan, in the future, to have our software block questionable connections in the future. So it’s not something that concerns us too much. As it stands these requests are simply being redirected to wordpress (after the warnings are raised) to https:/// , which doesn’t exist.