HTTP PUT Call via REST API returning 200 code but empty response body

Jotinder Singh
Kilo Contributor

I have created a Scripted REST API call with HTTP PUT Method. I am calling the endpoint from a python script in order to update an incident in SNOW from my external application.

When I make the PUT request from Postman, it is working fine and is updating the Incident. Hence I know my script is working fine and also the user has the required roles to update the incident. 

However when I make the same call using my Python script, I get HTTP 200 but an empty response body and the incident is not updated. What am I possibly doing wrong? I tried playing around with header in my python script.

If I mention incorrect username / password in auth argument in my python script or if I mention incorrect content type in header, I do get a HTTP 401 response with proper error in the response body. However everything is correct and HTTP code is 200, I get empty response body with no updates happening.

 

Below is my Python requests snippet.

 

req_header = {"Content-Length": "230",
"Accept-Encoding": "identity, deflate, compress, gzip",
"Connection": "keep-alive",
"Accept": "*/*",
"User-Agent": "python-requests/0.11.1",
"Content-Type": "application/json"
}

API_ENDPOINT = "https://office_snow_instance.com/api/org/hear_clear_incoming_rest_api/updateincident"

data_json = {"SnowID": "IN21003453511",
"Incident_short_description": "Updated incoming REST call for jotinderl",
"assigned_to": "Jotinder Singh",
"sys_id": "be66f8587bd03850198c42eddc4bcb5f"
}
r = requests.put(url=API_ENDPOINT, data=data_json, auth=('POCuser ', 'XXXXXXXX'), headers=req_header)
print(r)
print(r.content)
return r.content

Note: masked some of the data in above code to maintain corporate security.
1 ACCEPTED SOLUTION

Hi Jotinder

It's a little hard (at least for me) to troubleshoot this with the information/snippets you've provided.  I have questions such as why the endpoint isn't the table API, but a customer table (hear_clear_incoming_rest_api) as well as why you're using port 8080 (and in the one screenshot a reply from local 127.0.0.1)  

Below is a snippet from my Personal Dev instance that works fine with Python using the standard ServiceNow Incident Table.  Could it simply be that you didn't import the request handler package into Python? (line 2 - I don't see that in your snippet)

#Need to install requests package for python
import requests

# Set the request parameters - The last parameter is the SYSID of the incident 
url = 'https://devXXXXX.service-now.com/api/now/table/incident/ed92e8d173d023002728660c4cf6a7bc'

user = 'admin'
pwd = 'xxxxxxxx'

# Set proper headers
headers = {"Content-Type":"application/json","Accept":"application/json"}

# Do the HTTP request
response = requests.put(url, auth=(user, pwd), headers=headers ,data="{\"short_description\":\"Updated incoming REST call for jotinderl\",\"assigned_to\":\"77ad8176731313005754660c4cf6a7de\"}")

# Check for HTTP codes other than 200
if response.status_code != 200: 
    print('Status:', response.status_code, 'Headers:', response.headers, 'Error Response:',response.json())
    exit()

# Decode the JSON response into a dictionary and use the data
data = response.json()
print(data)

 

View solution in original post

10 REPLIES 10

MattiasJonsson
ServiceNow Employee
ServiceNow Employee

What does the scripted rest api look like?

Does your script define the response?

https://docs.servicenow.com/bundle/quebec-application-development/page/integrate/custom-web-services...

If correct or helpful, please indicate so!

 

Hi Mattias,

 

Yes I have defined the response in my script. 

This is how my script looks.

 

(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
try {
var bo = [];
var body = {};


var number_id = request.body.data.SnowID;
var gr1 = new GlideRecord('incident');
if (number_id != undefined) {
gr1.addQuery('number', number_id);
}
gr1.query();

if (gr1.getRowCount() < 1) {
response.setError(new sn_ws_err.BadRequestError("Invalid CorrelationID or SnowID"));
} else {
var gr = new GlideRecord('incident');

if (number_id != undefined) {
gr.addQuery('number', number_id);
}
gr.query();
if (gr.next()) {

var shortdesc = request.body.data.Incident_short_description;
if (shortdesc != undefined) {
gr.short_description = shortdesc;
body.ShortDescription = gr.short_description;
}

var assignedto = request.body.data.assigned_to;
if (assignedto != undefined) {
gr.assigned_to = assignedto;
body.assignedto = gr.assignedto;
}

gr.update();

body.short_description = gr.short_description;
body.Number = gr.number;


body.Sys_ID = gr.sys_id;
bo.push(body);
response.setBody(body);
return response;

}
}
} catch (ex) {
gs.log("Error: " + ex.message);
}

})(request, response);

Roy Verrips
Tera Expert

Considering you said it's working in Postman, I'd venture to guess the issue isn't on the ServiceNow side.   The issue could be the content length calculation i.e.,

"Content-Length": "230"

The body is only 175 characters - I don't think it's a required field in the header - Can you try without it?  I believe the only required header is Content-Type.  I don't think User-Agent is required, but good to have.  What happens if you set the header as follows?

req_header = {
"User-Agent": "python-requests/0.11.1",
"Content-Type": "application/json"
}

 

Hi Roy,

 

I tried with the header that you mentioned, but am still getting HTTP 200 response but an empty response body.

 

find_real_file.png

 

Regards,

Jotinder