-
-
Notifications
You must be signed in to change notification settings - Fork 21
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
Improve unserialization of VFS URL query parameters #56
Conversation
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.
Btw, this is what I came up with:
const assembleQueryData = (object) => {
const assembled = {}
const keys = Object.keys(object)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const dots = key.split('.')
let last = assembled
for (let j = 0; j < dots.length; j++) {
const dot = dots[j]
if (j >= dots.length - 1) {
last[dot] = object[key]
} else {
last[dot] = last[dot] || {}
}
last = last[dot]
}
}
return assembled
}
Also, the parsing could just happen in the utility function: Line 177 in d250050
No need to touch the actual VFS code 🤔 |
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.
Could you please amend the commit message so that it says:
Improve unserialization of VFS URL query parameters
Oh, yes, no need to change vfs! so should I have a commit in /*
* Parses URL Body
*/
const parseGet = req => {
const {query} = url.parse(req.url, true);
const assembledQuery = assembleQueryData(query);
return Promise.resolve({fields: assembledQuery, files: {}});
};
/*
* Assembles a given object query
*/
const assembleQueryData = (object) => {
const assembled = {}
const keys = Object.keys(object)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const dots = key.split('.')
let last = assembled
for (let j = 0; j < dots.length; j++) {
const dot = dots[j]
if (j >= dots.length - 1) {
last[dot] = object[key]
} else {
last[dot] = last[dot] || {}
}
last = last[dot]
}
}
return assembled;
} |
If you feel like my suggestion was a better example, then feel free to commit that. We'll be adding tests here so we know that it works properly. |
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.
Some minor stuff still to do here, including fixing the linting errors. I'll write a test for this and add it 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.
Here is a test that you can add to __tests__/utils/vfs.js
. It can be placed in the bottom of the describe
scope. Since I don't have write access to your fork, this is probably the easiest way to do this :)
test('assembleQueryData', () => {
const result = utils.assembleQueryData({
'a': 'b',
'b.a': 'foo',
'b.b.a': 'foo',
'b.b.b': 'foo',
'b.b.c': 'foo',
'b.b.d': 'foo',
'b.b.e': 'foo',
'c': 'null',
'd': 'true',
'e': '1'
});
expect(result).toEqual({
a: 'b',
b: {
a: 'foo',
b: {
a: 'foo',
b: 'foo',
c: 'foo',
d: 'foo',
e: 'foo'
}
},
c: 'null',
d: 'true',
e: '1'
});
});
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 realized that we had not taken arrays into account here.
?f.0=1&f.1=1&f.2=3
turns into:
"f": {
"2": "3"
}
This is obviously wrong :D So this needs to be fixed as well.
I think we should encode differently in client-side. In this way it will be decoded correctly. We don't have to touch unserialization. |
I believe that it's the underialization that needs to change. The client already does this correctly by having a sequence as keys, ex |
In this way, how we can distinguish between index and key 🤔 |
We can pretty much assume that it's an array if all the suffixes for the current key are numbers.
I don't understand what you mean by this. |
I think we can replace this line with : |
Not sure that is 100% reliable. An object can have numbers as keys as well,
and this does not seem to handle cases where it is for example mixed.
You can check this by updating the test with the suggested change. I would
recommend using a test-driven workflow: write the test with the outcome you
want, then change the implementation. That way there's no need for guessing
:)
…On Sun, Sep 5, 2021, 19:54 mahsashadi ***@***.***> wrote:
I think we can replace this line
<https://github.com/mahsashadi/osjs-server/blob/146efc9335b9c68603765698d15479374ca8afa6/src/utils/vfs.js#L191>
with :
last[dot] = last[dot] || (/^\d+$/.test(dots[j + 1]) ? [] : {})
—
You are receiving this because your review was requested.
Reply to this email directly, view it on GitHub
<#56 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AABHODBHYESO62I23YQGBU3UAOVEXANCNFSM5C74ZRNQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
We're starting to get somewhere now 😄 Could you please rebase this branch to the latest master so that the tests runs properly ? I discovered a race condition in the Core that prevents the tests from completing without doing a timeout which makes it impossible to check this PR 🤓 |
Just a quick instruction on how to rebase quickly:
Edit I just realized that this won't work with forks... sorry. This should work 🤔
|
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 ran the latest commit of this locally and checked the test, and it looks good to me 👍
So after you've done a rebase then the only thing that is left is to add the type casting!
os-js/osjs-client#165 (comment)
Nice work :)
Whenever I try to check the codeclimate report to see why the check is failing, I'm just getting the message "We do not currently have an analysis of these two commits" and whenever I click "Analyze" nothing seems to happen. Could you let me know if this PR needs some work that I could help out with? |
Probably because they have a retention policy on logs and this one is expired :/ |
Hi again, long time past since this pull request. |
@mahsashadi yeah, it's been quite a while. This is such a large integration that I haven't found much time to review it. However, I have been thinking about it every now and then. I'm not sure if having serialization like this is the best approach 🤔 Maybe this could be better solved by allowing JSON in the GET query ? |
@andersevenrud could you give an example of what you mean? If @mahsashadi doesn't have time to look into it I would be happy to give it a shot. Also, any updates on os-js/osjs-client#165, since that was mentioned in this PR as well? |
@ajmeese7 Instead of serializing like suggested here (and in linked PRs), I suggest just using JSON instead. Suggested solution here for the following
But I feel like this would be better approach:
In this context the relevant URL query parameters revolves around the The server by default does not allow this, but it's possible to override this to only be enabled on the VFS express router using middleware. |
So in client-side, we need to change this method as below: In server-side, we can change this method as below: But I think you mean something else in server-side, can you explain more? @andersevenrud |
Almost. It would be something like: const pairs = Object.entries(data).map(([key, val]) => {
const isNull = val === null;
if (typeof val === 'object' && !isNull) {
return `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(val))}`
} else {
return `${encodeURIComponent(key)}=${encodeURIComponent(val)}`
}
});
return pairs.join('&'); So instead of a "deep" serialization, any object or array is just made into JSON.
I believe there's a way to just use If not, it's super easy to just do this manually (as you can see from the code example above). |
Sorry but I did not get the whole thing yet:
|
Sorry, yes that's correct. Not sure what I was thinking here :)
I don't understand this. |
With the code example you wrote above for serialization, seems nothing need to be change in sever… options are correctly unserialized and passed to vfs. |
Since I was an idiot with the |
Is this method OK for unserialization? const assembleQueryData = (data) => {
let assembled = {};
for (const key in data) {
try{
const currentVal = JSON.parse(data[key]);
assembled[key] = currentVal;
}catch(e) {
assembled[key] = data[key];
}
}
return assembled;
}; |
I think here we are loosing some types for non-objects values. For example |
That won't really matter :) |
Using native methods is a little bit nicer :) const entries = Object
.entries(data)
.map(([k, v]) => {
try {
return [k, JSON.parse(v)]
} catch (e) {
return [k, v]
}
})
return Object.fromEntries(entries) |
Thanks @andersevenrud Just since |
As mentioned in os-js/osjs-client#165 (comment) I would like to have the PR split up. The same goes for this one. |
Thanks for the split 👌 since this branch now has so many commits and merges, and in addition to this now a conflict it might just be easier to open a new PR. A small tip: Look into git rebase instead of doing merges. This will save you a little bit of pain when working with PRs when the master branch is updated. |
Agreed @mahsashadi |
I'm closing this since we've agreed on a way to move forward. I've also opened an issue where we can concentrate the discussion. Things got a bit confusing with the client/server stuff :D |
The implementation of createOptions method changes to support decoding of options passed by GET request.
Relevant: