szym3ns
szym3ns

Reputation: 5

Can't call GET method from the other docker container (HTTP 500)

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);
    }
}

Upvotes: 0

Views: 1189

Answers (1)

Artem
Artem

Reputation: 1646

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],
    ]
); 

Upvotes: 1

Related Questions