Decode "multipart/form-data" with WebDev

We have a Zebra label printer that can send HTTP POST requests when certain conditions are met, such as when the ribbon is low. It uses “multipart/form-data” content type, and I am having difficulties figuring out how to parse the data so I can decipher the exact nature of the alert.

Does anyone know how I can decode “multipart/form-data” so I can decipher the alert message from the printer? I have tried a few different ways without success. I may be missing something obvious.

Probably want to start here:

HttpServletRequest.getPart(name)

(On the request object.)

I’ve got to be missing something obvious here. I’m trying to import the HttpServletRequest class, and I’m getting an error. I’ve tried the following:

from javax.servlet.http import HttpServletRequest
from java.servlet.http import HttpServletRequest
from java.http import HttpServletRequest

I keep getting “No module named servlet (or http).” What am I missing?

By the way, I’m brand new to importing standard Java libraries into Python scripts. Although that was probably already very obvious. :slight_smile:

You don’t need to import anything - you already have access to an instance of the HttpServletRequest interface. Access it from the request parameter - request["servletRequest"] - so all together it would be something like:

parts = request['servletRequest'].getParts()
part = request['servletRequest'].getPart("name")
1 Like

Thank you! I’m getting an error when I try that.

HTTP ERROR 500 Traceback (most recent call last): File “<samplequickstart/TestHTTP:doPost>”, line 4, in doPost at org.eclipse.jetty.server.Request.getParts(Request.java:2322) at org.eclipse.jetty.server.Request.getParts(Request.java:2310) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) java.lang.IllegalStateException: java.lang.IllegalStateException: No multipart config for servlet

However, I think may be making progress. Prior to opening this ticket, I was able to receive the multipart data with no issues using the following command:

data = request['postData']

The problem was that I wasn’t sure how to decode the data once it had arrived. I just realized that the data was BASE64 encoded, but now when I decode it, the contents are treated as a string. This makes it difficult to extract the actual form data I need.

----------------------------394672442565504488316976
Content-Disposition: form-data; name="test"

testvalue
----------------------------394672442565504488316976
Content-Disposition: form-data; name="test2"

test2value
----------------------------394672442565504488316976--

Obviously, I would prefer that the data is sent via JSON, but that does not appear to be an option with the Zebra printers. Is there any easy way to convert the BASE64 encoded form data into something that would allow me to retrieve values based on the keys?

Thanks again for the help!

Hmm, the bad news is it looks like that IllegalStateException isn’t something you can work around (though it’s an easy fix on our side; I’m going to open a ticket).
For parsing the data, I don’t see any readily available helper classes that are exposed. If you know the format you’re going to get from the zebra printer, it’s probably reasonable to do your own parsing.

Okay, sounds good. I have already started on parsing the string. It should be consistent and there are only 2 key/value pairs, so I don’t think it should be that hard to do.

Thanks for your help and prompt responses!

1 Like

I just realized that the data was actually being received as a byte array, and something within Ignition was converting it to BASE64 when it wrote the data to the tag. To convert the payload from the POST directly to string, just use the following function.

data = request['postData'].tostring()

There are other options for converting the byte array that can be found here: https://docs.python.org/2.7/library/array.html