Recently we setup a sandbox server for one of our APIs. You know, it’s always a good idea to have customers play with a sandbox rather than with a production system. The setup went smoothly and the API did pass all the tests. However, one of our customers complained that when they were accessing the API via PHP they were getting “Empty reply from server”.
The Problem – Empty Response
What the heck, we thought and tried to replicate the problem. Exactly as the customer had reported, the API worked well from Postman and command line CURL but was failing with the PHP CURL big time. “Empty reply from server” was the exact error message.
We have an Nginx server sitting as a proxy in front of our application. A quick test revealed that the requests were not even reaching our API. So there was something in Nginx or in PHP.
A Strategy for Solving the Problem
Whenever we need to find a nasty bug in code or just want to solve a problem we always look at a working system and then try to spot a difference. But the irony is that our environments seemed to be exactly the same. Both the live and the sandbox servers run Debian Jessie 64 bit and we use the same version of Nginx.
One difference was that for the staging API we used a hyphen in the URL (to be more precise we used a sub-domain containing hyphen). After some Googling we came across a discussion saying that hyphens were not supported by CURL. It was a revelation. We quickly removed the hyphen from the sub-domain just to learn that it did have no effect. What a disappointment.
The Aha Moment
Finally we started comparing Nginx configurations. In our understanding this was the last point of hope. To our discouragement they looked exactly the same or did they? We were about to start screaming when we noticed a seemingly innocent difference between the configuration files. The production server had three lines of SSL configuration.
ssl_ciphers ECDH+AESGCM:H+AESGCM:ECDH+AES256:H+AES256:ECDH+AES128:H+AES:ECDH+3DES:H+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
ssl_session_cache shared:SSL:10m;
ssl_prefer_server_ciphers on;
So we quickly copied the SSL configuration lines to the sandbox and voila it all worked well. We hope this helps if you are stuck in a similar situation.