Problem/Motivation

Follow-up from #2793233: [FEATURE] Respect the provided maximum page[limit] value

Currently amount of items per page is capped by 50 items. There is a good reason behind this decisionl (see parent issue), however certain cases still require this value to be changed. Since JSON API is zero configuration module, the best place to implement the configuration is JSON API Extras.

Proposed resolution

Provide configuration which allows backend developers to easily configure max value of page[limit] per entity per bundle.

Comments

Spleshka created an issue. See original summary.

spleshka’s picture

Assigned: Unassigned » spleshka

Assigning to myself

spleshka’s picture

Title: Max max value of page[limit] configurable per entity/bundle » Make max value of page[limit] configurable per entity/bundle
e0ipso’s picture

Priority: Normal » Minor

Lowering priority on this.

spleshka’s picture

Assigned: spleshka » Unassigned

Still hoping to resolve this issue, but unassigning myself, because I couldn't find time for this within the last 1.5 months. Let's open this issue for other contributors and see if someone can beat me :)

e0ipso’s picture

Status: Active » Closed (outdated)

I'm closing this as part of issue queue cleanup. Please reopen if necessary.

moshe weitzman’s picture

Status: Closed (outdated) » Active

Its needed on a project of mine (mass.gov())

e0ipso’s picture

Thanks for picking this one up Moshe.

moshe weitzman’s picture

Status: Active » Needs review

I made a new module - https://www.drupal.org/project/jsonapi_page_limit. If folks prefer this functionality in Extras thats fine with me.

s_leu’s picture

I created a patch the moves the functionality moshe implemented in https://www.drupal.org/project/jsonapi_page_limit into this module, as jsonapi_page_limit doesn't work when jsonapi_extras is available. Also having this configurable on the UI via a textfield makes this configuration easier.

Happy to improve the patch if there's anything to improve.

s_leu’s picture

StatusFileSize
new1.13 KB
s_leu’s picture

Forgot a closing tag and improved the field description slightly. Couldn't use the "upload" button here in the form, thus loading up the patch for #11 in a separate post, the interdiff is in comment #11.

s_leu’s picture

Another typo in the field description...

luksak’s picture

Status: Needs review » Needs work

Setting a limit for a bundle broke pagination for me. Right now I dont know what is going wrong, but i assume that it always outputs a next page link without an appropriate offset and therefore has infinite pages :)

s_leu’s picture

Version: 8.x-1.x-dev » 8.x-3.x-dev
Status: Needs work » Needs review
StatusFileSize
new8.63 KB
new6.52 KB

Thanks for checking the patch. I've fixed the issue with pagination and added a test for it as well. Here's the new patch

bbrala’s picture

Status: Needs review » Needs work

Thanks for taking the time to get this working :)

I found some time to test this and found some issues that need to be resolved.

  1. +++ b/modules/jsonapi_defaults/jsonapi_defaults.module
    @@ -70,6 +71,17 @@ function _jsonapi_defaults_form_alter(array &$form, FormStateInterface $form_sta
    +  $form['bundle_wrapper']['fields_wrapper']['defaults']['page_limit'] = [
    +    '#type' => 'textfield',
    +    '#title' => 'Page limit',
    +    '#default_value' => $config_resource->getThirdPartySetting(
    +      'jsonapi_defaults',
    +      'page_limit'
    +    ) ?: OffsetPage::SIZE_MAX,
    +    '#description' => t('Enter the limit of records fetched per page. <strong>Please note that changing this can have an impact on performance and does have security implications.</strong><br />
    +      Read more in the JSON:API documentation at <a href="https://www.drupal.org/docs/8/core/modules/jsonapi-module/pagination#s--cant-i-set-a-page-limit-higher-than-50" target="_blank">drupal.org</a> and consider using the <a href="https://www.drupal.org/project/jsonapi_boost" target="_blank">JSON:API Boost module</a> for better performance.'),
    +  ];
    +
    

    We can set the limit to a lower value than the jsonapi module. This will break things, since it will then limit the results on all pages EXCEPT the first one.

  2. +++ b/modules/jsonapi_defaults/src/Controller/EntityResource.php
    @@ -62,7 +63,17 @@ class EntityResource extends JsonApiEntityResourse {
    +      $page_params = $request->query->get('page');
    +      $offset = array_key_exists(OffsetPage::OFFSET_KEY, $page_params) ? (int) $page_params[OffsetPage::OFFSET_KEY] : OffsetPage::DEFAULT_OFFSET;
    +      $params[OffsetPage::KEY_NAME] = new OffsetPage(
    +        $offset,
    +        $this->getPageLimit($page_params, $resource_config)
    +      );
    

    I would probably make this an method.

  3. +++ b/modules/jsonapi_defaults/tests/src/Functional/JsonApiDefaultsFunctionalTest.php
    @@ -13,6 +14,11 @@ use Drupal\Tests\jsonapi_extras\Functional\JsonApiExtrasFunctionalTestBase;
    +  const PAGE_LIMIT_OVERRIDE_VALUE = 100;
    

    Doesn't this mean we now only test with an higher limit? If so, rather we not do that.

  4. +++ b/modules/jsonapi_defaults/tests/src/Functional/JsonApiDefaultsFunctionalTest.php
    @@ -64,6 +70,49 @@ class JsonApiDefaultsFunctionalTest extends JsonApiExtrasFunctionalTestBase {
    +    // 4. Check page limit override.
    +    /** @var JsonapiResourceConfig $resource_config */
    +    $resource_config = JsonapiResourceConfig::load('node--article');
    +    $resource_config->setThirdPartySetting('jsonapi_defaults', 'default_filter', []);
    +    $resource_config->save();
    +    $this->createDefaultContent(300, 1, FALSE, TRUE, static::IS_NOT_MULTILINGUAL);
    +    $response = $this->drupalGet('/api/articles', [
    +      'query' => ['page[limit]' => static::PAGE_LIMIT_OVERRIDE_VALUE],
    +    ]);
    +    $parsed_response = Json::decode($response);
    +    $this->assertArrayHasKey('data', $parsed_response);
    +    $this->assertCount(static::PAGE_LIMIT_OVERRIDE_VALUE, $parsed_response['data']);
    +    $first_node_uuid = $parsed_response['data'][0]['attributes']['internalId'];
    +    $this->assertArrayHasKey('links', $parsed_response);
    +    $this->assertArrayHasKey('next', $parsed_response['links']);
    +    $this->assertArrayNotHasKey('prev', $parsed_response['links']);
    +    $this->assertPagerLink($parsed_response['links']['next']['href'], 1);
    +    $response = $this->drupalGet($parsed_response['links']['next']['href']);
    +    $parsed_response = Json::decode($response);
    +    $this->assertCount(static::PAGE_LIMIT_OVERRIDE_VALUE, $parsed_response['data']);
    +    $this->assertNotEqual($first_node_uuid, $parsed_response['data'][0]['attributes']['internalId']);
    +    $this->assertArrayHasKey('next', $parsed_response['links']);
    +    $this->assertArrayHasKey('prev', $parsed_response['links']);
    +    $this->assertPagerLink($parsed_response['links']['next']['href'], 2);
    +    $this->assertPagerLink($parsed_response['links']['prev']['href'], 0);
    

    Should this also test setting the limit to something higter than the limit and check if that doesn't work?

s_leu’s picture

Status: Needs work » Needs review
StatusFileSize
new11.09 KB
new10.9 KB

Thanks for the review @bbrala. Made the suggested improvements, here's the new patch.

bbrala’s picture

Status: Needs review » Fixed

Thanks! Tested and seems like it is good to go :)

  • bbrala committed 854ad1e on 8.x-3.x authored by s_leu
    Issue #2884292 by s_leu, Spleshka, e0ipso, moshe weitzman, bbrala, Lukas...

Status: Fixed » Closed (fixed)

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

gowda_mohan’s picture

Can anyone please let me know how to patch the submodules jsonapi_extras/jsonapi_defaults? I tried the following to no avail:
"extra": {
"patches": {
"drupal/jsonapi_extras" : {
"Configurable JSON:API Max Limit": "https://www.drupal.org/files/issues/2020-08-09/max-page-limit-configurab..."
}
},

Output:
$ composer update
Gathering patches for root package.
Loading composer repositories with package information
Updating dependencies
Nothing to modify in lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove

bbrala’s picture

Latest version has this feature merged, are you running the latest version?

drupalninja99’s picture

So I installed the module and configured 1000 max for all my overridden resources. I am still seeing that on all the JSON requests they are not using the overridden value but are instead using the default "50" limit. I have poked around but I need a line of code to zoom in on to see where the "overridden" value is being lost in the handoffs from one method to another.

dishabhadra’s picture

I installed the latest version of the module and set the page limit configuration in the overridden resources. All the JSON requests using the default limit of "50", page limit configuration not working as expected.

I debugged the code and fixed the issue. Created the patch for the same.

I covered the below scenarios,

  • If page[limit] set in the page request as a parameter then use that limit.
  • If no parameter set in the request and page limit set in the configuration for each entity use that as a limit.
  • If nothing is set then use default one "50".
  • .

Please review my patch.

jithenderc’s picture

@dishabadra Hi, I am trying to apply your patch on the drupal core but getting exceptions while doing it. I am using drupal core 8.

bbrala’s picture

Status: Closed (fixed) » Active

Ok this seems to need some work then... reopening.

theruslan’s picture

@dishabhadra thanks for your work!
But patch from #24 doesn't work on Drupal 9.3.9 / PHP 7.4.28 (UPD: and on PHP 8.1.3)

mogio_hh’s picture

I can confirm, that page[limit] cannot be set via the module.

Is the field in the jsonapi defaults module just buggy or was this never implemented correctly?

mogio_hh’s picture

I can confirm, that page[limit] cannot be set via the module.

Is the field in the jsonapi defaults module just buggy or was this never implemented correctly?

admin: Please remove the double post. thanks

dan_rogers’s picture

For anyone looking and/or confused, this is in the "JSON API Defaults" submodule. It must be enabled in order to be set via the UI.

Even then, it is set per endpoint, in the "Resource Ovverides" tab, in the "Collection" fieldset > Page limit.

Even after set, I had to manually specify my limit in the actual call as well, ie `&page%5Blimit%5D=200`.

Hope this helps someone.

danishkshah’s picture

I can confirm the Patch #24 is not working. I have enabled "JSON API Defaults" submodule. Overwritten the resource by setting the page limit. Even after manually specifying the limit above the set page limit. It is still returning 50 records only.

pingwin4eg’s picture

Note that the jsonapi_defaults conflicts with the next_jsonapi module. Both try to alter the jsonapi.entity_resource controller/service.

In my case next_jsonapi's controller works and jsonapi_defaults' doesn't, this in turn doesn't enable the page limit change from the module.

mayurngondhkar’s picture

Reroll patch

bbrala’s picture

Can you please also attach an interdiff? You can read how here: creating-an-interdiff

rishabh vishwakarma’s picture

Added a patch for Drupal 9

jaykainthola’s picture

I have tested patch #35 and it's working fine. Now, its taking configuration of resource for page limit.