Let’s talk about UI Elements and interceptors

|
Share
Let’s talk about UI Elements and interceptors

Box UI Elements are used by lots of developers to embed Box Content in a custom experience on a web site. The speed of deployment and ease of use makes them very compelling. See more in these articles: Getting Started with Box UI elements, Let’s talk about integrating Box and Introducing the Box UI elements workshop

Sometimes though there are some edge use cases where developers need to implement a very specific piece of functionality that is not directly supported in the UI Elements currently. For example

  • Only allow PDFs to be uploaded with the upload component (or don’t allow ZIP files to be uploaded).
  • Show a message/banner based on metadata on the file(s) or folder.
  • Exclude certain files from view
  • Automatically refresh the access token if expired
  • Add a prefix to uploaded files
  • Custom logging of requests and responses for monitoring purposes

One solution to these use cases functionality is using ‘interceptors’. These are javascript functions that directly allows the developer to manipulate the request and response to and from theBox API. They are part of the Axios library that is used by the Box UI elements to facilitate the communication between the client and the Box API.

It is important to state that any interceptor changes will only effect the client experience, not Box permissions or settings.

Box UI Elements supports two interceptor patterns:

  1. Request Interceptor: Access and manipulate the request being sent to the Box API.
  2. Response Interceptor: Access and manipulate the response from the Box API

Setup

I have a standard HTML page that contains a Box UI Element content explorer and a request and response interceptor example. Currently, they just write the value of the config object to the console. The config object is the data about the request or response that I get access to manipulate. So for requests, I can change the headers, the url and the data passed, and for the response I can change the data that has been returned.

 var myResponseInterceptor = (config) => {
            console.log(config);
   return config;
    };
    var myRequestInterceptor = (config ) => {
            console.log(config);
   return config;
    };
        var accessToken = "<DEVELOPER TOKEN>";
        var folderId = "<FOLDER ID>";
        var explorer = new Box.ContentExplorer();
        explorer.show(folderId, accessToken, 
        {
            "container":".container",
            "requestInterceptor":myRequestInterceptor,
            "responseInterceptor":myResponseInterceptor
        });

An intercepted GET request looks something like this and will give access to manipulate the URL being requested, the headers and the query parameters.

2

An intercepted POST request looks something like and gives access to the posted data as well:

3

And an intercepted response looks something like this, allowing me to interrogate both the returned data and the details of the request that resulted in the response.

4

First example — exclude ZIP files from upload

Let’s look at my first example. I want to make sure that the user cannot upload ZIP files to Box via our UI Element. Of course I can add a message to the page etc., but I really want to avoid any ZIPs going into the folder.

So to do this I need to intercept the request to upload a zip and make sure it does not complete.

  1. Identify the request that is responsible for the upload.
    This does require some knowledge of the the workings of the Box API, so I look at this upload file reference and determine that if it is a POST call to a URL that starts with ‘https://upload’. it is a upload call being made.
  2. Check the name
    The name of the file will be in the data attributes for POST requests with formData which the upload endpoint use. The formData is actually a JSON string so it will need to be parsed to a JSON object to access the individual attributes.
  3. Set a different URL
    As I don’t want the file to upload I can change the URL to ‘something else’ — here I add a URL to the Box API that I know will return an error. This will make the request fail and the file will not be uploaded. I cannot directly cancel the request so use a ‘fake’ redirect it instead.
  4. Alert the user
    Here I add a javascript alert but it could also write to a banner or notification on the page.
 var myRequestInterceptor = (config ) => {
      console.log(config);
      if ( config.method == "post" && config.url.startsWith("https://upload")) {
          var formDataAttributes = JSON.parse(config.data.attributes);
          if (formDataAttributes.name.endsWith(".zip")) {
            console.log("No zip files allowed");
            //send to another URL that will error
            var rejectURL = "https://api.box.com/2.0/files/badextension";
            config.method = "get";
            config.url = rejectURL;
            //Alert the user - could also display a banner or similar
            alert("Please upload anything other than ZIP files.");
          }
      }
      return config;
    };

When I load my page and try to upload a zip file I get this alert

5

and this message in the UI Element uploader

6

Check the GitHub gist with the page.

Second example — exclude docx, xlsx and pptx from the list of files

In this example I want to load the UI Element Content Explorer but I want to exclude xlsx, pptx and docx files from the view in the list.

To achieve this I need to intercept the response from Box and remove entries from the returned list of items.

  1. Identify the response that contains the file list
    There two ways of getting a list of files for folder. The /items endpoint or the folder information endpoint (by including the ‘item_collection’ field). By logging the requests I can see that the UI elements use the second option
  2. Alter the response to omit files with a give extension
    The response data holds the item_collection which has a list of all the returned files. I add a filter that removes the three office formats
  var myResponseInterceptor = (config) => {
      if(config.request.responseURL.includes('item_collection')) {
          config.data.item_collection.entries = config.data.item_collection.entries.filter((entry) => {
            return !entry.name || !/\.(docx|xlsx|pptx)$/i.test(entry.name);
          });
       }
  return config;
};

Before implementing the interceptor:

7

After implementing the interceptor:

8

Check the GitHub Gist with the page.

Third example — add a banner to preview if the file has malware

This interceptor can mimic what the box.com app experience is when a file is identified with malware via Box Shield security. Box Shield can scan all uploaded files for malware and add additional protections (such as disable downloads) and alerting admins of the file. If a file has been identified with malware, Box will add a global metadata template instance called ‘MalwareDeepScan’ to the file.

For this interceptor I need to do three things.

  1. Add the malware metadata template to the request
    To be able to read the malware metadata I need to make sure that it is requested as part of the response. I do this by adding it to the list of fields for the file that is being previewed from the Box UI Element.
  2. Check the malware attribute on the response
    The response will list the values of all the fields requested. If the malware metadata is present on a file it means Box Shield has identified malware in the file.
  3. Display a banner above the preview if the file has been identified with malware
    A bit of HTML to show a banner on the page if the file has been identified with malware
var myResponseInterceptor = (config) => {
      //If the type of the returned data is file and the metadata is not null, then prepend a malware warning banner
     if(config.data.type && config.data.type=='file') { 
        if(config.data.metadata!=null) {
          $("#banner").text('Malware detected');
        }
   };
   return config;
};
var myRequestInterceptor = (config ) => {
   if(config.url.startsWith('https://api.box.com/2.0/files')) {
      //Clear the banner
      $("#banner").text('');
      let params = config.params;
      //Inject the metadata.global.MalwareDeepScan field into the request
      params.fields+=params.fields + ',metadata.global.MalwareDeepScan';
      config.params = params;
   }
   return config;
};

Preview of Malware infested document

9

Preview of regular document

Check the GitHub gist with the page

Further reading

More details about the Axios interceptor pattern:

🦄 Want to engage with other Box Platform champions?

Join our Box Developer Community for support and knowledge sharing!

10