File Upload with Ajax
This reference topic outlines how the platform addresses same-origin policy restrictions to accomplish file upload with Ajax. It also illustrates use of the "Wrap In HTML" parameter in request messages and why you might see "lorem ipsum" text in the response HTML.
Note: In any scenario where files are being uploaded, anti-virus protection is recommended. Anti-virus protection for the platform can be added by the System Admin in Policy Manager.
It includes these sections:
- Same-Origin Policy Restrictions
- The "Wrap In HTML" Parameter
- Reading the Response
- Browser Limitation Workaround
- Operations that Support File Upload
- Background
Same-Origin Policy Restrictions
The Akana API Platform is an Ajax-based browser application. In supporting file upload with this type of application, one of the challenges is dealing with the browser's Same-Origin Policy restrictions. These restrictions prevent browser-based applications from invoking an Ajax call to a different domain.
To work around this restriction, there are multiple mechanisms that apps can use, such as JSONP, XDR, CORS, postMessage, and Flash policies. Each has its advantages and limitations; some only work for certain browsers or only work for HTTP GET calls. Some we do not support.
To work with these security restrictions when uploading files, the platform uses a jQuery plug-in to facilitate file upload. In simple terms, the plug-in creates an invisible iframe, instructs the server to return the response to the iframe, and sets the domain for the iframe to match the domain for the parent page. When the message is submitted, the main page is not refreshed, but the iframe is created and the response is returned to the iframe. Because the domain for the iframe matches the domain for the parent page, the platform can access the response.
Whenever we use this mechanism to support file upload in the Akana API Platform user interface, we pass the wrapInHTML request parameter. In response, the API returns a script tag, with the security domain set, wrapped in HTML.
The "Wrap In HTML" Parameter
In order to work with the Same Origin security policy when uploading files, in file upload operations the platform passes a wrapInHTML request query parameter. In the response, which is read programmatically, the API returns a script tag, with the security domain set, to an HTML iframe. The response is wrapped in HTML so that the iframe can read it. The HTML response is also padded to ensure it is readable to all browsers (see Browser Limitation Workaround below).
The sample request for the POST /api/apps/versions/{AppVersionID}/keyinfo operation is an example of this, as shown below:
https://{hostname}/api/apps/versions/4iXro2Uxs2h4LviCshR9pK9w.acmepaymentscorp/keyinfo?wrapInHTML=true
Below is an example of code you can use to create the iframe:
<iframe id="ifFileManager" style="width:100%;height:100%;" frameborder="0" src="/resources/global/upload.html?dynamic=true"></iframe>
This is a way of integrating Ajax file upload in the user interface and getting the response into JavaScript without changing the browser context.
Note: This parameter is needed only for browser-based applications using Ajax to post multipart/form-data form. If you are using Java or .NET or some other environment that is not browser-based, this parameter is not required even for multipart/form-data operations.
Reading the Response
Because the response is returned to an iframe, which is essentially an HTML page, the response must be readable as HTML. Therefore, the response is wrapped in HTML, as shown in the example below which is from the POST /api/dropbox/wsdls operation. Note the <script> tag which sets the domain for the iframe to match the domain for the main page.
<!DOCTYPE html><html lang="en"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"> <meta content="IE=edge" http-equiv="X-UA-Compatible"> <meta name="description" content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris lacus elit, ornare eget luctus vel, porta id elit. Maecenas molestie, libero sit amet blandit faucibus, orci nisi aliquet nisi, id mollis mauris ipsum a enim. Morbi lacus velit, placerat sit amet luctus eget, pulvinar a massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi eleifend tincidunt pellentesque. Cras eu sapien massa, vitae rutrum sapien. Aenean id condimentum sem. Suspendisse tempor luctus ipsum, vel metus."><script type="text/javascript">document.domain='api.acmepaymentscorp.com'; </script></head><body>PersonService.wsdl,xsd0.xsd,xsd1.xsd,xsd10.xsd,xsd11.xsd,xsd12.xsd,xsd13.xsd,xsd14.xsd,xsd15.xsd,xsd2.xsd, xsd3.xsd,xsd4.xsd,xsd5.xsd,xsd6.xsd,xsd7.xsd,xsd8.xsd,xsd9.xsd</body></html>
Browser Limitation Workaround
If an API call returns an error message that is less that 512 bytes in size, and the user's browser is Internet Explorer, the IE "Friendly Error Messages" feature replaces the custom error page with a generic one. In order to make sure that the custom error message is displayed for all users, regardless of browser, we add padding that increases the size to over 512 bytes.
For example, the response below is an HTTP status 200 success message. The <meta> tag includes padding to increase the size of the message to over 512 bytes. This padding is not displayed as part of the visible content of the HTML page, but ensures that the actual response message is relayed, rather than an Internet Explorer default page.
<!DOCTYPE html> <html lang="en" status="200" statusText="success"> <head> <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="IE=edge" http-equiv="X-UA-Compatible"> <meta name="description" content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris lacus elit, ornare eget luctus vel, porta id elit. Maecenas molestie, libero sit amet blandit faucibus, orci nisi aliquet nisi, id mollis mauris ipsum a enim. Morbi lacus velit, placerat sit amet luctus eget, pulvinar a massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi eleifend tincidunt pellentesque. Cras eu sapien massa, vitae rutrum sapien. Aenean id condimentum sem. Suspendisse tempor luctus ipsum, vel metus."> </head> <body status="200" statusText="success"> </body> </html>
Operations that Support File Upload
The file upload operations used by the platform support upload of several types of files; for example, avatar files for apps, APIs, users, or groups, or a WSDL ZIP file for an API.
In general, any operations that support file upload use the jQuery plug-in and the wrap in HTML parameter as explained above. These operations use multipart/form-data as the Content-Type in the request message. Some examples are:
- Apps service, Save Key Info: POST /api/apps/versions/{AppVersionID}/keyinfo
- Dropbox service, Read WSDL ZIP: POST /api/dropbox/wsdls
- Content service, Upload Content: POST /content/{path} operation (with multipart/form-data content type) to upload a single file, or multiple files in a ZIP; POST /content/{path} operation (with application/x-www-form-urlencoded content-type) to create a new folder.
Background
The wrapInHtml parameter is only needed if a browser-based client is making the call using AJAX, and only in the scenario of a single-page application.
In a single-page application, the browser’s address bar never changes, or changes only after the hash character. This is done so that a JavaScript context/cache is maintained in the page memory for a long time.
Browsers do not allow retrieval of the contents of a file in JavaScript for security reasons. Because of this, the only way to make a multi-part request is to use the form submit. But, the form submit will change the address, which doesn't work in the context of a single-page application. Therefore, the Community Manager developer portal uses an HTML iframe as the form submit output. But the JavaScript running in the single-page application must be able to read the contents of the HTML iframe. There are different kinds of issues with reading from an HTML iframe in different browsers.
To work around these browser restrictions to read from an HTML iframe, the Community Manager developer portal wraps the output of this REST API call in HTML so that the single-page JavaScript application can read the response.