I'm working on a Python API to handle REST calls to MongoDB. The API is based on Kule (and thus includes Bottle and PyMongo modules). The front-end is built using node.js. I have been developing and testing on localhost with the API, front-end, and MongoDB on different ports.
I have set up the API and have been trying to get CRUD requests to work. I can get these to work from a Python script as well as from Javascript running on Apache server. However, when I add the same code to the front-end, GET works, but POST fails with a 500 error.
This POST code works on the Apache server:
var myrequest=new XMLHttpRequest();
myrequest.onreadystatechange=function(){
if (myrequest.readyState==4){
if (myrequest.status==201){
alert(myrequest.responseText);
} else{
alert("An error has occured making the request");
}
}
}
myrequest.open("POST", "http://localhost:8080/items", true);
myrequest.setRequestHeader("Content-type", "application/json;charset=UTF-8");
myrequest.send(JSON.stringify({'name' : 'Name', 'description' : 'Description'}));
When I add this to the front-end, I get the following traceback from Kule:
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\bottle.py", line 764, in _handle
return route.call(**args)
File "C:\Python27\lib\site-packages\bottle.py", line 1625, in wrapper
rv = callback(*a, **ka)
File "C:\Python27\lib\site-packages\bottle.py", line 1575, in wrapper
rv = callback(*a, **ka)
File "C:\Python27\lib\site-packages\kule\kule.py", line 64, in post_list
inserted = collection.insert(request.json)
File "C:\Python27\lib\site-packages\pymongo\collection.py", line 351, in insert
docs = [self.__database._fix_incoming(doc, self) for doc in docs]
TypeError: 'NoneType' object is not iterable
127.0.0.1 - - [24/Jun/2014 07:53:40] "POST /scenarios HTTP/1.1" 500 50
So, what am I doing wrong? Why does the Javascript break in node.js? I have GET working, but POST fails. Why?
Thanks!
I found my error.
myrequest.setRequestHeader("Content-type", "application/json;charset=UTF-8");
"Content-type" should be "Content-Type" with an upercase "T".
Silly mistake. Left as a note to others.
Related
So I'm trying to use Axios to fetch some data before the test begins.
the test step is defined as follows
const axios = require('axios');
step("GET google", async function() {
await axios.get("https://www.google.com/")
});
And I have a test spec that looks like this
# Getting Started with Gauge
## GET google
* GET google
This is on a fresh Taiko/Gauge project. When running gauge runs specs I get the following error
Installing required plugins.
# Getting Started with Gauge
## GET google F
Failed Step: GET google
Specification: specs\test.spec:6
Error Message: AxiosError: Request failed with status code 400
Stacktrace:
And nothing else happens
I have a JavaScript application which is running in Node.js environment and communicates to its clients ( also in JavaScript ) using a ZeroMQ. The messages come on the server in JSON format.
The application code throws it out
Node.js SyntaxError: Unexpected token in JSON at position 0
when it is parsed using JSON.parse(). I'm unable to figure out the issue. I've verified the JSON using http://jsonlint.com
Any help with JSON.parse() is welcome.
Edited:01/10/17, 15:33
Here are the client and server JavaScript code files. You'll need to create the .js files, can't post such a big code.
The JSON data file is also provided.
You'll need to launch the server.js and client.js and then the server console will print out the exception for unrecognized character.
https://www.4shared.com/folder/6VFJqrgU/javascript.html
Stackoverflow imposes link posting restrictions so had to post one link with all the files.
Just for info, I'm a C++ programmer, so don't bother about the code formatting or style of programming. I had to do it for a project need.
Edit 02/10/17, 11:50: Well it turns out that it is the JSON.parse() method which is unable to parse the json. But, I added a .trim() call to the args[1].toString() and the error has moved downstream. Unexpected token o in JSON at position 10. I don't understand what is wrong!!
Edit 04/10/17: Here is the minimal code.
var fs = require('fs');
try
{
var event = fs.readFileSync('demoReport.json', 'utf8');
console.log(event);
var eventObj = JSON.parse(event);
var reportName = event["ReportName"];
var reportData = event["ReportData"];
console.log(reportData);
}
catch(error)
{
console.log("JSON parsing failed: " + error);
}
This is the json:
{"EventName":"ReportGenEvent","TemplateFileNameLocation":"File location","ReportFormat":".pdf","ReportName":"TestReport","ReportLocation":"report location","Locale":"French","ReportData":{"dateTime":"2017-09-29T00:05:22.824Z","streamName":"","measurementTime":"2017-04-01T01:13:25.000Z","durationSeconds":0.0,"outOfBand":false,"notFinal":false,"newMeasurement":false,"savedFileName":"","measurementType":"Unknown","analysisElapsedSeconds":1.3462,"analysisElapsedCPUSecs":0.0624004,"geometryID":"GEOM","geometryDescription":"","measurementUUID":"6060c80f-007c-4992-88f8-55e2200d99b7","backgroundUUID":"","measurementWorkflowID":"Measurement","instrumentProperties":{"classCode":8,"description":"","manufacturer":"","model":"","properties":"locationName=Home latitude=25 longitude=20 elevation=30","serialNumber":"product/1","versionInformation":"=V1.0"}}}
Thanks.
Overview of the problem
I am running a webpage and an API written in python. The webpage sends some data to the python API in a POST request, which processes it and sends it back. The API works fine with curl requests and console AJAX requests. However, when I load the webpage in a new tab, all POST requests for the first 10 seconds or so are ‘stalled’ (not carried out by Chrome) until they fail. After around 10 seconds POST requests work fine, and the python API catches a broken pipe (ERRNO 32, logs below). If I hard refresh the tab, then the site immediately works and the request isn’t stalled at all, however if I open a new tab with the site in then again there’s this 10 second delay.
Specifics
This only happens on Chrome, it works fine on Firefox and Safari. I have run the API and the webpage on both localhost and an AWS instance, and there is still the ~10 second delay, after which it works fine. It happens on chrome on other computers and works on Firefox on other computers.
How I've tried to fix it
Chrome apparently stalls requests when its either negotiating a proxy connection or reaches its limit of 6 TCP connections. I don’t know why doing a hard-reset wouldn’t cause it to have to re-negotiate its connection to the API, or why it wouldn’t have to do that each time. Even if it is doing that, its shouldn’t consistently take around ~10 seconds should it? I’ve also ensured that the site is not reaching 6 TCP connections.
Potential problem?
I have no problems with the HTTP request stalling if I change the request to be from another site, and this issue is specific to Chrome, so I’m wondering if Chrome implements XMLHTTPRequests in a way that BaseHTTPRequests doesn’t know how to deal with, and that’s leading to the broken pipe. But I don’t know why it always fixes itself after ~10 seconds each time.
I’ve spent many hours on this now, any help would be massively appreciated please!
HTML/JS:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>OSR Web</title>
</head>
<body>
<script>
var http = new XMLHttpRequest();
var url = "http://localhost:1234";
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
var bestGuess = http.responseText;
console.log(bestGuess);
}
}
document.addEventListener("click", function(event){
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.send("TestData");
});
</script>
</body>
</html>
Python API:
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
class S(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
def do_GET(self):
self._set_headers()
self.wfile.write("OSR API Active")
def do_POST(self):
print "received"
self._set_headers()
self.data_string = self.rfile.read(int(self.headers['Content-Length']))
inputData = self.data_string
print inputData
self.wfile.write("Received\n")
def run(server_class=HTTPServer, handler_class=S, port=1234):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print 'Starting HTTPD'
httpd.serve_forever()
run()
Broken pipe error message:
127.0.0.1 - - [11/Aug/2017 15:34:13] "GET / HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 56506)
Traceback (most recent call last):
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 321, in process_request
self.finish_request(request, client_address)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 657, in __init__
self.finish()
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 716, in finish
self.wfile.close()
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 283, in close
self.flush()
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 307, in flush
self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------
received
127.0.0.1 - - [11/Aug/2017 15:36:45] "POST / HTTP/1.1" 200 -
TestData
Screenshot of the chrome network tools
I followed the docs on the websocket-rails github wiki page, but couldn't overcome this difficulty, I get this error with chrome:
WebSocket connection to 'ws://0.0.0.0:3000/websocket' failed: Error during WebSocket handshake: Unexpected response code: 301
I installed the websocket-rails gem, generated the install, I set successfully config.middleware.delete Rack::Lock in development.rb; I'm using Rails 4.
I got in the view:
<script type="text/javascript">
var dispatcher = new WebSocketRails('0.0.0.0:3000/websocket');
</script>
I got in my chat_controller.rb:
class ChatController < WebsocketRails::BaseController
def initialize_session
puts "Session Initialized"
end
def user_connected
puts 'user connected'
end
end
in my events.rb:
WebsocketRails::EventMap.describe do
subscribe :client_connected, :to => ChatController, :with_method => :user_connected
end
As you can see, my goal is to display "Session Initialized", and "user connected", in my thin server console each time that someone goes on a page. Between, I run the server with bundle exec thin start, but I got a javascript error instead (websocket connection failed error 301).
Thanks to the members of the Websocket Rails IRC, I found out that in my route, I was appending the locale before every path, so it coudln't find it.
Check your routes.rb if someone hit that issue too !
I am having a problem similar to socket.io issue using sails.js. Every once in a while (once per day, or even few hours, it varies), a visitor to the web site/app will crash Node, seemingly due to the way his websocket client tries to connect. Anyway, here's the crash log:
debug: Lowering sails...
/Volumes/Two/Sites/lsdfinder/node_modules/sails/node_modules/express/node_modules/connect/lib/utils.js:216
return 0 == str.indexOf('s:')
^
TypeError: Cannot call method 'indexOf' of undefined
at exports.parseSignedCookie (/Volumes/Two/Sites/lsdfinder/node_modules/sails/node_modules/express/node_modules/connect/lib/utils.js:216:19)
at Manager.socketAttemptingToConnect (/Volumes/Two/Sites/lsdfinder/node_modules/sails/lib/hooks/sockets/authorization.js:35:26)
at Manager.authorize (/Volumes/Two/Sites/lsdfinder/node_modules/sails/node_modules/socket.io/lib/manager.js:910:31)
at Manager.handleHandshake (/Volumes/Two/Sites/lsdfinder/node_modules/sails/node_modules/socket.io/lib/manager.js:786:8)
at Manager.handleRequest (/Volumes/Two/Sites/lsdfinder/node_modules/sails/node_modules/socket.io/lib/manager.js:593:12)
at Server.<anonymous> (/Volumes/Two/Sites/lsdfinder/node_modules/sails/node_modules/socket.io/lib/manager.js:119:10)
at Server.EventEmitter.emit (events.js:98:17)
at HTTPParser.parser.onIncoming (http.js:2076:12)
at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:120:23)
at Socket.socket.ondata (http.js:1966:22)
9 Oct 10:42:24 - [nodemon] app crashed - waiting for file changes before starting...
In config/sockets.js, authorization is set to true. Not sure what else to do, where to fix this. Any suggestions? I can read the Sails docs too, but this appears to be a problem in Express/Connect, no? Thanks.
...René
The problem is that once every so often, a client will connect that has no cookies. Sails.js is using util.parseSignedCookie() from Connect without checking for errors, and therefore an error is thrown. This is what it looks like in Sails:
if (handshake.headers.cookie) {
handshake.cookie = cookie.parse(handshake.headers.cookie);
handshake.sessionID = parseSignedCookie(handshake.cookie[sails.config.session.key], sails.config.session.secret);
}
If you take a look into the cookieParser() middleware of Connect, you can see error checking is required:
if (cookies) {
try {
req.cookies = cookie.parse(cookies);
if (secret) {
req.signedCookies = utils.parseSignedCookies(req.cookies, secret);
req.signedCookies = utils.parseJSONCookies(req.signedCookies);
}
req.cookies = utils.parseJSONCookies(req.cookies);
} catch (err) {
err.status = 400;
return next(err);
}
}
I've created a Gist here that fixes the problem, and will submit a pull request to Sails.js when I have the time. The Gist uses Connect's cookieParser() middleware to automatically handle errors. If you want to use this, modify this file in your modules folder:
node_modules/sails/lib/hooks/sockets/authorization.js
If you are doing a crossdomain request, you could turn off authorization.
In *site_dir/config/sockets.js* set authorization to false. One way of doing it. You can also call your api with something like this
bash
**http://localhost:1337?cookie=smokeybear**
Its is in the comments on the sockets.js file.