4

Explanation

I made a simple REST api in Java (GET).

  • Postman works (both localhost and IPv4)

  • curl from command line works (both localhost and IPv4)

  • External request from a different city works (IPv4)


Expected

To have PHP curl work on the localhost

Actual

For some reason PHP curl on IPv4 works, but localhost does not work


PHP curl output error

  • Failed to connect to localhost port 8080: Connection refused

  • curl error: 7


Code

$url = 'http://localhost:8080/api/user';
$curl = curl_init($url);
echo json_decode(curl_exec($curl));

I have tried (from the top of my head, no specific order)

curl_setopt ($curl, CURLOPT_PORT , 8080);
curl_setopt($curl, CURLOPT_POST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
Jsh0s
  • 519
  • 1
  • 8
  • 18
  • @Calos sorry I'm not sure what you mean, but I'm using a tomcat local server, spring boot application – Jsh0s Feb 04 '20 at 03:06
  • 1
    @Calos I actually disabled the fiewall while trying to fix this, didn't work, I have a question, if its not listening why does postman and command line curl work on localhost? just php curl doesn't – Jsh0s Feb 04 '20 at 03:20
  • @Calos It's been there since the beginning, I mentioned both of them right at the top of my post – Jsh0s Feb 04 '20 at 03:57
  • **[You should not switch off `CURLOPT_SSL_VERIFYHOST` or `CURLOPT_SSL_VERIFYPEER`](https://paragonie.com/blog/2017/10/certainty-automated-cacert-pem-management-for-php-software)**. It could be a security risk! [Here is how to get the certificate bundle if your server is missing one](https://stackoverflow.com/a/32095378/1839439) – Dharman Feb 08 '20 at 17:49

4 Answers4

18

For those ones who are using Docker, Vargant and so on.

You got Failed to connect to localhost port 8080: Connection refused error, because you are trying to connect to localhost:8080 from inside virtual machine (eq. Docker), this host isn't available inside the Docker container, so you should add a proxy that can reach a port from the out.

To fix this issue add the next line of code after your curl_init():

curl_setopt($ch, CURLOPT_PROXY, $_SERVER['SERVER_ADDR'] . ':' .  $_SERVER['SERVER_PORT']);

Here is a full example:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $APIUrl);

if ($_SERVER['HTTP_HOST'] == 'localhost:8080') {
    // Proxy for Docker
    curl_setopt($ch, CURLOPT_PROXY, $_SERVER['SERVER_ADDR'] . ':' .  $_SERVER['SERVER_PORT']);
}

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);

if (curl_errno($ch)) {
    $error = curl_error($ch);
}

curl_close($ch);
Serhii Popov
  • 3,326
  • 2
  • 25
  • 36
  • That's a very good workaround for Docker. – Claudio Silva Feb 24 '21 at 13:32
  • It doesn't work for me. I got `Failed to connect to 172.18.0.3 port 8080: Connection refused` which has IP and port of server inside Docker. I call API of a container from another container. They run in different ports. – Tommy Hoang Nov 24 '22 at 09:06
1

I'm not sure if this counts as an answer but I just restarted the linux VM and now its working...

Jsh0s
  • 519
  • 1
  • 8
  • 18
  • 1
    It actually counts as not reproducible. We usually delete such questions unless you think that this problem is going to happen to other people and this simple suggestion will help them too. – Dharman Feb 08 '20 at 17:50
  • @Dharman I agree, this might not help anybody, should I delete it? – Jsh0s Feb 08 '20 at 21:47
0

Not sure if it's still usefull for you, but I've faced with almost same problem. I've started php server using php -S localhost:5500 or with VS-code extention, and try to connect via curl to same host, and it taken almost infinite time with no response. Solution was simple (if you understand russian, or can use translator you can find full article here). So, from this article:

This script will not work with the default WPN-XM v0.8.6 setting because there is only one php -C gi process listening in the background, but your example requires (at least) two of them. php -C gi is already in use by the script making the curl request and therefore Nginx cannot redirect it to php -C gi. This means that you will first come across a blank page with a loading indicator and then remove the connection timeout. The main problem is that php -C gi doesn't automatically spawn new processes (if needed). The issue is discussed here: https://github.com/WPN-XM/WPN-XM/issues/323

So the solution for me was to create another php server with a different port (for example 5500 and 5550) and everything started working.

0

I also add here something for those ones who are using Docker:

If having a default web app and an API, of course these should be two different services.

Here's a docker compose example:

version: '3'
services:
    default:
        container_name: web_app
        build: 
            context: ./
            dockerfile: ./default_page/Dockerfile
        volumes:
            - ./default_page:/var/www/html
        ports:
            - 8080:80
        networks:
            - my-network
    api:
        container_name: api
        build:
            context: ./
            dockerfile: ./default_page/html/public-html/api/Dockerfile
        volumes:
            - ./default_page/html:/var/www/html
        ports:
            - 3000:80
        networks:
            - my-network

networks:
    my-network:
        driver: bridge

I'm having this folder structure with default_page/html, so I can easily FTP deploy with a non public folder (DEV shared hosting fail ).

Now PHP curl is possible like that:

$apiUrl = "http://api/public-html/user"; // whatever endpoint
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);

Please check here as well that I have this public-html, which is unnecessary for other cases.

PS: sorry for being lazy and not provide an answer with clean folder structure. Of course in a usual environment and not having to few money for a real server, the web-app and the api should be in a separate folder.

Kurt Lagerbier
  • 170
  • 2
  • 11