Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance the vocabularies serializer to accept a list of tokens #1295

Merged
merged 5 commits into from
Dec 21, 2021

Conversation

sneridagh
Copy link
Member

@sneridagh sneridagh commented Dec 18, 2021

We will need this next week.

@mister-roboto
Copy link

@sneridagh thanks for creating this Pull Request and help improve Plone!

To ensure that these changes do not break other parts of Plone, the Plone test suite matrix needs to pass.

Whenever you feel that the pull request is ready to be tested, either start all jenkins jobs pull requests by yourself, or simply add a comment in this pull request stating:

@jenkins-plone-org please run jobs

With this simple comment all the jobs will be started automatically.

Happy hacking!

@tiberiuichim
Copy link
Contributor

May I suggest tokens instead of token_list as parameter? Also, I think we'd need to have a POST service here: https://github.com/plone/plone.restapi/blob/master/src/plone/restapi/services/vocabularies/configure.zcml

@sneridagh
Copy link
Member Author

I test drive it, and it needs adjustments. Do not merge yet.

@tiberiuichim Better not POST for caching, right? Also token and tokens, wouldn't it be far too similar and error prone?

@sneridagh
Copy link
Member Author

@jenkins-plone-org please run jobs

@tisto
Copy link
Member

tisto commented Dec 18, 2021

We should make a decision regarding tokens vs token_list and add it to our naming convention:

https://github.com/plone/plone.restapi/blob/master/docs/source/conventions.rst

I will do some research...

@sneridagh
Copy link
Member Author

@jenkins-plone-org please run jobs

@sneridagh
Copy link
Member Author

@tisto @tiberiuichim ready. Used tokens as parameter. Sticked to the GET request for caching purposes.

Copy link
Contributor

@tiberiuichim tiberiuichim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand, we're not gonna be able to have tokens with commas in them, right? I don't know how common this use case is.

@sneridagh
Copy link
Member Author

@tiberiuichim you have a point, ideally not... but who knows... could be a vector of bugs.

The whole "let's decide how we encode lists in parameters" story is also important, I just used what we already have in there.

@ksuess
Copy link
Member

ksuess commented Dec 20, 2021

Same topic, how to handle list parameters, in search endpoint.
? Is it a default for a JSON API to handle commas as list separators?
search endpoint gets
@@search?metadata_fields:list=subject,modified&portal_type:list=News Item,Event
then searches for
query {'metadata_fields': ['subject,modified'], 'portal_type': ['News Item,Event']}
which returns an empty result.

@tiberiuichim
Copy link
Contributor

that list argument conversion is not correct. https://zope.readthedocs.io/en/latest/zdgbook/ObjectPublishing.html#argument-conversion.

list – collect all values with this name into a list.

It should be @search?metadata_fields:list=subject&metadata_fields:list=modified

@sneridagh
Copy link
Member Author

@ksuess in the search endpoint we are constrained by how Zope Querystring parser search parameters are encoded so the action is taking already care of passing Zope the right way (see the action code) in jsx, when you call the action, just pass a JS array in the action.

@sneridagh
Copy link
Member Author

hehe, @tiberiuichim was faster than me :)

@tisto
Copy link
Member

tisto commented Dec 20, 2021

This PR raises a number of REST API design principles questions:

  1. Do we want to use multiple parameters dependent on if we pass a single parameter (e.g. "token=foo") or a list of parameters (e.g. "tokens=foo,bar"). Some APIs use a single parameter, no matter if you pass a single parameter or multiple parameters (e.g. "token=foo" and "token=foo,bar"). I think I personally prefer to use a param that accepts both a single term and a list.
  2. Do we want to include the type of the passed param into our param name (token vs token_list). I'd be ok with the plural solution that we currently have in this PR. Including the type might be a slippery slope.
  3. URL encoding lists. There are a bazillion ways of handling this. You can just urlencode stuff (like "foo,bar" -> "foo%82bar"). You can pass a parameter multiple times (e.g. token=foo&token=bar). You can encode stuff like "[foo,bar]", ...

I started to dip my toe into urlencoding arrays and nested structures for the querysting-search endpoint (#1252 (comment)) and I have to admit it is just a horrible mess and there is no standard whatsoever as far as I can see.

@tiberiuichim
Copy link
Contributor

@tisto There's also the option of using Zope's argument parsing, with tokens:list=foo&tokens:list=bar

@ale-rt
Copy link
Member

ale-rt commented Dec 20, 2021

My 2 c., do what we are used to do!

Either use:

  • tokens=foo&tokens=bar
    or:
  • tokens:list=foo&tokens:list=bar
    if you want to be explicit.

Notes:

  1. while there is no difference when the parameter appears once in the query string, id does make a difference when it is present just once, i.e. token=foo will be give you a self.request.form equal to {"token": "foo"}, while token:list=foo will give you a self.request.form equal to {"token": ["foo"]} (notice the list).
  2. If you opt for tokens=foo,bar you must protect your code from people passing the parameter multiple times, i.e.: tokens=foo,bar&tokens=baz.
  3. Just a curiosity, query string can be exploited and Zope does a great job in preventing that. There is tons of stuff to read, start from https://en.wikipedia.org/wiki/HTTP_parameter_pollution. IIRC also facebook was found vulnerable to this attack (PHP...)

@jensens
Copy link
Member

jensens commented Dec 21, 2021

I agree with @ale-rt - and I tend to not reinvent the wheel and use Zope list query parameter syntax.

@sverbois
Copy link

just my 2c

When I design REST API I always use a plural noun when the API client can provide mutliple values. It is more predictive for the user.
Here I would use:
tokens:list=foofor the singleton list tokens=['foo']
tokens:list=foo&tokens:list=bar for a multi-valued list tokens=['foo','bar']

@sneridagh
Copy link
Member Author

@jenkins-plone-org please run jobs

@sneridagh
Copy link
Member Author

@ale-rt @jensens refactored to use multi valued, as in Zope. I will merge if all is good from you!

@sneridagh sneridagh requested a review from ericof December 21, 2021 14:12
@ale-rt
Copy link
Member

ale-rt commented Dec 21, 2021

Mine was just a suggestion :)
I am good with this PR.
I would wait for the reviews of @tisto and @ericof ;)

@sneridagh
Copy link
Member Author

@ale-rt a good one! Thanks for weigh in! We already talked about it in today's Volto Team meeting and agreed to go this way.

Copy link
Member

@tisto tisto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am good with this PR. ToDo:

  • Add the multiple params approach to API design best practices
  • Add test and docs to show that you can pass a single param with "tokens" as well
  • Deprecate "token" for the future
  • Refactor usage of other approaches (e.g. "," in expendables) to support the new "standard", deprecate the old way for the next major release

@tisto tisto merged commit 6a9310f into master Dec 21, 2021
@tisto tisto deleted the vocabserializeracceptlistoftokens branch December 21, 2021 14:43
@ale-rt
Copy link
Member

ale-rt commented Dec 21, 2021

Given that you are into json you might also be interested in making this happen: zopefoundation/Zope#957

sneridagh added a commit that referenced this pull request Jan 16, 2022
…kforp6

* origin/master: (140 commits)
  Back to development: 8.18.2
  Preparing release 8.18.1
  Add deprecation msg in docs for tiles endpoint (#1234)
  Mark 1307 as internal
  Add internal towncrier classifier
  Be permissive when testing the schema of the querystring endpoint (#1306)
  Back to development: 8.18.1
  Preparing release 8.18.0
  test(leak): Fix unclosed socket leaks
  test(deprecation): Fix some warnings from our code
  Expandable params as list and deprecations for list as comma separated (#1301)
  Improve vocabulary endpoint when asking for a list of tokens adding resilience and deprecation warning (#1299)
  Do not break if publish recursive folder children that are already published (#1291)
  Back to development: 8.17.1
  Preparing release 8.17.0
  Enhance the vocabularies serializer to accept a list of tokens (#1295)
  Fix typo.
  Refactor text extraction
  Add a line break between blocks
  Move logic of _extract_text function inside the DraftJS indexer
  ...
@sneridagh sneridagh linked an issue Jan 17, 2022 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enhance the vocabularies serializer to accept a list of tokens
8 participants