Apex REST does not support multipart/form-data requests[SOLVED]

Apex REST does not support multipart/form-data requests[SOLVED]
Photo by phil cruz / Unsplash
Apex REST does not support multipart/form-data requests[SOLVED]
Photo by phil cruz / Unsplash

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

global with sharing class MyApexService

    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

JSON Comparison in APEX

Compare two JSONS with simple == operator just like comparing two variables. LHS and RHS JSON can have different values and order of keys; the comparator will consider only the overall schema/structure.

Check Features

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.  

Note: this hack works only when the caller has the ability to remove the content-type header from the request before making a call to the Apex REST service.

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 (read this article for multipart/form-data file upload to Salesforce with APEX REST Service). 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 😬.

APEX REST Service responding to multipart/form-data requests

The Solution

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


DZining the building blocks for Enterprise Applications


Great! You’ve successfully signed up.

Welcome back! You've successfully signed in.

You've successfully subscribed to THR(EA)DZ.

Success! Check your email for magic link to sign-in.

Success! Your billing info has been updated.

Your billing was not updated.