diff --git a/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php b/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php index bf4e056ad5..5b1bc2a12d 100644 --- a/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php +++ b/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php @@ -229,12 +229,7 @@ public function post(Request $request, $entity_type_id, $bundle, $field_name) { // 201 Created responses return the newly created entity in the response // body. These responses are not cacheable, so we add no cacheability // metadata here. - $headers = [ - // @todo Do we want the File URI (for the actual file) like this? - 'Location' => $file->url(), - ]; - - return new ModifiedResourceResponse($file, 201, $headers); + return new ModifiedResourceResponse($file, 201); } /** @@ -347,9 +342,13 @@ protected function validateAndLoadFieldDefinition($entity_type_id, $bundle, $fie throw new BadRequestHttpException(sprintf('Field "%s" does not exist', $field_name)); } - // @todo check the definition is a file field. + /** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */ $field_definition = $field_definitions[$field_name]; + if ($field_definition->getSetting('target_type') !== 'file') { + throw new AccessDeniedHttpException(sprintf('"%s" is not a file field', $field_name)); + } + if (!$this->entityTypeManager->getAccessControlHandler($entity_type_id)->fieldAccess('create', $field_definition)) { throw new AccessDeniedHttpException(sprintf('Access denied for field "%s"', $field_name)); } diff --git a/core/modules/hal/tests/src/Functional/EntityResource/File/FileUploadHalJsonTestBase.php b/core/modules/hal/tests/src/Functional/EntityResource/File/FileUploadHalJsonTestBase.php index fadbc0515c..a1aa294dc2 100644 --- a/core/modules/hal/tests/src/Functional/EntityResource/File/FileUploadHalJsonTestBase.php +++ b/core/modules/hal/tests/src/Functional/EntityResource/File/FileUploadHalJsonTestBase.php @@ -41,7 +41,8 @@ protected function getExpectedNormalizedEntity($fid = 1, $expected_filename = 'e return $normalization + [ '_links' => [ 'self' => [ - 'href' => $normalization['uri'][0]['value'], + // This link is generated from File::url(). + 'href' => file_create_url($normalization['uri'][0]['value']), ], 'type' => [ 'href' => $this->baseUrl . '/rest/type/file/file', diff --git a/core/modules/rest/src/EventSubscriber/ResourceResponseSubscriber.php b/core/modules/rest/src/EventSubscriber/ResourceResponseSubscriber.php index 93736702b3..9fbf3858f8 100644 --- a/core/modules/rest/src/EventSubscriber/ResourceResponseSubscriber.php +++ b/core/modules/rest/src/EventSubscriber/ResourceResponseSubscriber.php @@ -104,33 +104,32 @@ public function onResponse(FilterResponseEvent $event) { */ public function getResponseFormat(RouteMatchInterface $route_match, Request $request) { $route = $route_match->getRouteObject(); - $acceptable_request_formats = $route->hasRequirement('_format') ? explode('|', $route->getRequirement('_format')) : []; - $acceptable_content_type_formats = $route->hasRequirement('_content_type_format') ? explode('|', $route->getRequirement('_content_type_format')) : []; - $acceptable_formats = $request->isMethodCacheable() ? $acceptable_request_formats : $acceptable_content_type_formats; + $acceptable_response_formats = $route->hasRequirement('_format') ? explode('|', $route->getRequirement('_format')) : []; + $acceptable_request_formats = $route->hasRequirement('_content_type_format') ? explode('|', $route->getRequirement('_content_type_format')) : []; + $acceptable_formats = $request->isMethodCacheable() ? $acceptable_response_formats : $acceptable_request_formats; $requested_format = $request->getRequestFormat(); $content_type_format = $request->getContentType(); - // If an acceptable format is requested, then use that. Otherwise, including - // and particularly when the client forgot to specify a format, then use - // heuristics to select the format that is most likely expected. - if (in_array($requested_format, $acceptable_request_formats)) { + // If an acceptable response format is requested, then use that. Otherwise, + // including and particularly when the client forgot to specify a response + // format, then use heuristics to select the format that is most likely + // expected. + if (in_array($requested_format, $acceptable_response_formats, TRUE)) { return $requested_format; } - // If a request body is present, then use the format corresponding to the - // request body's Content-Type for the response, if it's an acceptable - // format for the request. - elseif (!empty($request->getContent()) && in_array($content_type_format, $acceptable_content_type_formats)) { + + if (!empty($request->getContent()) && in_array($content_type_format, $acceptable_request_formats, TRUE)) { return $content_type_format; } + // Otherwise, use the first acceptable format. - elseif (!empty($acceptable_formats)) { + if (!empty($acceptable_formats)) { return $acceptable_formats[0]; } + // Sometimes, there are no acceptable formats, e.g. DELETE routes. - else { - return NULL; - } + return NULL; } /** diff --git a/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php b/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php index a3f7d9effa..a259792a79 100644 --- a/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php @@ -133,10 +133,13 @@ public function testPostFileUpload() { $this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']); - $this->setUpAuthorization('POST'); - $uri = Url::fromUri('base:' . static::$postUri); + $response = $this->fileRequest($uri, $this->testFileData); + $this->assertResourceErrorResponse(403, $this->getExpectedUnauthorizedAccessMessage('POST'), $response); + + $this->setUpAuthorization('POST'); + // This request will have the default 'application/octet-stream' content // type header. $response = $this->fileRequest($uri, $this->testFileData); @@ -424,14 +427,16 @@ public function testFileUploadMaliciousExtension() { * {@inheritdoc} */ protected function assertNormalizationEdgeCases($method, Url $url, array $request_options) { - // TODO: Implement assertNormalizationEdgeCases() method. + // The file upload resource only accepts binary data, so there are no + // normalization edge cases to test, as there are no normalized entity + // representations incoming. } /** * {@inheritdoc} */ protected function getExpectedUnauthorizedAccessMessage($method) { - // TODO: Implement getExpectedUnauthorizedAccessMessage() method. + return sprintf('You are not authorized to create this file entity'); } /**