Steps to Reproduce

  1. Install the current stable version of Drupal (8.1.x)
  2. Create a custom rest resource (example code here)
  3. Send a GET request to your new rest resource
  4. See that the request succeeds
  5. Upgrade to Drupal 8.2.x
  6. Send another GET request to your rest resource
  7. See that the request fails with 404 and the error message:
    {
      "message": "No route found for \"GET /todo/\""
    }

Expected result

That custom rest resources would continue to work after upgrading to Drupal 8.2.x

Actual result

Custom REST resource now responds with a 404 and the error message:

{
  "message": "No route found for \"GET /todo/\""
}

Video demonstration

https://www.youtube.com/watch?v=mdR8peJIu_A

Notes

I verified this experimentally with 8.2.0-beta2 and 8.2.0-dev on September 20, 12:30pm EDT. I suspect it is related to #2308745: Remove rest.settings.yml, use rest_resource config entities.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

MKorostoff created an issue. See original summary.

mikeryan’s picture

I'm also having this problem, in a fresh 8.2.x install (no upgrade from 8.1.x), with http://cgit.drupalcode.org/migrate_plus/tree/migrate_example_advanced/mi...

Error message: Client error: `GET http://d82.dd:8083/migrate_example_advanced_position?_format=json` resulted in a `404 Not Found` response:
{"message":"No route found for \u0022GET \/migrate_example_advanced_position\u0022"}
 at http://d82.dd:8083/migrate_example_advanced_position?_format=json.

I've also enabled the /dblog/{id} endpoint through restui, and can't get that to work either.

cilefen’s picture

Title: Custom REST resource no longer accessible after upgrading to Drupal 8.2.x » [regression] Custom REST resource no longer accessible after upgrading to Drupal 8.2.x

The video shows you had an EntityStorageException that you didn't mention in the issue summary. Could you add that please? @mikeryan: Same or similar exception?

cilefen’s picture

@mikeryan: Oh you didn't upgrade.

MKorostoff’s picture

FileSize
2.33 KB

@cilefen sure, sorry, I meant to include this with the original post. It's attached.

I'm reasonably confident that the terminal error is due to the fact that this was my second or third upgrade attempt. I upgraded once, and after I noticed my resource wasn't responding, I downgraded so as to capture the issue on video. The rest module attempts to create a config entity called rest_resource_config.entity.node. Because I had already run the upgrade once, the entity already existed, hence the error. This is all to say, I don't believe the error in my terminal is related to the issue discussed in this thread, but I could be wrong.

cilefen’s picture

Issue summary: View changes

That and the fact that #2 wasn't an upgrade...

Wim Leers’s picture

Because I had already run the upgrade once, the entity already existed, hence the error. T

How can you run the update again? Drupal prevents update functions (to migrate data from one version to the next) to be run multiple times, precisely for this reason.

Wim Leers’s picture

Are you seeing this error?

#2308745-253: Remove rest.settings.yml, use rest_resource config entities:

I tried the update path from 8.1.3 to 8.2.x via drush. I got the Failed: The "rest_resource_config" entity type does not exist. on the first try. I think we have to rebuild the entity type registry? The update worked flawless on the second drush updb. I did not call drush cr before the first drush updb. Worth a follow-up?

Which was reported again at #2721595-61: Simplify REST configuration:

rest module

Update #8201

Failed: Drupal\Component\Plugin\Exception\PluginNotFoundException: The “rest_resource_config” entity type does not exist. in Drupal\Core\Entity\EntityTypeManager->getDefinition() (line 125 of /Users/george.cassie/Sites/devdesktop/drupal-8.1.6/core/lib/Drupal/Core/Entity/EntityTypeManager.php).

(We forgot to open a follow-up for that.)

It'd be great if you could try to reproduce this. If so, this will become a critical issue, and one that will have to be fixed before 8.2.0 is released.

Wim Leers’s picture

Oh wait, #2 is indeed not an update. So that can't be the cause.

#2: After deploying the config, did you rebuild your routes?

Berdir’s picture

This happens when you have warm caches when running the update, I just reproduced this when updating to 8.2.0-rc1, I don't think something changes since then.

An explicit call to clearCachedDefinitions() on the entity type manager should fix this before calling getDefinition() should fix this.

Wim Leers’s picture

Priority: Major » Critical
Wim Leers’s picture

Title: [regression] Custom REST resource no longer accessible after upgrading to Drupal 8.2.x » [regression] rest_update_8201() can fail and break things
Status: Active » Needs review
FileSize
1.47 KB

Berdir at #10:

An explicit call to clearCachedDefinitions() on the entity type manager should fix this before calling getDefinition() should fix this.

dawehner at #2308745-254: Remove rest.settings.yml, use rest_resource config entities:

+  \Drupal::entityDefinitionUpdateManager()->installEntityType(\Drupal::entityTypeManager()->getDefinition('rest_resource_config'));

This line is the problematic line. Conceptually we should NOT get the definition from the entity type manager, but rather hardcode the definition in the update function which was available at the point in time we wrote the code.
So we better fix the update function I guess. Practically it doesn't matter than much because this is a config entity anyway, which doesn't deal with all that.

Both achieve the same result, but the latter seems the correct one to me. If the rest_resource_config entity type definition changes at a later time, then this particular update function will install the definition as it is at that later time, rather than at the time of this particular update function. Which means subsequent update functions will try to update it to the then-newer version, but it'll already be at that version.

Therefore, I'm going to go with @dawehner's proposal.

P.S.: alexpott raised this very concern at #2308745-245: Remove rest.settings.yml, use rest_resource config entities, but dawehner felt there was no harm because it's just a "create" operation, and I agreed. We were wrong.


This patch takes the config entity type definition in the annotation:

/**
 * Defines a RestResourceConfig configuration entity class.
 *
 * @ConfigEntityType(
 *   id = "rest_resource_config",
 *   label = @Translation("REST resource configuration"),
 *   config_prefix = "resource",
 *   admin_permission = "administer rest resources",
 *   label_callback = "getLabelFromPlugin",
 *   entity_keys = {
 *     "id" = "id"
 *   },
 *   config_export = {
 *     "id",
 *     "plugin_id",
 *     "granularity",
 *     "configuration"
 *   }
 * )
 */
class RestResourceConfig extends ConfigEntityBase implements RestResourceConfigInterface {

… and maps that to a corresponding new ConfigEntityType([…]) instantiation, so that it no longer relies on the entity type manager. Which means no more caches to be cleared (as Berdir says), nor any chance of using not the appropriate version of that definition (as dawehner says).

Berdir’s picture

Status: Needs review » Reviewed & tested by the community

Works for me. This is pretty much a no-op anyway for config entity. entityDefinitionUpdateManager() doesn't care about them and doesn't do anything for them, but complains if they don't exist.

dawehner’s picture

WFM +1

  • catch committed fabc088 on 8.3.x
    Issue #2803179 by Wim Leers, MKorostoff, Berdir, dawehner: [regression]...

  • catch committed f4078d7 on 8.2.x
    Issue #2803179 by Wim Leers, MKorostoff, Berdir, dawehner: [regression]...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Theoretically we could have update tests for this, but it'd be a lot of work compared to what is equivalent to "use the literal schema definition instead of hook_schema()". So opened #2803865: Additional test coverage for rest_update_8201() as a follow-up and committed to 8.3.x and 8.2.x, thanks!

MKorostoff’s picture

Status: Fixed » Needs work
FileSize
2.33 KB

Hey guys, after testing the patch in #12 I got the exact same result as the initial ticket description. Here is a recording of my test http://www.youtube.com/watch?v=md8Z55-VxQw

mikeryan’s picture

Heh, Matt got in while I was adding my comment:

I'm still having my non-upgrade-related issue: #2803905: Custom REST resource no longer accessible after upgrading to Drupal 8.2.x .

So, should I close that one while we take it back up here? Seems the update issue was a red herring...

Berdir’s picture

@MKorostoff: That is a different error. It complains that the entity already exists. That means you already did run the updates before, at least partially. that isn't supported. You have to manually delete those configs or you need to restore a db dump from before you started to update.

catch’s picture

Status: Needs work » Fixed

Let's discuss Mike's issue in #2803905: Custom REST resource no longer accessible after upgrading to Drupal 8.2.x , the update change here makes sense in itself.

Wim Leers’s picture

Thanks, Berdir, for responding to #18.

Thanks, catch, for responding to #19.

MKorostoff’s picture

@Berdir, that's the exact same error message—if you compare terminal_output.txt and terminal_output2.txt you'll see that the two messages are identical verbatim. I also offered that same theory (that the update had already run) in #5, but Wim Leers felt that was unlikely in #7.

In any event, after deleting rest.resource.entity.node from the config table, I was able to run the upgrade successfully and my service worked! So thanks all around!

So, to summarize for anyone who finds this thread with a similar issue later, here's what I think happened in my case:

  1. I attempted to upgrade to 8.2.x
  2. The upgrade attempt failed, for reasons I will discuss below.
  3. I downgraded to 8.1.x.
  4. I attempted to upgrade a second time
  5. The upgrade failed again, but for a different reason this time. There was a config entity called "rest.resource.entity.node" which was created by upgrade attempt 1. Upgrade attempt 2 through infinity could not complete, because the name "rest.resource.entity.node" was already taken.
  6. I deleted the record "rest.resource.entity.node" from the config table.
  7. I fixed the problem that caused upgrade attempt 1 to fail (discussed in detail below), and then ran drush updb.
  8. All database updates ran, and my rest resource worked again!

So the question remains: why did upgrade attempt 1 fail? The failure occurred in RestResourceConfig::normalizeRestMethod(). This function is (I think) responsible for migrating validating the HTTP verbs on each rest resource as they are migrated from the rest.settings config entity to the rest.resource.my_custom_resource_id config entity. The problem is that my custom rest resource implemented a PUT method, which is not valid in Drupal rest. What made this particularly sticky is that, even AFTER I removed the PUT method from my class, Drupal continued to "remember" that it had been there previously. I'm really not sure how or why Drupal "remembered" that I used to have a PUT method, because the PUT method was not referenced by the rest.settings config (I also cleared caches about a million times). I never did figure out how to make Drupal "forget" about my invalid PUT method. In the end, I just changed RestResourceConfig::normalizeRestMethod() from this:

protected function normalizeRestMethod($method) {
    $valid_methods = ['GET', 'POST', 'PATCH', 'DELETE'];
    $normalised_method = strtoupper($method);
    if (!in_array($normalised_method, $valid_methods)) {
      throw new \InvalidArgumentException('The method is not supported.');
    }
    return $normalised_method;
  }

To this:

protected function normalizeRestMethod($method) {
    $valid_methods = ['GET', 'POST', 'PATCH', 'DELETE', 'PUT'];
    $normalised_method = strtoupper($method);
    if (!in_array($normalised_method, $valid_methods)) {
      throw new \InvalidArgumentException('The method is not supported.');
    }
    return $normalised_method;
  }

Then ran the upgrades, and then changed the code back. Now everything works. Thanks everyone!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.