http post a base64 json request between Node.js and Python Flask server but Node received an incomplete json - python

I try to send a base64 json form node.js server to python flask server and than return a same base64 code back to node.js server. Flask can successfully receive my json but when it response to node and node try to print out the response. I got a error message say: "Unexpected end of JSON input". I found the reason is node server can not receive the base64 completely. It just only receive a small portion. What is the problem? Is post request has a string limit?
I tested when I change the base64 code to a short string. Node server can receive response normally.
Anyone can help me? Thank you.
This is my code:
<<< Node.js Server >>>
var express = require('express');
var http = require('http');
var app = express();
app.get('/', (req, res) => res.send('Hello World!'));
app.listen(10000, () => console.log('Running on http://localhost:10000'));
postData = JSON.stringify({
'code': <base64 code or short string here>
});
var options = {
hostname: 'localhost',
port: 10001,
path: '/test',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
};
var req = http.request(options, (res) => {
res.on('data', (chunk) => {
var data = JSON.parse(chunk);
console.log(data.message);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
req.write(postData);
req.end();
<<< Python Flask Server >>>
from flask import Flask
from flask import request
from flask import jsonify
app = Flask(__name__)
#app.route('/test', methods=['POST'])
def test():
request_data = request.get_json()
print(request_data['code'])
return jsonify(
message = request_data['code']
)
app.run(host='localhost', port=10001)

In NodeJS code, in data event, you will get chunk data(partial data), you need to wait until end event and then parse, following example may help you
var req = http.request(options, (res) => {
var data = '';
res.on('data', (chunk) => {
data += chunk.toString(); // buffer to string
});
res.on('end', () => {
data = JSON.parse(data);
console.log(data.message);
console.log('No more data in response.');
});
});

Related

Fetch JSON.parse: unexpected end of data at line 1 column 1 of the JSON data fast api

Hi i got a python fast api backend server.
#app.get("/getName")
async def getName() -> JSONResponse:
data_sniffer = DataSniffer()
data = json.dumps(data_sniffer.get_data())
print(data)
return JSONResponse(content=data,headers={'content-type':'application/json'})
this is the console output of data :{"first_name": "test"}
My Frontend Code looks like this
useEffect(() => {
async function query() {
const options = {
method: 'GET',
mode: 'no-cors',
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application-json',
},
};
const res = await fetch('http://127.0.0.1:3000/getName', options);
console.log(res);
const data = await res.json();
console.log(data);
}
query();
});
but i get following error message SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
my network response looks like this:
"{"first_name": "test"}"
Has anyone a clue why fetch cant parse the json?
For anyone who has the same issue what worked for me is I moved my Backend folder to the root directory of my Frontend and removed the mode no-cors of the fetch request. I installed the no cors app and now it works. I think the mode no-cors broke my request.

How to print data in an Axios call to flask

Hi there I am doing a project with a React Frontend and Flask Backend. I am using axios to make calls from the Frontend to the Backend, but I am having trouble accessing the data I am sending with my request. I have tried several different methods of accessing the data but have no luck printing my variables.
Here is my flask endpoint:
#app.route('/login')
#cross_origin()
def login():
print(request.data)
return "Hello World"
Here is my axios call:
let options = {
method: 'GET',
url: flaskEndpoint+ "/login",
data: JSON.stringify(loginData),
// crossOrigin:'Access-Control-Allow-Origin',
crossOrigin:'*',
headers: {
'Content-Type': 'application/json'
},
json: true
}
console.log(JSON.stringify(loginData))
axios(options)
.then(response => {
console.log(response);
// this.setState({
//
// })
setAuth(true);
Cookies.set("user", "loginTrue");
})
.catch(error => {
console.log("Error in the axios call:" + error);
})
}
And here is the result in the flask terminal:
What am I doing wrong and is there a better way?
So I should have used "print(request.json)" instead. Then I could access the data being sent, or use "request.json.get('username')" to get a particular value.

Python SocketIO-client doesn't receive emits from nodeJS server

So this is what I am trying to do, I want to be able to send a message in a browser towards a python script. I've got to the point where I can send a message in the browser and the server sees it. For testing purposes I used io.emit('input', data) to send the data towards my python script but nothing happens on the python side.
script.py:
import socketio
sio = socketio.Client()
#sio.event
def connect():
print('connected')
#sio.on("input")
def on_input(key):
print(key)
sio.connect('http://192.168.2.9:5000', namespaces=['/justin'])
server.js:
const express = require('express')
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
var justin = null;
app.use(express.static('public'));
io.of('/justin').on('connection', function(socket){
console.log('justin connected');
justin = socket;
});
io.on('connection', function(socket){
console.log('a user connected');
socket.on('event', (data) => {
io.emit('input', data)
})
socket.on('disconnect', () => {
//
})
});
http.listen(5000, function(){
console.log('listening on *:5000');
});
Is there something I'm not seeing or is this just not possible?
Thanks in advance!

django saving messages to database via node server and socket.io

I have node server:
var http = require('http');
var server = http.createServer().listen(4000);
var io = require('socket.io').listen(server);
var cookie_reader = require('cookie');
var querystring = require('querystring');
var redis = require('redis');
var sub = redis.createClient();
//Subscribe to the Redis chat channel
sub.subscribe('chat');
//Configure socket.io to store cookie set by Django
io.use(function(){
io.set('authorization', function(data, accept){
if(data.headers.cookie){
data.cookie = cookie_reader.parse(data.headers.cookie);
return accept(null, true);
}
return accept('error', false);
});
io.set('log level', 1);
});
io.sockets.on('connection', function (socket) {
//Grab message from Redis and send to client
sub.on('message', function(channel, message){
socket.send(message);
});
//Client is sending message through socket.io
socket.on('send_message', function (message) {
values = querystring.stringify({
comment: message,
sessionid: socket.handshake.cookie['sessionid'],
});
var options = {
host: 'localhost',
port: 8000,
path: '/node_api',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': values.length
}
};
//Send message to Django server
var req = http.request(options, function(res){
res.setEncoding('utf8');
//Print out error message
res.on('data', function(message){
if(message != 'Everything worked :)'){
console.log('Message: ' + message);
}
});
});
req.write(values);
req.end();
});
});
When I send message it does not save in the database..
Here is my view for django:
#csrf_exempt
def node_api(request):
print "inside node"
try:
print "inside try"
session = Session.objects.get(session_key=request.POST.get("sessionid"))
print "first"
user_id = session.get_decode().get("_auth_user_id")
print user_id
user = User.objects.get(id=user_id)
Comments.objects.create(user=user, text=request.POST.get("comment"))
r = redis.StrictRedis(host="localhost", port=6379, db=0)
r.publish("chat", user.username + ": " + request.POST.get("comment"))
return HttpResponse("Everything worked :")
except Exception, e:
return HttpResponseServerError(str(e))
Whats wrong in here??
Can anyone guide me to right direction?
When I go to '/node_api/' url it says Session matching query doesnot exist..
My view for displaying message:
#login_required
def home(request):
print "entered"
comments = Comments.objects.select_related().all()[0:100]
return render(request, "index.html", locals())
When I submit the message its not saving to database neither displaying...
Thanx in advance??
If you are using python then why don't you try python way of doing realtime.
Try tornado with django. It supports socket.io..
You can code in python with no difficulty.
It doesn't mean javascript is not good but try do in python and have a look at tornado, redis, django. YOu will find your solution.

Is it OK to pass both token and client_id to the client when Channel API is used?

I need to create an application, where GAE server will always talk with just one client (i.e. one message should be always sent just to one client).
I do the following -
Python:
def get(self):
# generate token, when page is loaded
client_id = uuid.uuid4().hex
token = channel.create_channel(client_id)
template_values = {'token': token,
'client_id': client_id
}
self.response.out.write(template.render('page.html', template_values))
def post(self):
# reply to the client
...
client_id = self.request.get('id')
channel.send_message(client_id, message)
Javascript:
sendMessage = function(field) {
$.ajax({
type: "POST",
url: "/",
data: "f=" + field + "&id=" + "{{ client_id }}", // WARNING!
contentType: "application/x-www-form-urlencoded",
success: function(data) {
}
});
};
onOpened = function() {
connected = true;
sendMessage('opened');
};
onMessage = function(msg) {
alert(msg.data);
};
onError = function(err) {
alert(err);
};
onClose = function() {
alert("close");
};
// open new session
channel = new goog.appengine.Channel('{{ token }}'); // WARNING!
socket = channel.open();
socket.onopen = onOpened;
socket.onmessage = onMessage;
socket.onerror = onError;
socket.onclose = onClose;
It works well, but with such scenario both token and client_id are passed to the client. Is it OK?
There's no technical reason not to do this. If you're worried about security, the token is far more valuable: an attacker who could listen to your traffic could take the token and listen to channel messages in a different context. The clientid wouldn't let them do that.
But I do have a question: why not return the message in the POST response, rather than sending a message over the channel? Or is the sample code just simplified for the example?

Categories