-
Notifications
You must be signed in to change notification settings - Fork 912
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
Allow user/preferences/[KEY]
to accept arbitrary keys
#3787
base: master
Are you sure you want to change the base?
Conversation
I wasn't actually expecting us to change the behaviour! I thought you meant you were going to fix the client to not use such silly names... |
Also what is the point of the first commit if the second one reverts it? If you want to offer two alternatives then open two PRs don't lump them together in one PR because then if we merge it we'll add loads of useless noise to the history. |
I was planning on squashing it before it got merged. I'll go ahead and do that now.
While MapRoulette has a primary instance ( It is possible for each service have a static api key (for example, the main MR server could use With all that said, if you are against having arbitrary keys in user preferences, would you accept a PR that validated the PUT /user/preferences endpoint to not have keys that would be invalid for the EDIT: I'll note that this fixes the case of /user/preferences/gps.trace.visibility, where |
This was a two-part problem: 1. Keys with a `.` would have the latter part of the key interpreted as a format. Example: `gps.trace` would have the key set to `gps` and a format set to `trace`. 2. The :preference_key parameter would not be URL decoded. Signed-off-by: Taylor Smock <tsmock@meta.com>
05ebd4f
to
8faa6bb
Compare
I think the underlying problem here is that we are using the keys in our urls, without any validation to ensure that they are url safe. A similar example would be our validation of user display_names, which are validated as url safe, since we use those in urls. validates :user, :associated => true
- validates :k, :v, :length => 1..255, :characters => true
+ validates :k, :length => 1..255, :characters => { :url_safe => true }
+ validates :v, :length => 1..255, :characters => true
end It's a bit surprising that this hasn't come up until now! And it's quite funny to me that the problem is highlighted by the keys that we use internally for gpx visibility and diary default language, both of which use "." characters 😄 Unfortunately I'm not in favour of the proposed solution. We've been trying to move away from plain-text API responses, mostly for consistency reasons between API endpoints but also for developer ergonomics (you don't want to have some responses handled by an xml or json library, but have to handle some responses that aren't). But we have also settled on the convention that you can choose between response formats using extensions e.g. I'm open to further discussion and any suggestions! |
Right now, So a
The point being that the preference value can be anything, and the application developer is going to have to deal with it (unless it is dealt with inside the website code), so I don't think this specific endpoint ( |
I think you've misunderstood my point, since I wasn't talking about encoding json into the values. In fact I wasn't discussing the values of the user preferences at all. The point is that for our other API calls, we have a convention of returning responses in either XML or JSON, and not plain text. Furthermore, for calls that return multiple objects we return a list of objects, and for calls for individual objects we return the individual object, not just the "contents" of the object. Compare for example with nodes:
Note that for an individual node request we return the whole node object, even though you could argue that the id is redundant and there's no need to return the object, you could just return the attributes. Now we compare with preferences:
It seems reasonable (and good for consistency) that asking for a single preference should return a Now at the moment we don't provide a structured responses for individual preference requests, but the reason that I don't like this proposal is that it will prevent us from doing so in future. In particular, we need to be able to return structured error messages, which is a common complaint about parts of our API. We can't return error messages in a structured format without giving the developers the ability to make format-specific requests! I.e. if you want xml structured error messages then you need to be able to make XML formatted requests (e.g. request urls ending in .xml), and so if requests have a format then the non-error responses should be formatted to match. Again, this highlights why we are moving away from plain-text responses and the importance of allowing format-specific request urls. |
In this case, it sounds like the If you want to return a structured message for this specific endpoint, maybe the Issues I can see with having Example: <osm version="0.6" generator="...">
<preferences>
<preference k="gps.trace.visibility" v="private"/>
<preference k="gps.trace.visibility.json" v="identifiable"/>
<preference k="gps.trace.visibility.xml" v="identifiable"/>
<preference k="key.json" v="{\"some\":\"json\"}"/>
<preference k="key" v="{\"some\":\"unexpected json\"}"/>
</preferences>
</osm> Anyway, I'm working on adding support for response formats on that endpoint. Using |
We could instead add an additional optional filter to This should also play nicely with different output formats, e.g. GET /api/0.6/user/preferences.json?key=my.key |
…ed key This does break compatibility if an application requested json/xml in the Accept header and did not actually expect json/xml back. Signed-off-by: Taylor Smock <tsmock@meta.com>
63fee9c
to
8a935a6
Compare
OK. The There might be a better way to detect/change the request format, but the ways I tried didn't work out ( So I think I've addressed @gravitystorm's problems by getting the endpoint to return XML/JSON responses, unless the |
Yeah, I pretty much think it's a hard requirement - or at least (as I said above) not doing anything now that makes it impossible to implement in future. I think it would be bad to have a convention on our API (using format extensions like Two other things spring to mind:
So I iterate back to the situation where we either need to implement the |
Encoding the hash character as %23 should do the job (e.g. |
Signed-off-by: Taylor Smock <tsmock@meta.com>
Supporting I do have a hack to allow for I'm looking into better options, but something, somewhere, is causing issues when I do that. Which I'm trying to fix by stepping through the code. |
Can the dots in the key be url encoded? E.g. |
Technically, yes. Unfortunately, most common URL encoders that people use will not encode
|
…encoded Clients should URL encode '.' manually when their chosen encoder does not. The hex code for '.' is 0x2e, so % encoding would make it %2e (or %2E). Signed-off-by: Taylor Smock <tsmock@meta.com>
I was just reading section 2.3 "Unreserved Characters" and this concerns me:
It then goes on to say:
So that sounds like |
I'm wondering how many preferences, other than the ones in this codebase, use problematic characters from the set |
Honestly, I need to figure out why our code doesn't like multiple I wrote a quick fake site to check and see if it was an upstream bug, and it does not appear to be. So I'm going to have to figure out why our code doesn't like multiple |
This is my understanding too. |
So I think I found a fix for the multiple I still don't know why the |
I don't understand what you are trying to achieve with the "multiple |
2cf8699
to
bb207a9
Compare
The problem is that This is (partially) fallout from supporting
|
Signed-off-by: Taylor Smock <tsmock@meta.com>
But I still don't understand what you are trying to achieve! I thought we'd clarified that we can't use any unescaped If you are trying to support both (optional) format extensions and also dotted-keys in the url, then I believe that's a dead-end. You can't distinguish these two different situations:
Similarly if you consider keys with multiple
I don't want to see a special-case for the User Preferences API along the lines of "please note that if you have a I don't want you to spend more of your time and effort working on debugging something that turns out to be a dead end or not useful, so I recommend that we clarify what you are trying to do before you jump in with more coding. |
Sorry, that might be a misunderstanding due to issuecomment-1318982892. In any case, the current code should handle the case where
I agree. The problem is that it is a "hard" requirement to have the ability to support Using
I did not want to do any special casing at all. My original intent was to support arbitrary keys for the endpoint. Unfortunately, if we do support Current options:
Thank you for the consideration. I've been busy the past week or so fixing JOSM tickets prior to (what I had hoped to be) a release week. |
This was a two-part problem:
.
would have the latter part of the key interpreted asa format. Example:
gps.trace
would have the key set togps
and a format set totrace
.This PR has two commits.The first commit adds a method (fix_request_key
) that takes the request and merges the:preference_key
and:format
parameter keys, and then URL decodes them. This method does not work with keys likegps.trace.visibility
but does work with keys likehttps://some.ones/api
.The second commit uses routes to [do the URL decoding, and it does not have to deal with the key being split at
.
characters into a key and format].My preference would therefore be to use the routes, but on just in case the project doesn't want to have explicit route entries foruser/preferences/:preference_key
, I have kept the commit addingfix_request_key
instead of squashing it.EDIT: The commits have been squashed.