-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[App Search] DRY helper for encoding/decoding routes that can have special characters in params #89811
Conversation
- Primarily document URLs & analytics queries (which uses generateEnginePath)
- Documents titles & Analytics queries
- Feedback from Davey - the pages don't open in a new window, so shouldn't use the popout icon - Not strictly related but since we're touching these links anyway, I'm shoving it in (sorry)
@@ -56,7 +56,7 @@ export const ACTIONS_COLUMN = { | |||
{ defaultMessage: 'View query analytics' } | |||
), | |||
type: 'icon', | |||
icon: 'popout', | |||
icon: 'eye', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change has nothing to do with encoding/decoding, but Davey requested it recently (since the popout icon typically indicates a new tab/window, and that's not the case here) and I figure I'd shove it in this PR since it touches the 2 concerned views 😬 If you super hate that lmk and I can stop being lazy & pull it out to a separate PR haha
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine.........😒
import { EngineLogic } from './'; | ||
|
||
/** | ||
* Generate a path with engineName automatically filled from EngineLogic state | ||
*/ | ||
export const generateEnginePath = (path: string, pathParams: object = {}) => { | ||
const { engineName } = EngineLogic.values; | ||
return generatePath(path, { engineName, ...pathParams }); | ||
return generatePath(path, encodePathParams({ engineName, ...pathParams })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My hope is that by baking this into our new generateEnginePath
helper that it'll "just work" going forward and at the very least we won't accidentally forget to encode user-generated IDs going forward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the problem I see here is that you are actually increasing the odds that someone will accidentally forget to encode user-generate ids, because as soon as you're in a place in the code you're not able to use generateEnginePath
, then you won't be in the habit of encoding path params.
I really wish there was just one way to create paths that we could used everywhere, decoupled from state, that would handle encoding path params.
generateAppPath(ENGINE_DOCUMENT_DETAIL_PATH, {
engineName: resultMeta.engine,
documentId: resultMeta.id,
})
}); | ||
|
||
return decodedParams; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just want to note - on some reflection, it's maybe a little overkill to have a helper for 2 instances in our app, but I think it'll be worth it (from the perspective of future-proofing) that we have one documented and canonical place where we ensure our URLs are correctly encoded, vs. doing it manually and maybe slightly differently in multiple places in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree.
const documentLink = generatePath( | ||
ENGINE_DOCUMENT_DETAIL_PATH, | ||
encodePathParams({ | ||
engineName: resultMeta.engine, | ||
documentId: resultMeta.id, | ||
}) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using the default RR generatePath
, I'm tempted to convert this to
generateEnginePath(ENGINE_DOCUMENT_DETAIL_PATH, {
engineName: resultMeta.engine,
documentId: resultMeta.id,
})
Just so we get the encoding baked in without having to manually call it. I know Jason mentioned earlier that was maybe confusing though 🤷 What do you all think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left another comment about a more generic generateAppPath
that I think applies here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My objection still stands. It's like we're trying to force things through this state based helper that don't make sense to be part of a state based helper.
That being said, it's also inconsequential to me. It will be just fine if you choose to do this. I stated my objection, but either way will be just fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ya I think you're right about that, I shouldn't be conflating the two different helpers. I'm good with a generic generateAppPath
(or maybe generateEncodedPath
if it should be specific to encoding?), will add that helper to this PR and have generateEnginePath
call that helper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this Constance, this will be super helpful. I left optional feedback.
- now handled/tested by useDecodedParams helper
- Should be used in place of generatePath
for consistency across the App Search codebase
@elasticmachine merge upstream |
@elasticmachine merge upstream |
💚 Build SucceededMetrics [docs]Module Count
Async chunks
History
To update your PR or re-run it, just comment with: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is kind of a net zero for me, so I'm not going to block or request further changes, but I want to say it's not the direction I'd have gone. I'm not sure what we gain out of these helpers (or useDecodedParams
) when they're mostly just wrappers around the base JavaScript API. If I manage to remember my path requires encoding (which is already a lot to ask of me tbh), I think the solution to that should be "use the JavaScript APIs that appear when I google 'stackoverflow encode url param' and not to hunt in our codebase to see whether we've written these helpers already.
If it was me I think I'd have relied on the default generatePath
and useParams
, changed param IDs in paths from stuff like :documentId
to :encodedDocumentId
and then either decoded encodedDocumentId
in the component after I get the value from useParams
or as a part of the relevant logic file, where I would pass encodedDocumentId
directly instead of documentId
.
Again, this is fine and if we want to go this way I'm down, it's just the pattern I'd have used.
@@ -56,7 +56,7 @@ export const ACTIONS_COLUMN = { | |||
{ defaultMessage: 'View query analytics' } | |||
), | |||
type: 'icon', | |||
icon: 'popout', | |||
icon: 'eye', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine.........😒
I think the key here, especially for me who spent about half a dev day debugging this on Kibana, is that it's not obvious which encoding our server API expects and why. It's It also was not obvious to me that RR's This helper manages all of that for us in a single place, making it easy to check git history & context. I know we're only really using this in 2 places in the codebase and that makes it "feel" not super useful right now, but I do think baking encoding into |
…-ml-jobs * 'master' of github.com:elastic/kibana: (254 commits) [Security Solution] [Detections] Remove allow_no_indices to prevent error being thrown in response of field capabilities (elastic#89927) Skip test for cloud (elastic#89450) [Fleet] Fix duplicate data streams being shown in UI (elastic#89812) Bump package dependencies (elastic#90034) [App Search] DRY helper for encoding/decoding routes that can have special characters in params (elastic#89811) TypeScript project references for Observability plugin (elastic#89320) [SearchSource] Combine sort and parent fields when serializing (elastic#89808) Made imports static (elastic#89935) [ml] migrate file_data_visualizer/import route to file_upload plugin (elastic#89640) [Discover] Adapt default column behavior (elastic#89826) Round start and end values (elastic#89030) Rename getProxyAgents to getCustomAgents (elastic#89813) [Form lib] UseField `onError` listener (elastic#89895) [APM] use latency sum instead of avg for impact (elastic#89990) migrate more core-owned plugins to tsproject ref (elastic#89975) [Logs UI] Load <LogStream> entries via async searches (elastic#86899) [APM] Abort browser requests when appropriate (elastic#89557) [Alerting] Allow user to select existing connector of same type when fixing broken connector (elastic#89062) [Data Table] Use shared CSV export mechanism (elastic#89702) chore(NA): improve logic check when installing Bazel tools (elastic#89634) ...
…ecial characters in params (#89811) (#90080) * Add encodePathParam helper + update components that need it - Primarily document URLs & analytics queries (which uses generateEnginePath) * Add useDecodedParams helper + update components that need it - Documents titles & Analytics queries * [Misc] Change popout icon to eye - Feedback from Davey - the pages don't open in a new window, so shouldn't use the popout icon - Not strictly related but since we're touching these links anyway, I'm shoving it in (sorry) * Remove document detail decode test - now handled/tested by useDecodedParams helper * Add new generateEncodedPath helper - Should be used in place of generatePath * Update all instances of generatePath to generateEncodedPath for consistency across the App Search codebase * Fix failing tests due to extra encodeURI() done by generatePath * Add missing branch test for analytics query titles Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Summary
There are two instances in App Search's routing where URLs can have special characters (user generated):
/app_search/engines/national-parks-demo/documents/test@#$
/app_search/engines/national-parks-demo/analytics/query_detail/test@#$
Testing these changes
Documents testing:
Analytics testing:
NOTE
There is still a bug when you reload the page on a document or query with the special character
%
in the title. React Router tries to double-decode the%
and unfortunately breaks the page. This is an issue with thehistory
library, NOT our code, and there is nothing we can do about it: #82440Checklist