The Disturbed One The Disturbed One - 8 days ago 5
Javascript Question

Server Response gets weirdly en-/decoded when using special characters

As frontend and AJAX lib I am using Ext JS and I am encountering the following problem:

I am uploading a file, which shall be uploaded to the backend and the backend answers with the corresponding filepath in the repository, including some metadata. The whole answer is a JSON inside a HTML structure. (this needs to be done since the Ext js file upload creates a hidden iFrame and otherwise the domain of the iFrame differs from the browser)

The backend answers with the following path inside the response:

/documents/test/uploadTesthtml_ü_&/uploadTesthtml_ü_&.jpg


In the network panel the path is correct. But as soon as the success handler kicks in, the response contains this path:

/documents/test/uploadTesthtml_ü_&/html_ü_&.jpg


I get that this is pretty confusing to understand, when you haven't seen it life, but we need to be prepared for this specific use case and I hope you can follow my explanation.




Edit as answer to @Alexander's comment:

We are using a Java backend and use the following HTML structure around our JSON response:

<html>
<head>
<script>
function doDomainRelaxing() {
var x = location.hostname.indexOf('.') + 1;
if (x > 0)
document.domain = location.hostname.substring(x);
}
doDomainRelaxing();
</script>
</head>
<body>
[{...}] //JSON response
</body>
</html>


As far as I know, the reason for this was, that ExtJS uses a hidden iFrame for the file upload, which will receive the response from the server, after that, the response is taken from the iFrame to fake the response.responseText. The domain of our browser popup gets relaxed but the iFrame's domain doesn't, therefore we had a problem with the same origin policy and the response.responseText was empty. To solve that, we use the mentioned HTML wrapper to relax the domain of the iFrame as well.

Answer

The cause of the problem was the HTML wrapper around the response and the way the JSON was written into the wrapper.

Originally, the JSON was written directly into the HTML response inside the body, which causes the browser to interpret the content as HTML entities and therefore the &uuml; was decoded to ü in the iFrame HTML. After that, when ExtJS takes the response from the hidden iFrame, it was encoded, but only the & and not the ü. The solution was to add the JSON response after the body was rendered via JS.

<html>
    <head>
        <script>
            function doDomainRelaxing() {
                var x = location.hostname.indexOf('.') + 1;
                if (x > 0)
                    document.domain = location.hostname.substring(x);
            }
            doDomainRelaxing();
        </script>
    </head>
    <body>
        <script>
            document.body.innerText = [{...}] //JSON response
        </script>
    </body>
</html>

And afterwards I had to use Ext.htmlDecode(response.responseText); in my success handler to decode the &amp; in the response.