Send Json over websocket - javascript

I have a JavaScript client and Python tornado server. I am sending messages in Json format strings back and forth. here is my JavaScript function:
var message = {};
var senders
message["messageKey"] = "title";
$.ajaxSetup({ cache: false });
$.getJSON("sample.json", function(json) {
message["data"]= json;
senders = jsonToStrConvert(message);
});
function jsonToStrConvert(mes)
{
var getBack= JSON.stringify(mes);
return getBack;
}
It basically takes the data from a json file, convert it to string object and send it through.
On the server side, python with tornado framework:
JsonMessage = json.loads(message)
self.write_message(JsonMessage['messageKey'])
It works fine, even with relatively large Json payload. After convert the string message to dictionary, I can freely do anything with it. However, sometimes for unknown reasons, I got error like this:
connection opened
ERROR:tornado.application:Uncaught exception in /
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/tornado/websocket.py", line 494, in _run_callback
result = callback(*args, **kwargs)
File "index.py", line 29, in on_message
JsonFormattedMessage = json.loads(message)
File "/usr/lib/python3.4/json/__init__.py", line 318, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.4/json/decoder.py", line 343, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.4/json/decoder.py", line 361, in raw_decode
raise ValueError(errmsg("Expecting value", s, err.value)) from None
ValueError: Expecting value: line 1 column 1 (char 0)
connection closed
The error happens under the same circumstances when it works, both server and client on the same network. happens with the same json payload that worked before.
I have absolutely no knowledge about networking. Is there any better web-sockets server to use? may be specific for JSON? Is there any cashe or something I can refresh to prevent that error? I searched alot and could not find a better reliable way?

Related

How to package plain JSON content in a WSGI response?

I have a Django WSGI (not my decision) website making a call to fetch dynamically generated JavaScript. I put the function in views.py and it's receiving the request and doing the work, but the return value is being rejected.
The HTML (JavaScript section of web page) that calls this function does it like this:
var jscript = document.createElement('script');
jscript.id = 'generate';
jscript.style.visibility = 'hidden';
jscript.style.display = 'none';
jscript.src = `/generate?callback=catchOptions${query}`; // jsonp https://en.wikipedia.org/wiki/JSONP query is a list of parameters in query string format
if (document.getElementById("generate") == null)
document.body.appendChild(jscript); // javascript needs this to work properly
There's map file that maps /generate to /generate_planet (see below). Getting into the function works great. It's the return value that Djangoff is rejecting.
Here is the function in views.py
from cgitb import reset
from django.shortcuts import render
from . import planetor
from django.http import JsonResponse
def generate_planet(request):
res = planetor.generate(request.content_params, "/app/planetor/", "FRAMES=1")
# res is JSON text, NOT a python dict
return res
# res looks like this:`callback({'camera_location': '-30,-30,-30', 'camera_angle': '30', 'sun_color': '5,5,5', 'sun_position': '10000,0,-10000', 'planet_size': '20.06', 'background': 'background_2.jpg', 'planet': 'surface_1.jpg', 'clouds_size': '1.02', 'clouds': 'clouds_16.jpg', 'clouds_density': '0.80', 'atmosphere': 'iodine', 'atmosphere_density': '0.95', 'atmosphere_size': '1.03', 'moons': '4', 'moon_position': None, 'moon_size': None, 'moon': None, 'random_color': None, 'random_float': None, 'random_trans': None, 'star_system': 'Barnard', 'star_index': 'Zeta', 'planet_index': 'II', 'planet_type': 'Surface ', 'identity': '81654447928', 'designation': 'v_star_index v_star_system v_planet_index', 'clouds_file': 'clouds_16.jpg'})
The function call actually works, and the "planetor.generate()" runs. The problem is, the return JSON (JSONP really) from this, is rejected by Djangoff
Djangoff spits out this:
Internal Server Error: /generate_planet
Traceback (most recent call last):
File "/usr/local/lib/python3.9/dist-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.9/dist-packages/django/utils/deprecation.py", line 119, in __call__
response = self.process_response(request, response)
File "/usr/local/lib/python3.9/dist-packages/django/middleware/clickjacking.py", line 33, in process_response
response.headers['X-Frame-Options'] = self.get_xframe_options_value(
AttributeError: 'dict' object has no attribute 'headers'
[05/Jun/2022 16:52:11] "GET /generate_planet? HTTP/1.1" 500 56694
It's looking for the return value to be wrapped in something I'm sure but for the life of my I can't find 1) any API documents for WSGIResponse to I can construct one and 2) examples of anyone doing anything like this with Djangoff
I eventually figured this out.
If you send a request to Django, like this:
/my_request?key1=value1&key2=value2&key3=value3
By whatever means (raw URL, form submit, ajax request, whatever)
To have Django catch that request and return a JSON answer put a function like this in views.py
def my_request(request):
selections = request.GET # <== this gets the query string paramaters as a dictionary
# use the query string parameters as the parameters of the function for creating the answer to the request
res = {"answer1":"value1","answer2":"value2"} # << python dictionary of answer
return JsonResponse(res) # convert dictionary to JSON
If you want to get JSONP back, you'll have to just code the raw javascript:
return 'callback({"answer1":"value1","answer2":"value2"})'

TypeError: expected bytes-like object, not str

I know this question has been asked much times, but please look once in my problem.
I am sending base64 image data from angular to python flask but when I am processing that base64 data on flask server(python3) then it is giving me the error
TypeError: expected bytes-like object, not str
My Javascript code is:
window['__CANVAS'].toDataURL("image/png");
Output of the above line is:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUg....."
I am receiving same data on flask server as string.
Code on python server that is using above base 64 data is:
def convert_to_image(base64_code):
image_64_decode = base64.decodebytes(base64_code)
image_result = open('baseimage.jpg', 'wb')
image_result.write(image_64_decode)
img_rgb = cv2.imread('baseimage.jpg')
return img_rgb
then it is giving the following error trace:
File "/home/shubham/py-projects/DX/Web/app/base64toimage.py", line 10, in convert_to_image
image_64_decode = base64.decodebytes(base64_code)
File "/usr/lib/python3.5/base64.py", line 552, in decodebytes
_input_type_check(s)
File "/usr/lib/python3.5/base64.py", line 521, in _input_type_check
raise TypeError(msg) from err
TypeError: expected bytes-like object, not str
above python function working fine if I am converting the image using this function
import base64
with open("t.png", "rb") as imageFile:
str = base64.b64encode(imageFile.read())
print str
please help me to solve this question? I am new to python.
base64.decodebytes only accepts byte arrays, use base64.b64decode instead it accepts Strings as well
Encoded bytes will do.
bytes(base64_code, encoding='utf-8')

"Unexpected end of JSON input" error on loading JSON file from local file system

Hi I'm trying to retrieve data from a title.JSON file into an index.html file using AJAX calls.Both these files resides in my local file system.I have created a new instance of the chrome and 've set its target property as "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"--disable-web-security --user-data-dir="c:/chromedev"(I'm aware that this is not a good practice. Just trying out a server less way).Below is my code
<h1><a id="headName" href="#">Name</a></h1>
<p onclick="spaLoad()">NameChange</p>
function spaLoad(){
var xhr = new XMLHttpRequest();
xhr.open('GET','title.json',true);
xhr.send();
xhr.onreadystatechange=function () {
//var obj=xhr.responseText;
var obj = JSON.parse(xhr.responseText);
console.log(obj);
console.log(xhr.readyState);
console.log(xhr.status);
console.log(xhr.statusText);
//document.getElementById('headName').innerHTML = obj;
document.getElementById('headName').innerHTML = obj.name;
}
}
title.json
{"name":"stackoverflow","age":"100"}
I get my h1 updated as "stackoverflow" through an ajax call along with the error
Uncaught SyntaxError: Unexpected end of JSON input
at JSON.parse ()
at XMLHttpRequest.xhr.onreadystatechange
Here are my doubts:
1.I hope AJAX is for the communication between the client and the server. Though I have avoided using a server by modifying the browser settings, how did the ajax call work for me?Is it logical?
2.The JSON file contains the data as objects.Then why should I use JSON.parse(responseText)?(JSON.parse() is for converting the string from server into object for client I hope).If i directly give var obj=xhr.responseText;I get undefined.
3.readystate is changing to 4, but status is always 0.Why is it so?How could I resolve it.
Please give a brief explanation of how this server less ajax call works.I'm very new to ajax and is confused with this.
It is because readystate change fires multiple times and you expect it to fire once. You would need to check for readystate to be equal to 4 and the status to be 200 (or zero in your case since you are on the file protocol). Or use the onload and onerror events instead.
And if you still get a parsing error than you need to debug what is being returned.
//see what is returned
console.log(xhr.responseText)
//Look to see if you have hidden characters in the file.
console.log(escape(xhr.responseText))
Parsing errors occur either the file you are loading returns something else like an error page OR it has special hidden characters that cause the parser to choke.

Encode string javascript so that it can be transmitted to a server

I'm trying to send json string in the get request to the server, here is how it looks before encoding :
filters={"groupOp":"AND","rules":[{"field":"countrycode","op":"eq","data":"ARG"}]}
Naturally I end up with null pointer when trying to get this json string, then I googled this encodeURIComponent and it partially encodes this string like this :
filters={"groupOp"%3A"AND"%2C"rules"%3A[{"field"%3A"countrycode"%2C"op"%3A"eq"%2C"data"%3A"ARG"}]}
But this is how it supposed to be in order to work :
filters=%7B%22groupOp%22%3A%22AND%22%2C%22rules%22%3A%5B%7B%22field%22%3A%22countrycode%22%2C%22op%22%3A%22eq%22%2C%22data%22%3A%22ARG%22%7D%5D%7D
How do I get this, entirely encoded string so I can read it at server side properly ?
Reason why I used get instead of post
I'm sending this filter(json) content to the server side, web service gets data from the database and returns pdf document.
Using post, I'm able to send correct data and the response is successfully displayed in my firebug console. But I need to return pdf doc to override the current page or open new window/tab and return in that one.
I think you're overworking this problem. Or encoding too many times. Or something.
You've got a JSON string, and you are trying to JSON encode it. That seems...unhelpful.
A better approach might be to produce a Javascript object, then JSON.Stringify that, and then transmit it as a parameter.
var thing = {
groupOp : "AND",
rules : [
{ field : "countrycode", op : "eq", data : "ARG" },
...
],
...
};
var stringrep = JSON.stringify(thing);
// post via jQuery
$.ajax({
type: 'POST',
url: url,
data: stringrep,
dataType: 'json'
success: function() { ... },
});
Normally for a JSON stringified message to or from the server, you'd want to use HTTP POST. HTTP GET puts all "parameters" in the URL; there is no message body. In contrast, HTTP POST allows you to attach a message body to the HTTP message, which can be "anything". With that approach, you don't need to url-encode the quotes and spaces; the JSON message just gets transmitted as the message body of the HTTP message.
HTTP POST is the way applications upload images, or transmit XML documents, and so on. Anything complex gets transmitted via POST.
var filtersParameter = 'filters=' + encodeURI(JSON.stringify(filters));
var filtersParameter = 'filters=' + atob(JSON.stringify(filters));
Note: atob() method uses base64 algorithm to encode the data. This encoded data can be easily passed to a server where it can be decoded using corresponding decoding methods (in python base64.b64decode(encoded_string) is used).

Problems loading JSON code in Python

I've been tyring to figure out how to load JSON objects in Python.
I'm able to send a JSON string to the server, but there it fails.
This is what I'm sending through a websocket with JavaScript:
ws.send('{"test":"test"}');
The server receives it without a problem, but can't validate it:
{"test":"test"}
This is not a JSON object!
Which comes forth from this code:
try:
data = data[:-1]
json.loads(data)
except ValueError:
print 'This is not a JSON object!'
else:
print ('JSON found!')
The data = data[:-1] is there to strip the delimiter sent through the websocket.
import traceback
try:
d = json.loads(data[data.index('{'):-1])
except:
traceback.print_exc()
else:
print(d)
This way only the dictionary part of the data-string is parsed to json.loads().

Categories

Resources