httpPost response status codes?

I've been using the python 'requests' module for a while now, until a recent unexpected complication caused me to try system.net.httpPost again.

When i was using 'requests', my code looked something like this:

resp = requests.post(postUrl, headers=urlHeaders, data=payload)
if resp.status_code < 400:
	respJSON = system.util.jsonDecode(resp.content)
	logger.debug("POST API Success!")
	logger.debug(str(respJSON))
	return respJSON
else:
	logger.error("POST API Error: " + str(resp.status_code) + " - " + str(resp.content))
	logger.error("POST API Payload: " + str(payload))
	shared.log.scriptError(scriptName + "ERROR: " + str(resp.status_code) + " - " + str(resp.content))		
	return None
# end if

Which was working our really nice for me, as i could easily detect if the request failed by examining resp.status_code, and then easily create a descriptive error with resp.content.

However, now that i'm forced to use net.httpPost, my code looks a bit more like this:

try:
	resp = system.net.httpPost(url=postUrl, contentType="application/json",postData=payload, headerValues=urlHeaders, connectTimeout=30000,bypassCertValidation=True, throwOnError=True)
		
	respJSON = system.util.jsonDecode(resp)
	logger.debug("POST API Success!")
	logger.debug(str(respJSON))
	return respJSON

except:
	shared.log.scriptError(scriptName + " Error executing API, check error logs for details")
	logger.error("POST API failure. Check error logs")
	return None
# end try

The problem is, I can no longer extract the useful response content like i did before.
I have tried something from this forum post, where i captured the IOError e, but that returns just the string:

Server returned HTTP response code: 400 for URL: https://api.unleashedsoftware.com/StockAdjustments/cc0ef00f-b663-11ea-9101-7fca5527d026

Which is too generic to be of use to my client to debug.

So i then tried setting throwOnError=False, which provided the following JSON strings:

SUCCESS:

{u'Status': 'Completed', u'StockAdjustmentLines': [{u'Comments': None, u'SerialNumbers': , u'Product': {u'ProductCode': '5017'.........

FAILURE:

{u'Description': 'Cannot complete stock adjustment that leaves 0 stock with non-zero value. (Product 5017).', u'DebugInformation': None}

So at least with this i can provide a useful error message by looking at the response["Description"] field. However i don't have a reliable way to know whether the response was good or not, as i no longer get the HTTP response Code anymore.

Is there a way to get the best of both worlds here?

I don't really want to resort to something like this, as it doesn't seem particularly robust without knowing all the return options:

if respJSON["Status"] != "Completed" or respJSON["Status"] is None:
	logger.error(scriptName + " - " + respJSON["Description"])
	return None
else:
	return respJSON
# end if

We fixed these shortcomings in the system.net.http* functions with the introduction of system.net.httpClient in 8.0.

I don’t know if there’s any other workarounds besides using raw Java HttpURLConnection.

What happened with using requests that caused you to go back to system.net.httpPost?

Hmm that does look nice. Any way all these nice fixes can find themselves back ported to 7.9?
I fear it will be a bit of a mission to try upgrade to 8.

I’m not really sure why requests stopped working. Unleashed said there was an issue with their SSL cert, which they fixed. But ever since that issue i kept getting SSL connection errors when using GET and POST commands.

I had to use httpGet and httpPost with bypassCertValidation=True to get around it.

I was using a fairly old version of the requests module, 0.2.4. I believe due to python 2.5 limitations on Ignition 7.9 i can only upgrade to 0.10 anyway.

Not possible to backport; Java’s HTTPClient was added in Java 11.

requests (at least, modern versions) has the ability to bypass SSL validation; there’s no bypass flag you could use there and keep the same API?

Right.
So requests added a ‘verify’ argument which bypasses SSL verification, in version 0.8.8.
I’ll try upgrade to 0.10.0 and give that a go i guess.

Its a shame we gotta use such old versions of things!

Did you already give up on trying to figure out why the SSL connection doesn’t work? (or works sporadically? is it a certificate error?)

I don’t understand enough about it to know why it doesn’t work to be honest. Previous to Unleashed reporting their issue i had never done anything special on Ignitions end for SSL.
So i didn’t really know how to manage it.

Trying to use the updated requests module and getting the following error:

Traceback (most recent call last):

File "", line 36, in testSA_Post

File "", line 10, in post_new

File "C:\Users\Admin.ignition\cache\gw192.168.45.1_8088_8043_main\C3\pylib\encodings\idna.py", line 3, in

import stringprep, re, codecs

ImportError: No module named stringprep

Not sure if the encodings module was something Ignition has by default, i don't remember manually adding it.