0

I have two Symfony server instances. First is on 127.0.0.1:8080, second is on 127.0.0.1:8081.

When I'm trying to send POST method from the second instance to the first instance, using url 127.0.0.1:8081/create, I receive HTTP 500.

I'm using Windows 10. Running the servers locally works without a problem. The POST method works perfectly. So that's mean there is some problem with a Docker, but I don't know where. Is it CORS problem?

Here is my docker-compose.yml in the first instance:

version: '3'

services:
    nginx:
        build:
            context: ./docker/nginx/
            dockerfile: Dockerfile-nginx
        volumes:
            - .:/var/www/symfony/
        ports:
            - 8080:80
            
    php:
        build:
            context: ./docker/php74/
            dockerfile: Dockerfile-php74
        volumes:
            - .:/var/www/symfony/

and in the second instance:

version: '3'

services:
    nginx:
        build:
            context: ./docker/nginx/
            dockerfile: Dockerfile-nginx
        volumes:
            - .:/var/www/symfony/
        ports:
            - 8081:80
            
    php:
        build:
            context: ./docker/php74/
            dockerfile: Dockerfile-php74
        volumes:
            - .:/var/www/symfony/

Here is default.conf for the nginx:

server {
    proxy_busy_buffers_size 512k;
    proxy_buffers 4 512k;
    proxy_buffer_size 256k;

    listen       80;
    server_name  localhost;
    root /var/www/symfony/public;

    location / {
        try_files $uri @rewriteapp;
    }

    location @rewriteapp {
        rewrite ^(.*)$ /index.php/$1 last;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass php:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS off;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
        
         # https://enable-cors.org/server_nginx.html
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            #
            # Custom headers and headers various browsers *should* be OK with but aren't
            #
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            #
            # Tell client that this pre-flight info is valid for 20 days
            #
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain; charset=utf-8';
            add_header 'Content-Length' 0;
            return 204;
        }

        if ($request_method = 'POST') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
        }

        if ($request_method = 'GET') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
        }

    }

    error_log /dev/stdout info;
    access_log /var/log/nginx/symfony_access.log;
}

Has anyone had a similar problem before?

@EDIT: This is my ApiController.php where I'm making a call to other server instance.

<?php

namespace App\Controller;

use App\Entity\Argument;
use App\Repository\ArgumentRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class ApiController extends AbstractController
{
    /**
     * @Route("/create", name="create_argument", methods={"POST"})
     */
    public function createArgument(Request $request, HttpClientInterface $client)
    {
        if (!strpos($request->headers->get('Content-Type'), 'application/json'))
        {
            $data = $request->toArray();
            $name = $data['name'];

            $response = $client->request(
                'POST',
                'http://127.0.0.1:8080/name',
                [
                    'headers' => [
                        'Content-Type' => 'application/json',
                        ],
                    'json' => ['name' => $name],
            ]);

            if ($response->getStatusCode() == 200)
            {
                $content = $response->toArray();
                $content['name'] = strrev($content['name']);

                $argument = new Argument();
                $argument->setName($content['name']);

                $entityManager = $this->getDoctrine()->getManager();
                $entityManager->persist($argument);
                $entityManager->flush();

                return new Response("Argument added", Response::HTTP_OK);
            }
        }

        return new Response("Bad request", Response::HTTP_BAD_REQUEST);
    }

    /**
     * @Route("/show", name="show_arguments", methods={"GET"})
     */
    public function showArguments(ArgumentRepository $repository)
    {
        $arguments = $repository->findAll();

        if (!$arguments)
            return new Response('There are no tasks.', Response::HTTP_NOT_FOUND);

        $encoders = [new XmlEncoder(), new JsonEncoder()];
        $normalizers = [new ObjectNormalizer()];
        $serializer = new Serializer($normalizers, $encoders);

        $content = $serializer->serialize($arguments, 'json');

        return new JsonResponse($content, Response::HTTP_CREATED, [], true);
    }
}
szym3ns
  • 5
  • 3
  • What does your error log say? – Abbas Akhundov Jan 26 '21 at 12:05
  • There are at least five different ideas of what 127.0.0.1 is here (each container believes 127.0.0.1 is itself, and those are different from the host proper). Can you edit the question to include the code that's making the call (as inline text, not an image and not behind a link) and the actual error you're getting (similarly)? – David Maze Jan 26 '21 at 12:09
  • @DavidMaze I pasted the code. I don't get any error, only 500 HTTP when I call /create. When I call 127.0.0.1:8081/show it works perfectly. The same for 127.0.0.1:8080/name in the first instance. – szym3ns Jan 26 '21 at 12:17

1 Answers1

1

When you send the request to the http://127.0.0.1:8080/name by Symfony HTTP client inside the container, the IP 127.0.0.1 is localhost of first php container, not your host with Windows.

The first server instance knows nothing about the second.

You should use the IP of your host machine with Windows instead 127.0.0.1

The example:

$response = $client->request(
    'POST',
    'http://10.0.75.1:8080/name',
    [
        'headers' => [
            'Content-Type' => 'application/json',
         ],
        'json' => ['name' => $name],
    ]
);

See how to get the IP of host

Also, you can merge 2 docker-compose.yml files into one, so you will have a common network between 2 server instances and each instance will know about other.

Updated: Also, you can add hostname: hostname for php service and use hostname as URL of your host.

version: '3'
services:
    nginx:
        build:
            context: ./docker/nginx/
            dockerfile: Dockerfile-nginx
        volumes:
            - .:/var/www/symfony/
        ports:
            - 8081:80
            
    php:
        build:
            context: ./docker/php74/
            dockerfile: Dockerfile-php74
        volumes:
            - .:/var/www/symfony/ 
        hostname: hostname

PHP code:

$response = $client->request(
    'POST',
    'http://hostname:8080/name',
    [
        'headers' => [
            'Content-Type' => 'application/json',
         ],
        'json' => ['name' => $name],
    ]
); 
Artem
  • 1,426
  • 12
  • 17
  • I created one docker-compose file as you said and still http 500 appear when I'm trying to send POST method from the second instance to the first instance. I thought that will help but I'm still doing something wrong. Here is my docker-compose.yml https://pastebin.com/9QKA8L2h – szym3ns Jan 27 '21 at 13:37
  • I see that I can ping first instance inside second instance. I think that there is wrong url in the response. It's not '127.0.0.1:8080' but something else. Any suggestions? – szym3ns Jan 27 '21 at 13:54
  • Could you run the command `ping secondinstance` inside the php_firstinstance container? – Artem Jan 27 '21 at 14:21
  • Bro I fixed the problem. I changed ports in the docker-compose.yml file (8080:80 => 8080:8080 and 8081:80 => 8081:8081), ports in the default.conf (nginx) for the each service (from 80 to 8080 and from 80 to 8081) and I changed servername in default.conf too (from localhost to the firstinstance/secondinstance) and it works!! Thank you for all help. – szym3ns Jan 27 '21 at 14:38