Skip to content

Commit

Permalink
use StreamedResponse in packages() controller method
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeroeny committed Sep 6, 2022
1 parent 50fe808 commit 4a3f401
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 37 deletions.
75 changes: 47 additions & 28 deletions src/Controller/RepoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;

final class RepoController extends AbstractController
{
Expand All @@ -41,32 +41,42 @@ public function __construct(
* @Route("/packages.json", host="{organization}{sep1}repo{sep2}{domain}", name="repo_packages", methods={"GET"}, defaults={"domain":"%domain%","sep1"="%organization_separator%","sep2"="%domain_separator%"}, requirements={"domain"="%domain%","sep1"="%organization_separator%","sep2"="%domain_separator%"})
* @Cache(public=false)
*/
public function packages(Request $request, Organization $organization): JsonResponse
public function packages(Request $request, Organization $organization): Response
{
$packageNames = $this->packageQuery->getAllNames($organization->id());
[$lastModified, $packages] = $this->packageManager->findProviders($organization->alias(), $packageNames);

$response = (new JsonResponse([
'packages' => $packages,
'available-packages' => array_map(static fn (PackageName $packageName) => $packageName->name(), $packageNames),
'metadata-url' => '/p2/%package%.json',
'notify-batch' => $this->generateUrl('repo_package_downloads', [
'organization' => $organization->alias(),
], UrlGeneratorInterface::ABSOLUTE_URL),
'search' => 'https://packagist.org/search.json?q=%query%&type=%type%',
'mirrors' => [
[
'dist-url' => $this->generateUrl(
'organization_repo_url',
['organization' => $organization->alias()],
RouterInterface::ABSOLUTE_URL
).'dists/%package%/%version%/%reference%.%type%',
'preferred' => true,
[$lastModified, $loader] = $this->packageManager->findProviders($organization->alias(), $packageNames);

$response = (new StreamedResponse(function () use ($organization, $packageNames, $loader): void {
$outputStream = \fopen('php://output', 'wb');
if (false === $outputStream) {
throw new HttpException(500, 'Could not open output stream to send binary file.'); // @codeCoverageIgnore
}

\fwrite($outputStream, ' ');
\flush();
\fwrite($outputStream, \json_encode([
'packages' => $loader(),
'available-packages' => array_map(static fn (PackageName $packageName) => $packageName->name(), $packageNames),
'metadata-url' => '/p2/%package%.json',
'providers-url' => '/p2/%package%.json',
'notify-batch' => $this->generateUrl('repo_package_downloads', [
'organization' => $organization->alias(),
], UrlGeneratorInterface::ABSOLUTE_URL),
'search' => 'https://packagist.org/search.json?q=%query%&type=%type%',
'mirrors' => [
[
'dist-url' => $this->generateUrl(
'organization_repo_url',
['organization' => $organization->alias()],
UrlGeneratorInterface::ABSOLUTE_URL
).'dists/%package%/%version%/%reference%.%type%',
'preferred' => true,
],
],
],
]))
->setPrivate()
->setLastModified($lastModified);
], JsonResponse::DEFAULT_ENCODING_OPTIONS));
}, Response::HTTP_OK, ['Content-Type' => 'application/json', 'X-Accel-Buffering' => 'no']))
->setLastModified($lastModified)
->setPrivate();

$response->isNotModified($request);

Expand Down Expand Up @@ -149,18 +159,27 @@ public function downloads(Request $request, Organization $organization): JsonRes
* requirements={"domain"="%domain%","package"="%package_name_pattern%","sep1"="%organization_separator%","sep2"="%domain_separator%"})
* @Cache(public=false)
*/
public function providerV2(Request $request, Organization $organization, string $package): JsonResponse
public function providerV2(Request $request, Organization $organization, string $package): Response
{
[$lastModified, $providerData] = $this->packageManager->findProviders(
[$lastModified, $loader] = $this->packageManager->findProviders(
$organization->alias(),
[new PackageName('', $package)]
);

if ($providerData === []) {
if ($lastModified === null) {
throw new NotFoundHttpException();
}

$response = (new JsonResponse($providerData))
$response = (new StreamedResponse(function () use ($loader): void {
$outputStream = \fopen('php://output', 'wb');
if (false === $outputStream) {
throw new HttpException(500, 'Could not open output stream to send binary file.'); // @codeCoverageIgnore
}

\fwrite($outputStream, ' ');
\flush();
\fwrite($outputStream, \json_encode($loader(), JsonResponse::DEFAULT_ENCODING_OPTIONS));
}, Response::HTTP_OK, ['Content-Type' => 'application/json', 'X-Accel-Buffering' => 'no']))
->setLastModified($lastModified)
->setPrivate();

Expand Down
21 changes: 14 additions & 7 deletions src/Service/Organization/PackageManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ public function __construct(Storage $distStorage, FilesystemInterface $repoFiles
/**
* @param PackageName[] $packages
*
* @return array{\DateTimeImmutable|null, mixed[]}
* @return array{\DateTimeImmutable|null, callable(): mixed[]}
*/
public function findProviders(string $organizationAlias, array $packages): array
{
$data = [];
$lastModified = null;
$filepaths = [];

foreach ($packages as $package) {
$filepath = $this->filepath($organizationAlias, $package->name());
Expand All @@ -47,15 +47,22 @@ public function findProviders(string $organizationAlias, array $packages): array
$lastModified = $fileModifyDate;
}

$json = \unserialize(
(string) $this->repoFilesystem->read($filepath), ['allowed_classes' => false]
);
$data[] = $json['packages'] ?? [];
$filepaths[] = $filepath;
}

$loader = function () use ($filepaths): array {
$data = [];
foreach ($filepaths as $filepath) {
$json = \unserialize((string) $this->repoFilesystem->read($filepath), ['allowed_classes' => false]);
$data[] = $json['packages'] ?? [];
}

return \array_merge(...$data);
};

return [
$lastModified,
\array_merge(...$data),
$loader,
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,12 @@ private function findDistribution(Package $package): string
$normalizedVersion = $latestReleasedVersion === 'no stable release' ?
'9999999-dev' : $this->versionParser->normalize((string) $latestReleasedVersion);

[, $providerData] = $this->packageManager->findProviders(
[, $loader] = $this->packageManager->findProviders(
$package->organizationAlias(),
[new PackageName($package->id()->toString(), (string) $package->name())]
);

$providerData = $loader();
foreach ($providerData[$packageName] ?? [] as $packageData) {
$packageVersion = $packageData['version_normalized']
??
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/Service/Organization/PackageManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function testFindProvidersForPackage(): void
'reference' => 'ac7dcaf888af2324cd14200769362129c8dd8550',
],
'version_normalized' => '1.2.3.0',
]]], $providers);
]]], $providers());
}

public function testReturnDistributionFilenameWhenExist(): void
Expand Down

0 comments on commit 4a3f401

Please sign in to comment.