Support of the multiple maps being embed with iframe and POST-based configuration approach
Description
With the recent changes provided by https://github.com/geosolutions-it/MapStore2/pull/8006 and corresponding PR MapStore now has a support of passing map configuration not by only GET parameters, but also using POST request to an endpoint. This endpoint then process POST values by transforming them into entries in sessionStorage and trigger redirect to the map viewer route. Client-side read values from sessionStorage and transform them into corresponding actions (to update map object, change center, trigger actions etc.). This approach overcomes limitation of URL length when everything is passed in the GET request, but it also turned out that current implementation is restrictive and doesn't allow to have multiple maps embed properly on the same page when POST approach is used.
The problem is caused by the fact that multiple iframes share sessionStorage whenever they have same origin. In this case configuration applied by back-end/passed to the sessionStorage will be overwritten by the last iframe loaded on the page and since MapStore clears passed parameters from sessionStorage after they read - this will lead to scenario when only one or even none of the map will get proper configuration.
Proposal
- Update endpoint on the back-end and make it generate UUID for each request.
- Use this UUID as suffix for
queryParamsitem in sessionStorage, e.g.queryParams-\<UUID\>. - Trigger redirect to the URL specified by the user but also add query parameter
uuidthat will be same as the one used by back-end to save configuration into sessionStorage. E.g.#/viewer/openlayers/config?uuid=bb9cae10-bfea-4411-b119-c5da05b378f8 - This parameter will be used then to fetch proper/corresponding item in the sessionStorage and will allow have unlimited amount of maps embed using POST.
What kind of improvement you want to add? (check one with "x", remove the others)
- [x] Minor changes to existing features
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Other... Please describe:
Other useful information
@alexander-fedorenko can you please argument a bit more this point and the involved use case?
Trigger redirect to the URL specified by the user but also add query parameter uuid that will be same as the one used by back-end to save configuration into sessionStorage. E.g. #/viewer/openlayers/config?uuid=bb9cae10-bfea-4411-b119-c5da05b378f8
@alexander-fedorenko can you please argument a bit more this point and the involved use case?
Trigger redirect to the URL specified by the user but also add query parameter uuid that will be same as the one used by back-end to save configuration into sessionStorage. E.g. #/viewer/openlayers/config?uuid=bb9cae10-bfea-4411-b119-c5da05b378f8
Sure, this is for the next point:
This parameter will be used then to fetch proper/corresponding branch of the sessionStorage and will allow have unlimited amount of maps embed using POST
MapStore need to know which part of the written queryParams object need to be used as a source of the parameters for the specific request/map on the page. This is possible by reading this extra query parameter from URL and then using it as a key to fetch proper branch of values. I'm not sure if there is another approach to make each embedded map understand which chunk of queryParams object should be used.
Yes It is ok. I don't see any other solution. This one should keep the same API simple for the user that creates the POST request, and require only a little bit more work to the server and mapstore.
I should only rename the parameter from uuid into a queryParamsID, to better identify the parameter inside the mapContext.
Make sure to give to the back-end developer the correct code to set sessionStorage and test the two cases.
@taba90 we should schedule the expected minor changes for the backend part accordingly.
@offtherailz I just thought about race condition that could probably appear if we going to write everything inside of a single structure called "queryParams" in the sessionStorage. Every time object need to be serialized/unserialized upon fetching data from sessionStorage or writing to it. Not necessarily, but it might be the case that multiple iframes will do reading/writing concurrently which can potentially lead to data corruption. What if instead of using single "queryParams" object, we will write each request data to unique entry called "queryParams-<queryParamsID>" or something similar?
Yes, good point. I agree with this solution. Can you @alexander-fedorenko sync with @taba90 about the necessary changes?