Issue with PUT byte content with system.net.httpClient - leading and trailing zeroes

Ignition 8.1.20
Having an issue trying to http put byte content (bytearray) with system.net.httpClient(). It appears to be adding extra leading and trailing zeroes. My goal is to take a base64 encoded string and http put a bytearray of the decoded string.

I've seen system.net.httpClient().request() is doing some uncommanded encoding on my binary data and I'm wondering if @pturmel suggestion of using java functions (for the base64 decode and conversion to bytearray?) will solve my issue. I'm terrible with java so I'd like to confirm this may fix my issue before I go down the learning hole.

Here's what I've reproduced:

import base64

Headers = {'Content-Type': 'application/octet-stream'}
ServerURL = "https://myserver/test1.txt"

image_64_encode = "YWJj"  #utf-8 base64 encoding of 'abc'
image_64_decode = base64.b64decode(image_64_encode)

ba=bytearray(image_64_decode)
body = ba

client = system.net.httpClient()
postResponse = client.put(ServerURL, None, body, headers=Headers)

zeroes

I also tried Content-Type=text/plain; charset=UTF-8 with the same results. If I http put just plain old ASCII, it works fine with no extra zeroes.

@Kevin.Herron suggestion like this exhibits the same behavior:

bin = [97, 98, 99] # 3 bytes of utf-8 to represent 'abc'
bytes = jarray.array(bin, 'b') # create a Jython Byte[]
body = PyByteArray(bytes)

I haven't verified with HTTP Toolkit because I don't have experience with it but I'm getting ready to start.

(snipped)

edit: okay sorry that's maybe not helpful if you don't have control over the receiving side. You can send binary with an application/octet-stream content type if you want. I think the system.net.httpClient will automatically set the content type to that if you provide a PyByteArray as the payload.

@Kevin.Herron - I agree. But I have a string memory tag that is populated by another process I don't have control of. It is a base64 encoded image. And unfortunately I don't have "much" control of the other side and I'm trying to avoid the extra 33% size increase due to base64 encoding.

Just saw your edit. Yeah, very little control on the receiving side. I am seeing the same issue with 'Content-Type': 'application/octet-stream'

This code PUTs just the 3 bytes for me, verified in Wireshark as well as the echoed response:

import base64

headers = {'Content-Type': 'application/octet-stream'}
url = "http://postman-echo.com/put"

image_64_encode = "YWJj"
image_64_decode = base64.b64decode(image_64_encode)

client = system.net.httpClient(redirect_policy="ALWAYS")

response = client.put(url=url, headers=headers, data=image_64_decode)

print response.statusCode
print response.text

I'll try your method shortly. In the meantime, this appears to work for me, too. No leading or trailing zeroes.

import base64
from java.util import Base64

Headers = {'Content-Type': 'application/octet-stream'}
ServerURL = "https://myserver/test1.txt"

encodedString = "YWJj"
decodedBytes = Base64.getDecoder().decode(encodedString);
body = decodedBytes

client = system.net.httpClient()
postResponse = client.put(ServerURL, None, body, headers=Headers)
1 Like

You're absolutely right, @Kevin.Herron. I used your example it worked. The issue was me trying to convert the str image_64_decode to a bytearray. That's what was adding the zeroes. Not sure why I thought it "needed" to be in a bytearray. Maybe like you said, application/octet-stream does that for me (without the zeroes)?

Thanks so much for your help.

Actually I just changed Content-Type to 'text/plain; charset=UTF-8' and your example still works. Guess I don't need to know the details of system.net.httpClient() other than it's working and I overcomplicated it :roll_eyes: