If you have a client application that captures certain information as multipart/form-data to be saved in Salesforce and requires some pre-processing before saving the information, then the first thing that comes to our mind is to quickly expose an API and build a custom REST Service in Salesforce like this

@RestResource(urlMapping='/Resource/v1')
global with sharing class MyApexService
{

    @HttpPost
    global static String doPost(){
    
        // code to pre-process the incoming data before saving it
    }
}

Unfortunately, if you try to call this API by submitting a multipart/form-data request, you will encounter an error as shown below and the reason is indeed what the error says i.e. Apex REST does not support multipart/form-data requests

The Hack

Salesforce or any other server application identifies the incoming HTTP request type based on the Content-Type header. Therefore the hack to make the custom API accept such requests is to remove that multipart/form-data from the header. This obviously isn't simple though! Why? To find that, we need to first understand how multipart/form-data request body looks like and how are they handled/processed by the server.  

The Recipe - multipart/form-data

Jump to any API client like postman and create a multipart/form-data request by selecting the Body as form-data

This allows you to send information as key-value pairs including file (more on files in next article). And if you explore the code snippet which is a sneak peak into how the form data is send in the HTTP body, you will see something like shown below in the snapshot. Here are the ingredients of the multipart/form-data recipe.

  1. The key is set in name attribute (e.g. Title highlighted below) followed by value (e.g. Inteygrate highlighted below)
  2. Each key-value pair is separated by a random string called Boundary : ----WebKitFormBoundary7MA4YWxkTrZu0gW. This is the most important spice and without this the server application cannot cook, i.e. process our request.
  3. The server application uses this boundary value to identify from where does each key-value pair starts and ends. In the below snapshot you can see the boundary values at the beginning and at the end of each key-value pair. Boundary strings aren't fixed and are random; therefore in-order to let the server application know the boundary for a particular request - the same must be passed in the content-type header.
Actual value of Boundary might be different from what is shown in your API client.

This recipe of reading the boundary and processing each individual key-value pair is handled out-of-box by Salesforce for Standard REST APIs but for custom REST APIs we need to handle the logic. And this is why we say ...This obviously isn't simple though! in the hack section. So what is the solution? Simple, identify the boundary from the request body yourself and do not rely on the content-type header because we will be removing it 😬.

The Solution

For the request shown in the snapshot above the request body would look something like below:

This post is for paying subscribers only

Sign up now and upgrade your account to read the post and get access to the full library of posts for paying subscribers only.

Sign up now Already have an account? Sign in
You’ve successfully subscribed to inteygrate
Welcome back! You’ve successfully signed in.
Great! You’ve successfully signed up.
Your link has expired
Success! Check your email for magic link to sign-in.