Handling attachments in IE9 & Older version browsers from SAPUI5 application and uploading them to SAP via SAP Gateway RESTful services
- added SAP Note 2170724 to fix error when maintaining external aliases
Use case: We need to upload the attachments from IE8/IE9 browser using SAP Gateway and SAPUI5. Many Enterprises still love to use legacy (old) browsers. 😆
So enabling these functionality becomes critical for companies without doing major browser upgrade. Let’s get started by discussing the scenarios and subsequently explaining the solutions involved.
Problem statement: SAPUI5 File uploader will work only with modern HTML5 browsers when using SAP Gateway as a backend to store files.
Issue: SAP Gateway OData service requires 2 custom headers to be set when handling attachment. (X-CSRF-Token and Slug). Only HTML5 compatible browsers will support setting these custom HTTP headers! In other words setting HTTP headers for a file upload request will not work in IE8 and IE9.
1.If you are using any Java server as frontend then below fix could be useful for you as suggested by W.Snoep ( Thank you Wim)
“Send parameters in the URL, and use the servlet to add the header parameters based on the URL parameters. The servlet already had the functionality of proxying but now also use it, to add the proper headers for slug and x-csrf/ x-requested-with header. This works and does add the file in the backend. However, since IE9 sends the file via an iframe as multipart/form data, it has extra header and footer data in the file in the backend. These need to be cut off in the backend ECC system. This functionality works smoothly now for IE9.”
2.If we can’t solve using (1) then we can follow below approach. (When both our frontend & backend are SAP systems).
Create a custom handler to achieve this.This blog mainly focuses on this approach. Here are the steps involved.
The development activities for this scenario have been split into two steps:
- Creation of custom handler – Setting up the Gateway environment (Steps covered in this blog)
- Consuming the OData service from SAPUI5 application (Watch out for this in the next blog)
Creation of custom handler – Setting up the Gateway environment
Client side (UI5 ver 1.22.4):
– In the UI5 client, for IE8 and IE9, add the x-csrf-token and slug (if you need it) value as hidden input value to the upload form. For newer browser (Chrome, IE10 etc.) , these values are added to the http request header.
– You can look up how to retrieve the upload form by looking at the upload method implementation for the FileUploader control in UI5 source code.
– For IE8 and IE9, set a different value (external alias defined below) for the uploadurl attribute of the fileuploader control.
The problem for IE8 and IE9 is that the default handler class (/IWFND/CL_SODATA_HTTP_HANDLER) for ICF odata node only reads the x-csrf-token from the http header and it’s not possible to set http header in IE8 and IE9. The idea is to create a custom handler to read the x-csrf-token from the post data and add it to the http request header and resume the normal request flow.
– Create a new custom handler class that implements the interface IF_HTTP_EXTENSION. This handler will read the x-csrf-token (or whatever name you use for the hidden input field) and set it in the http request header
– Since we cannot modify the handler list for the odata node because it’s sap standard, we’ll add the custom handler to the handler list in our application node which we have control. Add the default odata handler (/IWFND/CL_SODATA_HTTP_HANDLER) as the next handler in the list.
– Create an external alias for the new custom handler (e.g. customhandler). This value is used as the value for the uploadurl attribute on fileuploader control (pre-pend and append the value with ‘/’, e.g. /customhandler/) before setting to uploadurl attribute.
In IE8 and IE9, the fileuploader uploadurl will point directly to the application node and our custom handler will be processed before the default odata handler. Our custom handler reads the x-csrf-token from the post data and sets it to the http request handler thus allowing the default odata handler to read it.
Let’s start with coding and configuration stuffs. Assume we have created an OData service to handle attachments. Please refer below blogs if you want to know more on this.
Once we are done with the service you can notice our service will have a corresponding entry in the ICF application. Go to TCode SICF and check as shown below.
Click on the above highlighted entry and you can see the handlers involved.
The above handler will check the consistency of the X-CSRF-Token at runtime when we upload a file.
Now we need to manually set the X-CSRF-Token by creating a custom handler.
This must implement the interface “IF_HTTP_EXTENSION” and write logic in the method “IF_HTTP_EXTENSION~HANDLE_REQUEST” This will read the x-csrf-token and set it in the http request header
DATA: token TYPE STRING,
slug TYPE string.
*Read the Cross site forgetory token and Slug parameter from the POST data…
token = server->request->GET_FORM_FIELD( name = ‘X-CSRF-Token’).
slug = server->request->GET_FORM_FIELD( name = ‘Slug’).
server->request->set_header_field( name = ‘X-CSRF-Token’ value = token ).
server->request->set_header_field( name = ‘Slug’ value = slug ).
me->if_http_extension~lifetime_rc = if_http_extension=>co_lifetime_keep.
*Add below code so that subsequent handlers are called for the application node
me->if_http_extension~flow_rc = if_http_extension=>CO_FLOW_OK_OTHERS_OPT.
After done with creation of custom handler then we need to assign this to our OData service in the SICF application node as shown here.
Create an external alias for the new custom handler. This value is used as the value for the uploadurl attribute on file uploader control in the SAPUI5 app.
Click “External Aliases” and create a new alias pointing to our OData service we created in the beginning.
Make sure you prepend the alias name with forward slash ‘/’ otherwise you might encounter some error. After successful assignment alias structure will be like below one.
When maintaining external alias if you get error “Service not found” implement below note to sort this out.
Test the alias:
Testing the application:
For testing purposes I am using Google chrome to simulate IE behavior and check whether our OData service is working by passing data in URL headers. (Instead of passing in HTTP headers).
Get the X-CSRF-Token first:
Now get the token from the above request and pass them as URL parameter. Do not pass them in HTTP header .Use below URL to POST data to the server. Also attach the file which you want to upload. So our request should look similar to this.
Ensure we call in the below format:
AliasName – External Alias which we created pointing to OData service
EntitySetname – OData service Entity which handle media stream. In our case it is ‘FileDetailSet’
Slug – This can be used to pass File name, File type, File length etc.
Once we hit “Send “we can see below how the flow will happen in ABAP system.
Set the HTTP header manually in our custom handler which will be triggered first before calling OData handler.
As a next step our OData handler will be triggered. We can verify whether it is validated correctly in the Gateway framework as shown below (Flag set to X).
Finally we can see our create stream method is triggered. /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_STREAM
File content and Slug parameters are retrieved successfully within the Gateway framework.
Many Thanks to Andrew Ng for proposing this solution which motivated me to write up this as a blog. In my next follow up I will illustrate how we can integrate this to a SAPUI5 app and execute this from a MSIE (IE9) browser.
Thanks for reading this. Appreciate your feedback ! Also please hit “Like” if you like the blog post.