I have two Symfony apps (APIs) talking to each other via HTTP requests/responses using cURL PHP function. This works fine when they get small JSON responses, but the problem comes when getting and serving files. API1 (exposed to the Internet) needs to serve a file that is only accessible by API2(private, connected to API1 via VPN).
If I encode the content of the file in the first API and then pass it in the response body there is no problem, I can reconvert the file back to a stream and serve in the first API as a BinaryFileResponse. The problem comes with big files (>30MB), where the response body is huge and symfony's is not able to allocate that much memory.
Is there a way to forward or redirect a BinaryFileResponse from one API to the other, so the middle layer is invisible for the client?
These are the two pieces of code in each application:
Public API:
/**
*
* @Get("/api/login/getfile")
*/
public function testGetFilePrivate(Request $request)
{
$url = 'private/variantset/9/getfile';
$url = $this->container->getParameter('api2_url').$url;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 300000); //Set timeout in ms
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, TRUE);
$fileContent = base64_decode($data['filedata']);
$response = new Response($fileContent);
$disposition = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$data['filename']
);
$response->headers->set('Content-Disposition', $disposition);
return $response;
}
Private API:
/**
* @Get("/api/private/variantset/{id}/getfile")
*/
public function getVariantsetDataFileById($id)
{
$variantset = $this->getVariantsetById($id);
if(!$variantset){
$response = array("getdata"=>"ko","error"=>"Variantset does not exists");
return new JsonResponse($response);
}
if($variantset->getCreated()){
$auth_variants_dir = $this->container->getParameter('auth_variants_path');
$file_path = $auth_variants_dir . '/' . $variantset->getDatafile() . '.gpg';
$data = [
"getdata"=>"ok",
"filename" => $variantset->getDatafile() . '.gpg',
"filedata" => base64_encode(file_get_contents($file_path))
];
$response = new Response();
$response->setContent($this->container->get('serializer')->serialize($data, 'json'));
$response->headers->set('Content-Type', 'application/json');
}else{
$response = new JsonResponse(array("getdata"=>"ko","error"=>"Variantset does not have a file yet"));
}
return $response;
}