Debugging HTTP requests to PHP via the CLI

Want to help support this blog? Try out Oh Dear, the best all-in-one monitoring tool for your entire website, co-founded by me (the guy that wrote this blogpost). Start with a 10-day trial, no strings attached.

We offer uptime monitoring, SSL checks, broken links checking, performance & cronjob monitoring, branded status pages & so much more. Try us out today!

Profile image of Mattias Geniar

Mattias Geniar, April 22, 2014

Follow me on Twitter as @mattiasgeniar

You’re a sysadmin. You love the CLI. You use PHP. Surely, you should be able to troubleshoot PHP applications that are normally run via an HTTP server through the CLI as well, right? Well good news; you can – with a few caveats.

This is in follow-up of a blogpost I made in 2012 titled “Running php-cgi scripts via the CLI as a webserver would (by faking them)". If you can run your PHP applications via the CLI, you can use tools such as strace to debug the PHP app’s behaviour.

TL;DR: you can fake pretty much any HTTP request by setting the correct environment variables before you call the PHP binary.

First, the caveats.

  • Your PHP settings may be altered or overwritten in the webserver (Apache/PHP-FPM daemon), the PHP binary you run via CLI may not have a correct representation as the PHP(-FPM) binary used via that HTTP server – so check your PHP settings;
  • You won’t be using the APC or OPcache as you’re running PHP via the CLI, neither the opcode nor the key/value cache of APC/OPcache is used;
  • Your $_SERVER environment variables will be different than via an HTTP webserver, keep that in mind if your application depends on it;

Now. On with it.

Basic web application

If you have a simple PHP application you will most likely be able to run it simply via the CLI.

$ cd /path/to/your/docroot
$ php index.php

The output can (but is not necessarily the case) be the same as if it were called via the web.

Using environment variables to determine dev/staging/prod

Just like you can specify environment variables in Nginx or Apache, to allow your code to use different users/passwords/settings, it can be used via the CLI as well. If your application depends on an environment variable called APPLICATION_ENV to distinguish environments, you can add it to your request.

$ cd /path/to/your/docroot
$ APPLICATION_ENV=development \
  php index.php

A framework which uses routes

If you’re using a framework that has a routing controller, to map URI’s directly to the index.php file, you can add environment variables to make the PHP app think you’re requesting a specific URI.

$ cd /path/to/your/docroot
$ REQUEST_URI=/your-test-page \
  php index.php

Multi-domain PHP application

If you’re running your PHP application as a multi-site app, meaning your content and code behaviour can differ depending on the hostname being used in the request, you can also pass those along as environment variables.

$ cd /path/to/your/docroot
$ SERVER_NAME=www.yoursite.tld \
  HTTP_HOST=www.yoursite.tld \
  REQUEST_URI=/your-test-page \
  php index.php

Sending POST requests at CLI

The HTTP method is just a environment variable – so it’s changeable.

$ cd /path/to/your/docroot
$ REQUEST_METHOD=POST \
  CONTENT_TYPE=application/www-form-urlencoded \
  REQUEST_URI=/your-test-page php index.php

Conclusion

Running these PHP commands via the CLI allows you to troubleshoot applications more easily, as you can now reproduce specific HTTP requests on demand. The main benefit comes from the ability to attach a debugger (such as gdb or strace, sysdig) to that process.

You can see all low-level system calls as well as all network traffic (such as MySQL queries, memcached requests, MongoDB traffic, …) as your application is sending and receiving it.



Want to subscribe to the cron.weekly newsletter?

I write a weekly-ish newsletter on Linux, open source & webdevelopment called cron.weekly.

It features the latest news, guides & tutorials and new open source projects. You can sign up via email below.

No spam. Just some good, practical Linux & open source content.