@@ -42,6 +42,8 @@ public function __construct(
4242 private readonly PackageDistributionResolver $ distributionResolver ,
4343 private readonly PackageProviderManager $ providerManager ,
4444 private readonly MessageBusInterface $ messenger ,
45+ #[Autowire(param: 'dirigent.distributions.async_api_requests ' )]
46+ private readonly bool $ asyncApiRequests ,
4547 #[Autowire(param: 'dirigent.packages.dynamic_updates ' )]
4648 private readonly bool $ dynamicUpdatesEnabled ,
4749 #[Autowire(param: 'dirigent.metadata.default_mirror_fetch_strategy ' )]
@@ -64,7 +66,7 @@ public function root(RouterInterface $router): JsonResponse
6466 ];
6567
6668 if ($ this ->getParameter ('dirigent.distributions.mirror ' )) {
67- $ distributionUrlPattern = u ($ router ->getRouteCollection ()->get ('api_package_distribution ' )->getPath ())
69+ $ distributionUrlPattern = u ($ router ->getRouteCollection ()->get ('api_package_distribution_mirror ' )->getPath ())
6870 ->replace ('{package} ' , '%package% ' )
6971 ->replace ('{version} ' , '%version% ' )
7072 ->replace ('{reference} ' , '%reference% ' )
@@ -106,18 +108,19 @@ public function packageMetadata(Request $request): Response
106108 return $ response ;
107109 }
108110
109- #[Route('/dist/{package}/{version}-{reference}.{type} ' ,
111+ #[Route('/dist/{package}/{version}-r{revision}- {reference}.{type} ' ,
110112 name: 'api_package_distribution ' ,
111113 requirements: [
112114 'package ' => MapPackage::PACKAGE_REGEX ,
113115 'version ' => Requirement::CATCH_ALL ,
116+ 'revision ' => Requirement::POSITIVE_INT ,
114117 'reference ' => '[a-z0-9]+ ' ,
115118 'type ' => '(zip) ' ,
116119 ],
117120 methods: ['GET ' ],
118121 )]
119122 #[IsGrantedAccess]
120- public function packageDistribution (Request $ request , string $ reference , string $ type ): Response
123+ public function packageDistribution (Request $ request , int $ revision , string $ reference , string $ type ): Response
121124 {
122125 if (!$ this ->getParameter ('dirigent.distributions.enabled ' )) {
123126 throw $ this ->createNotFoundException ();
@@ -130,11 +133,55 @@ public function packageDistribution(Request $request, string $reference, string
130133 throw $ this ->createNotFoundException ();
131134 }
132135
133- if (null === $ metadata = $ this ->metadataRepository ->findOneByNormalizedNameAndReference ($ package , $ versionName , $ reference )) {
136+ if (null === $ metadata = $ this ->metadataRepository ->findOneByNormalizedNameAndRevision ($ package , $ versionName , $ revision )) {
134137 throw $ this ->createNotFoundException ();
135138 }
136139
137- if (!$ this ->distributionResolver ->resolve ($ metadata , $ type , async: $ this ->getParameter ('dirigent.distributions.async_api_requests ' ))) {
140+ if (!$ this ->distributionResolver ->resolve ($ metadata , $ type , $ this ->asyncApiRequests )) {
141+ throw $ this ->createNotFoundException ();
142+ }
143+
144+ $ path = $ this ->distributionResolver ->path ($ metadata , $ reference );
145+ $ filename = u ("$ packageName- $ versionName-r $ revision- $ reference. $ type " )->replace ('/ ' , '- ' )->toString ();
146+
147+ return $ this ->file ($ path , $ filename );
148+ }
149+
150+ /**
151+ * Fetch mirrored package distributions through the API.
152+ *
153+ * The endpoint to fetch mirrored distributions is separate because when Composer requests a mirror, it doesn't
154+ * know which revision to fetch, so we default to the latest revision with the specified reference.
155+ */
156+ #[Route('/dist-mirror/{package}/{version}-{reference}.{type} ' ,
157+ name: 'api_package_distribution_mirror ' ,
158+ requirements: [
159+ 'package ' => MapPackage::PACKAGE_REGEX ,
160+ 'version ' => Requirement::CATCH_ALL ,
161+ 'reference ' => '[a-z0-9]+ ' ,
162+ 'type ' => '(zip) ' ,
163+ ],
164+ methods: ['GET ' ],
165+ )]
166+ #[IsGrantedAccess]
167+ public function packageDistributionMirror (Request $ request , string $ reference , string $ type ): Response
168+ {
169+ if (!$ this ->getParameter ('dirigent.distributions.enabled ' )) {
170+ throw $ this ->createNotFoundException ();
171+ }
172+
173+ $ packageName = $ request ->attributes ->get ('package ' );
174+ $ versionName = $ request ->attributes ->get ('version ' );
175+
176+ if (null === $ package = $ this ->findPackage ($ packageName )) {
177+ throw $ this ->createNotFoundException ();
178+ }
179+
180+ if (null === $ metadata = $ this ->metadataRepository ->findOneByNormalizedNameAndDistributionReference ($ package , $ versionName , $ reference )) {
181+ throw $ this ->createNotFoundException ();
182+ }
183+
184+ if (!$ this ->distributionResolver ->resolve ($ metadata , $ type , $ this ->asyncApiRequests )) {
138185 throw $ this ->createNotFoundException ();
139186 }
140187
0 commit comments