Error with httpClient

below calls

  • First one using old method httpPost and got replay Ok-200
  • Second one using httpClient.post getting error below

Status: 422
Body: {"detail":[{"type":"missing","loc":["body"],"msg":"Field required","input":null}]}

### Working Fine ####

import system, json

####Blow one working fine 
url = "http://localhost:8001/getdata"
payload = {"message": "ping from httpPost"}

body = system.util.jsonEncode(payload)
headers = "application/json; charset=utf-8"

resp_text = system.net.httpPost(url, headers, body)
print "httpPost ->", resp_text

########## getting error 422######### 

import system, json

url = "http://localhost:8001/getdata"
payload = {"message": "ping from httpClient"}

client = system.net.httpClient()
body_bytes = bytearray(json.dumps(payload), "utf-8")

resp = client.post(
    url,
    headers={"Content-Type": "application/json; charset=utf-8",
             "Accept": "application/json"},
    data=body_bytes
)

print "Status:", resp.getStatusCode()
print "Body:", resp.getText()

To start with, do not import system, system.* functions are available by default in all contexts (with some omitted dependent on scope). Second, unless you are doing something really out there with json, just use system.util.jsonDecode/jsonEncode instead of importing a python library. You did this with the first script but not the second?

You are specifying a content type of application/json but then passing a byte array, which normally would get a content type of application/octet-stream

Quoting the manual:

Data to send in the request. Defaults to None. [optional]
String data will be sent with a Content-Type of text/plain; charset=UTF-8, unless a different Content-Type header was specified.
Dictionaries will be automatically encoded into JSON to send to the target server, with a Content-Type header set to application/json;charset=UTF-8 unless a different Content-Type header was specified.
Byte arrays will be streamed directly to the target server, with a Content-Type header of application/octet-stream unless a different Content-Type header was specified.

Based on your two scripts, you aren't actually doing a one to one comparison. The first script is only encoding the body data as a JSON object, the second is encoding as a byte array. Based on the manual, you should be able to pass the payload dictionary directly to the data parameter with no other encoding necessary.

Try using the following for your second script instead:

resp = client.post(
    url,
    headers={"Content-Type": "application/json; charset=utf-8",
             "Accept": "application/json"},
    data=payload
)

Also, you are creating an httpClient() object on every event. This is extremely non-optimal. Create the client object in a project library script, outside any function, so it will be cached and re-used.

Some general Ignition scripting optimizations:

  • Do not use the import statement directly in any event, nor in any def at all. Place all necessary imports in the outer level of a project library script, and create functions in that script to use the imported names.

  • in events and transforms, use a one-line callout to a project library function, passing all context variables are function arguments. Do not write general logic in events.

  • Use the right click menu on tabs in the project library script editor to "float" them, so you can edit library scripts while working anywhere else in the designer.

  • In jython, bytearray() doesn't create a byte array that is acceptable to java. (It is effectively useless/wrong in jython, always.)

4 Likes

Thanks a lot ryan and @pturmel for your guidance ,

issue solved it seems the endpoint using HTTP_ 1_1

client = system.net.httpClient(version="HTTP_1_1")