1

folks.

I have a servive running on my host machine. It is a NodeJS app with Express. It works fine at "localhost:3000".

Then, in a separate project, I have a Laravel App running fine inside Docker, and I access it at "http://localhost".

Now, my Laravel app needs to call the NodeJS app. I saw in Docker documentation I should use "host.docker.internal", since it will resolve to my host machine.

The this->http is a Guzzle\Client instance.

In my PHP code I have this:

$response = $this->http->request('POST', env($store->remote), [
    'form_params' => [
        'login' => $customer->login,
        'password' => $customer->password,
    ]);

If I call the NodeJS app from Postman it works fine. But calling from that PHP I got this error:

"message": "Client error: `POST http://host.docker.internal:3000` resulted in a `404 Not Found` response:\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot POST /</p (truncated...)\n",
    "exception": "GuzzleHttp\\Exception\\ClientException",
    "file": "/var/www/html/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php",
    "line": 113,

Does anyone have any clue how I can call my node app from PHP in Docker?

EDIT

I was thinking if I should not open the port 80 and bind it to port 3000 in my PHP instance (since the request is running in php docker image). I put in my Docker file these ports attribute:

php:
    build: ./docker
    volumes:
      - .:/var/www/html
      - ./.env:/var/www/html/.env
      - ./docker/config/php.ini:/usr/local/etc/php/php.ini
      - ./docker/config/php-fpm.conf:/usr/local/etc/php/php-fpm.conf
      - ./docker/config/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
    links:
      - mysql
    ports:
      - "3000:80"

So, port 80 in my PHP instance would bind to my OSX port 3000. But Docker complains port 3000 is in use:

Cannot start service php: b'driver failed programming external connectivity on endpoint project_php_1 (241090....): Error starting userland proxy: Bind for 0.0.0.0:3000 failed: port is already allocated'

Yes! In fact it is allocated. It is allocated by my NodeJS app, that is where I want to go. It looks like I do not know very well how ports and DNS works inside Docker for Mac.

Any help is very appreciated.

SOLVED

Hey, guys. I figured it out. I turned off Docker container, point a regular Apache to my Laravel project and I got what was happening: CORS.

I already had cors in my Express app, but after configure it better, it worked!

Here it is, in case anyone stumbled here and needs it:

1) Add cors to your Express (if you haven't yet)

2) Configure cors to your domains. For now, I will keep it open, but, for production APPS, please, take care and control wisely who can query your app:

// Express app:
app.use(
cors({
    "origin": "*",
    "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
    "preflightContinue": false,
    "optionsSuccessStatus": 204
  })
);
app.options('*', cors());

3) Use the host.docker.internal address (in my case, host.docker.internal:3000 , since my app is running on that port) from PHP to get to your Express App in OSX host machine. In my case, it will be a different domain/IP when it gets to production.

4) Just use Guzzle\Client to make your http call:

$response = $this->http->request('POST', env($store->remote) . '/store-api/customers/login', [
                'json' => [
                    "login" => $customer->login,
                    "password" => encrypt($customer->password),
                ]
            ]);

A important point to note: Express waits for json (in my app, at least), so do NOT use "form_data", use "json" option to POST requests:

At least, it was NOT a duplication of the other answers, as marked by @Phil, because those answers points to the same solution I have already mentioned, use the 'host.docker.internal' address.

ppalmeida
  • 2,924
  • 5
  • 20
  • 25
  • So you're wanting a container process to communicate with a host process running on port 3000, correct? See [this answer](https://stackoverflow.com/a/43541732/283366) – Phil Sep 16 '18 at 03:01
  • Your update doesn't make any sense. PHP / Guzzle are not subject to the same-origin policy. This was definitely not a CORS issue at least, not within the scope of the code you've posted. CORS issue only affect JavaScript requests – Phil Sep 16 '18 at 06:55
  • The only significant change I can see is swapping `form_params` to `json`. I suspect that's the only thing you had to fix up so if you want a more accurate _close_ reason, it's _"just a typo"_ – Phil Sep 16 '18 at 07:00
  • Yeah, I agree that cors should not interfere with PHP/Guzzle. I will check it again and come back. Maybe is the *form_params* to *json*. But, in theory, that should not throw 404 responses. By the way, thank you for your comments :-) – ppalmeida Sep 16 '18 at 15:02

0 Answers0