Updated: Apr 13
Github repository with the Mule Project can be found at the end of the post.
Are you familiar with the fromBase64 or the toBase64 functions from DataWeave 2.0? What about the getUrlEncoder or the getEncoder functions from Java? Do you know the differences between the “basic” Base 64 encoding and the “URL and Filename safe” Base 64 encoding? Well, you may have guessed it by now, but you’re about to find out the answers to these questions!
Or maybe you’re here because you keep getting the “Illegal base64 character” error in DataWeave. Even if you get this error using any other programming language, this post can help you understand why it is happening.
I was recently presented with this problem when Maria Isabel Vargas asked a question about base64 decoding in a Slack channel. She was using the fromBase64 function that’s available in Mule 4 - DataWeave 2.0 inside the dw::core::Binaries module to transform a basic Base 64 string into a binary value.
The problem was that the server was returning a Base 64 URL Encoded String (e.g. “cHJvc3RkZXY_YmxvZw==”) opposed to the basic Base 64 string from which the fromBase64 function attempts to transform. As a result, the Transform Message component was returning this error: “Illegal base64 character 5f". This error happens when the string that you are trying to transform contains a character not recognized by the basic Base 64 Alphabet (in this case it was an underscore character). Below you can see which characters are accepted.
Since the server was using the Base 64 URL encoding, the string that we were trying to decode in DataWeave contained different characters from the ones above because the Base 64 URL has a different alphabet. You can see this alphabet below.
Notice that the characters 62 and 63 differ from the basic Base 64 Alphabet and the Base 64 URL Alphabet. The first one contains the characters plus (+) and slash (/), while the second one uses the characters minus (-) and underline (_).
In other words, if you have an encoded string like "cHJvc3RkZXY_YmxvZw==", you wouldn’t be able to transform it using a basic Base64 decoder because it contains characters that are not recognized by its alphabet (the underline character).
You can get these two errors when you try to transform a Base 64 URL string using the fromBase64 DW function (at least when this post was created):
java.lang.IllegalArgumentException: Illegal base64 character 5f (when containing an underscore)
java.lang.IllegalArgumentException: Illegal base64 character 2d (when containing a minus)
Java contains a function called getUrlDecoder, which is used to decode a string that was encoded using the Base 64 URL alphabet. This is exactly the problem that we were trying to solve. But before you start panicking and coding your solution using Java and creating a whole Java class, it's way easier to just use the Mule 4 Scripting Module. I’ll show you how.
This module should already be installed in your Studio. However, if you can’t see it, you can download it from Exchange. Alternatively, you can use the “Add Modules” button from Anypoint Studio, which is located on your Mule Palette.
After that, you can simply take the Execute component and drag-and-drop it into your flow. For this demonstration, I will be using an HTTP Listener as a trigger, and I will send the encoded string in the body of the request from Postman.
Once you have the Execute component, you can select “Groovy” as your Engine and paste the following line of code into your script:
You should end up with this:
As you can see in this Groovy script, we are using the getUrlDecoder function to decode whatever is in our payload. The result will be returned to our Postman application in the body of the response.
You need to make sure that the payload that is sent to the Groovy script is a Java String. So, let’s add a Transform Message right after the HTTP Listener and transform the payload into a Java string. Like this:
Let’s start this Mule app and test!
We send the same string as before (cHJvc3RkZXY_YmxvZw==) from Postman, and we expect to get the decoded message as a response.
And… it worked!
Try it yourself
Do you want to experiment a bit more with all of this? For sure! Let me give you a quick guide on how to do this.
1. Encode the bytes/string into a Basic 64 URL encoded string
You will need Java (or you can also do it in Mule 4 using a Groovy script) to get the encoded string first. You don’t need to download and install Java onto your computer to do this; you can search for a free online Java compiler like this one: TutorialsPoint Java Compiler
There, just copy and paste this Java code:
Next, click on “Execute” in the top left corner. You will see the encoded string on the right side of the website (the last line in the white background). Copy this string and save it somewhere so that you can use it in the next steps.
2. Create your Mule App in Anypoint Studio
Follow the steps explained previously in “The Solution”, or paste this code into the XML configuration of your file:
3. Create a Postman request
If you don’t have Postman, you can download it for free from here: Postman Download. When you open it, you just have to click on the plus (+) button as you can see here:
Then, add this in the Request URL section:
And add the previously copied string inside the Request Body. Don’t forget to select “Raw” and “Text” from the two dropdowns that are over the request body text area.