Response could not be serialized, input data was nil or zero length - get

If I made a request using postman it responds OK but if I try to use it in my app returns
this error:
"Response could not be serialized, input data was nil or zero length."
that's how I'm making my request on SwiftUI
let headers: HTTPHeaders = [
.authorization(bearerToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6Im5yb2NoYSIsImNvcnJlb0VsZWN0cm9uaWNvIjoibmVzdG9yLnJvY2hhQGZvcnRlaW5ub3ZhdGlvbi5teCIsInRpcG9Mb2dpbiI6IjIiLCJqdGkiOiJjOGIwZWQ1MC1hY2UxLTQ2MzItYjQxOS1mZjI0NWEzOTkyYWMiLCJleHAiOjE1ODg3MDAwNzN9.TQxA9c9TzqtDbFJSbnWMIK_vUshdVWG5kUnSN2c4Gk8"),
.accept("application/json")
]
AF.request("http://192.168.0.14:81/api/visitas/movil/dia-en-curso/usuario/2020/dia/=05%2F05%2F2020", headers: headers).responseJSON{ response in
switch(response.result){
case .success(let response):
print(response)
case .failure(let error):
print(error.localizedDescription)
}
}
I don't know what I'm doing wrong because it's the same that I put in Postman

By default Alamofire considers responses that return a 200 response code but no data to be improper and produces an error. Updating the server to return a 204 or 205 status will fix it correctly. Alternatively, you can create your own instance of JSONResponseSerializer with the appropriate expected empty response codes and use that to handle responses.
AF.request(...).response(responseSerializer: customSerializer) { response in
}

Related

How to set response status code in route with type json in odoo 14

I have created a route with type Json in odoo 14.
#http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
headers = request.httprequest.headers
args = request.httprequest.args
data = request.jsonrequest
So when I receive request using this route everything is fine, but suppose I want to return a different status code like 401, I could not do that with the route which type is json.
I have also tried the bellow method but the problem with this method is that it stops all odoo future requests.
from odoo.http import request, Response
#http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
headers = request.httprequest.headers
args = request.httprequest.args
data = request.jsonrequest
Response.status = "401 unauthorized"
return {'error' : 'You are not allowed to access the resource'}
So in the above example If I set the response status code to 401 all other requests even if they are to different routes will be stopped and its status code changes 401 .
I have checked this problem in both odoo14 and odoo13.
You cannot specify the code of the response, as you can see the status code is hardcoded in http.py:
def _json_response(self, result=None, error=None):
# ......
# ......
return Response(
body, status=error and error.pop('http_status', 200) or 200,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
If the result is not an error the status code is always 200. but you can change the code of the method directly or use a monkey patch witch if it's not really important to specify the code of status in the result don't do ti ^^.
A simple monkey patch put this in __init__.py of the module that you want this behavior in it.
from odoo.http import JsonRequest
class JsonRequestPatch(JsonRequest):
def _json_response(self, result=None, error=None):
response = {
'jsonrpc': '2.0',
'id': self.jsonrequest.get('id')
}
default_code = 200
if error is not None:
response['error'] = error
if result is not None:
response['result'] = result
# you don't want to remove some key of another result by mistake
if isinstance(response, dict)
defautl_code = response.pop('very_very_rare_key_here', default_code)
mime = 'application/json'
body = json.dumps(response, default=date_utils.json_default)
return Response(
body, status=error and error.pop('http_status', defautl_code ) or defautl_code,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
JsonRequest._json_response = JsonRequestPatch._json_response
and in the result of JSON api you can change the code of status like this
def some_controler(self, **kwargs):
result = ......
result['very_very_rare_key_here'] = 401
return result
The risk in monkey patching is you override the method compeletly and if some change is done in Odoo in new version you have to do you it in your method too.
The above code is from odoo 13.0 I did a lot of this when I build a restfull module to work with a website uses axios witch don't allow sending body in GET request. and odoo expect the argument to be inside the body in json request.

request.get_json() return 400 bad request

So I am testing POST to add new stuff to my database in postman and it keeps returning 400 error with no other info
127.0.0.1 - - [23/Feb/2021 00:46:04] "[1m[31mPOST /drinks HTTP/1.1[0m" 400 -
I tried to use request.is_json and it returns True. The code just returns error as long as it runs to
new_drink = request.get_json()
I have no idea where did I mess up.
#app.route('/drinks',methods=['POST'])
#requires_auth('post:drinks')
def add_drinks(payload):
new_drink = request.get_json()
title = new_drink.get('title')
recipe = new_drink.get('recipe')
drink = Drink(title=title,recipe=json.dumps(recipe))
drink.insert()
result = {
"success": True,
"drinks": drink.long()
}
return jsonify(result), 200
Here is a link to my project
https://github.com/TYL1026/coffee_shop/blob/main/backend/src/api.py
As mentioned in the comments, in my case the problem was a header. I was setting "Content-Type": "application/json" but I was sending form-data. I removed the header and the problem was solved.

Gzip response from soapUI in PHP

I m trying to get gzip response and for that I'm sending this node in body.
$body['TPA_Extensions']['IntelliSellTransaction']['CompressResponse']['Value'] = "true";
It returned successful response but didn't show it in var_dump. In var_dump it shows Null. In below image it shows successful response. Successful Response Image
Can anyone tell me how I get this data "H4sIAAAAAAAAALWS0WvbMBDG/5VDe/BLbTkLY..."
For the request test step, add Script Assertion with below snippet:
//Check response is not empty
assert context.response
//Parse response and fetch required value
def cResponse = new XmlSlurper().parseText(context.response).'**'.find {it.name() == 'CompressedResponse'}?.text()
log.info "Extracted data : $cResponse"

HTTPBuilder Not Acceptable error

I am getting this error but my method looks perfectly fine to me
def http = new HTTPBuilder()
http.request(
'https://textalytics-topics-extraction-11.p.mashape.com/topics-1.2?txt=ben',
Method.GET,
ContentType.JSON
) { req ->
headers."X-Mashape-Key" = "mashkey"
response.success = { resp, reader ->
assert resp.statusLine.statusCode == 200
println "Got response: ${resp.statusLine}"
println "Content-Type: ${resp.headers.'Content-Type'}"
println reader.text
}
response.'404' = {
println 'Not found'
}
}
any ideas?
Given that HTTP Not acceptable means:
406 Not Acceptable
The resource identified by the request is only capable of generating
response entities which have content characteristics not acceptable
according to the accept headers sent in the request.
Then perhaps their API is finicky and you need to specify that you want the response to be JSON using the Accept header, using something like Accept: application/json.

Response from a POST request in Groovy RESTClient is missing data

I am using groovy RESTClient 0.6 to make a POST request. I expect an XML payload in the response. I have the following code:
def restclient = new RESTClient('<some URL>')
def headers= ["Content-Type": "application/xml"]
def body= getClass().getResource("/new_resource.xml").text
/*
If I omit the closure from the following line of code
RESTClient blows up with an NPE..BUG?
*/
def response = restclient.post(
path:'/myresource', headers:headers, body:body){it}
println response.status //prints correct response code
println response.headers['Content-Length']//prints 225
println response.data //Always null?!
The response.data is always null, even though when I try the same request using Google chrome's postman client, I get back the expected response body. Is this a known issue with RESTClient?
The HTTP Builder documentation says that data is supposed to contain the parsed response content but, as you've discovered, it just doesn't. You can, however, get the parsed response content from the reader object. The easiest, most consistent way I've found of doing this is to set the default success and failure closures on your RESTClient object like so:
def restClient = new RESTClient()
restClient.handler.failure = { resp, reader ->
[response:resp, reader:reader]
}
restClient.handler.success = { resp, reader ->
[response:resp, reader:reader]
}
You'll get the same thing on success and failure: a Map containing the response (which is an instance of HttpResponseDecorator) and the reader (the type of which will be determined by the content of the response body).
You can then access the response and reader thusly:
def map = restClient.get([:]) // or POST, OPTIONS, etc.
def response = map['response']
def reader = map['reader']
assert response.status == 200
I faced a similar issue and I took the cue from Sams solution but used closures to address it (similar solution but coded using closures instead of the returned object).
resp.data is always null when using the RESTClient, however the reader contains the data, so it would look something like this:
def restclient = new RESTClient('<some URL>')
def headers= ["Content-Type": "application/xml"]
def body= getClass().getResource("/new_resource.xml").text
try {
restclient.post(path:'/myresource', headers:headers, body:body) { resp, reader ->
resp.status // Status Integer
resp.contentType // Content type String
resp.headers // Map of headers
resp.data // <-- ALWAYS null (the bug you faced)
reader // <-- Data you're looking for
}
} catch (Exception e) {
e.response.status // Get HTTP error status Integer
}

Resources