Is it even possible? Im trying to do something like this
function sendToServer(){
var jsonObj = {ip: ip, port: port, stime: stime, maxsamples: maxsamples, dplaces: dplaces};
var jsonStr = JSON.stringify(jsonObj);
console.log(jsonStr);
console.log(jsonObj);
$.ajax({
url: url,
type: "POST",
data: jsonStr,
dataType: "json",
success: function (response){
console.log(response)
},
error: function (xhr,status,error){
alert(error.message);
alert(error.response);
}
});
};
I have no problem with retrieving the data in Python file. I can even modify it and get modified response. But if i try to save what i send I get an error saying "undefined". Both browsers Firefox and Chromium are saying that's error 500.
#!/usr/bin/python3
import cgi, cgitb
import json
import sys
import os
content_len = int(os.environ["CONTENT_LENGTH"])
req_body = sys.stdin.read()
myjson = json.loads(req_body)
# data modification
myjson["ip"] = "do sth"
print('Content-Type: application/json\r\n\r\n')
# 2 troublesome lines
open with("config.json", "w") as file:
file.write(myjson)
print(json.dumps(myjson))
I don't know what am I missing. I guess with flask it would be easier but I need to try it like this. Thanks in advance
It came out that the owner and group of the folder where files were, was wrong. Server should be the owner. So scripts are correct they work properly everything I had to do was type chown in console:/
Related
I am experimenting with Flask and AJAX, I have a simple API route here , hosted at OpenShift. I want to call the API in a Javascript file with Ajax. The OpenShift Python file is simple:
from flask import Flask
app = Flask(__name__)
import json
#app.route('/hello/<name>')
def hello_world(name=None):
str = {'key':'Hello World!', 'q':name}
#out = {'key':str}
res = json.dumps(str)
return res
if __name__ == '__main__':
app.run()
And here is the Ajax call:
$.ajax({
type:"GET",
dataType: "json",
data:'Payam',
url: "http://mypythonapp-spacepirate.rhcloud.com/hello/",
success: function(data){
buf1=data;
console.log(data);
}
})
But this makes a call to this url which results in 404. How can I solve this? Just to mention CORS is not an issue.
http://mypythonapp-spacepirate.rhcloud.com/hello/?Payam
Try changing your url property to
url: "http://mypythonapp-spacepirate.rhcloud.com/hello/world",
Then you will get a 200 response status, instead of the 404. The reason is the flask route you created has a required parameter after the hello/.
edit: followup to question about using variable for the data
method1: just add encode the parameter to the url
url: "http://mypythonapp-spacepirate.rhcloud.com/hello/" + encodeURIComponent(xyz)
method2: use the data parameter to the ajax call as you have started to do. I think that jquery will translate that into the URL query string for a get, like this. Notice the ? delimiting the start of query string:
http://mypythonapp-spacepirate.rhcloud.com/hello/?xyz
You can verify that by checking in your browser dev tools and seeing what URL the ajax call is actually requesting. Also note that in the flask handler you would then need to check for request.query_string to get the data, because <name> parameter would be empty.
Using the guidelines provided by Alex G Rice and the answers here Python Flask how to get parameters from a URL? I found out how to pass the data directly as following:
The Ajax call:
$.ajax({
type:"GET",
dataType: "json",
data:{'name':'Payam'},
url: "http://mypythonapp-spacepirate.rhcloud.com/hello/",
success: function(data){
buf1=data;
console.log(data);
}
})
The python file:
#app.route('/hello/', methods=['GET','POST'])
def hello_world(name=None):
buf1 = request.args.get('name')
str = {'key':'Hello World!', 'q':buf1}
#out = {'key':str}
res = json.dumps(str)
return res
I'm serving a web app made with flask. I just added a feature to make a geocoding request to google using ajax. So, pushing a button calls this function in loc_gm.js:
$(function() {
$('#geo_google').click(function() {
$.ajax({
url: 'geo_gm',
data: $('form').serialize(),
type: 'POST',
success: function(response) {
response = JSON.parse(response)
$('#Lat').val(response['lat']);
$('#Long').val(response['lng']);
},
error: function(error) {
console.log(error);
}
});
});
});
And this is the code in view.py:
#app.route('/geo_gm', methods=('GET', 'POST'))
def geo_gm():
calle1 = request.form['calle1']
calle2 = request.form['calle2']
altura = request.form['altura']
if calle1 and calle2:
address = '{}+y+{},+CABA,+AR'.format(calle1, calle2)
elif calle1 and altura:
address = '{}+{},+CABA,+AR'.format(calle1, altura)
url = 'https://maps.googleapis.com/maps/api/geocode/json?address={}&key={}'.format(address, GOOGLE_KEY)
response = requests.get(url)
result = response.json()
return json.dumps(result['results'][0]['geometry']['location'])
This works in my local machine ( I get the coordinates I want from Google), but when I upload it to the server (Digital Ocean), I get this error in the javascript console:
POST http://192.xx.xx.xxx/geo_gm 404 (NOT FOUND)
Being that IP address the one where my app is hosted.
I know this must be a silly mistake I'm making, but I can't figure it out.
Thanks!
Well, I finally found a workaround.
I added in the html file this:
<input type="hidden" id="geo-gm" name="variable" value="{{ url_for('geo_gm') }}">
That way I can have the relative path to geo_gm function. And then in the js file:
$.ajax({
url: $('#geo-gm').val(),
I did it this way because using {{ url_for('geo_gm') }} directly in the js file didn't work.
Maybe it's not the best way to do it, so if someone has a better way I'll be happy to hear it.
Thanks everybody.
Currently I'm using this function to send my JSON from a chrome extension. This is the client code from javascript sending the data.
function callPython(){
var url = 'http://AWS_IPNUMBER/';
var data = {'bob':'foo','paul':'dog'};
$.ajax({
url: url,
type: 'POST',
contentType:'application/json',
data: JSON.stringify(data),
dataType:'json',
success: function(data){
var jsonObj = $.parseJSON(data);
alert(jsonObj.encPassword);
},
failure: function(errorMsg) {
alert(errorMsg);
}
});
}
This is the server code for Python:
s = socket()
s.bind(('', 80))
s.listen(4)
ns, na = s.accept()
while True:
try:
data = ns.recv(8192)
except:
ns.close()
s.close()
break
data = json.loads(data)
print data
The problem is that although it is listening, data is empty at data = ns.recv(8192). Then data = json.loads(data) doesn't work since data is empty. Why is this? I thought it may be a problem with my security group on AWS but if I go to http://AWS_IPNUMBER/ I get the header from the browser while running the python script.
You may have better luck with a good framework like tornado or django.
I say this because in your code you are trying to parse an http POST with json.loads. HTTP isn't that simple. You will need to deal with the request and headers before you get to the body, and this can be spread out across multiple packets. Why try to reinvent the wheel when you can setup a standards compliant server from a well established project.
The data that $.ajax function will put is a complete HTTP request, which json.loads() won't understand. In this case you need to instantiate a HTTP server which will process the HTTP requests and then process the HTTP payload with json.loads().
I have been having problems with getting AJAX to post JSON correctly. The application is intended to be hosted on Google App Engine. But what I have does not post data.
Python
mainPage = """
<html>
html is included in my python file.
</html>
"""
class JSONInterface(webapp2.RequestHandler):
def post(self):
name =self.request.get('name')
nickname =self.request.get('nickname')
callback = self.request.get('callback')
if len(name) > 0 and len(nickname) >0:
newmsg = Entry(name=name, nickname=nickname)
newmsg.put()
if len(name)>0:
self.response.out.write(getJSONMessages(callback))
else:
self.response.out.write("something didnt work")
def get(self):
callback = self.request.get('callback')
self.response.out.write(getJSONMessages(callback))
This handler is meant to handle the Ajax calls from the web app. I am unsure if I need javascript to be associated with my main page in order to do so, as I haven't found information on it yet with my searches.
Javascript
$(document).ready( function() {
$("#post").bind('click', function(event){
var name = $("#name").val();
var nickname = $("#nickname").val();
postData = {name: name, nickname: nickname, callback: "newMessage"};
$.ajax({
type: "POST",
url: "http://localhost:27080/json",
data: postData,
dataType: "json",
done: function() {
// Clear out the posted message...
$("#nickname").val('');
},
fail: function(e) {
confirm("Error", e.message);
}
});
// prevent default posting of form (since we're making an Ajax call)...
event.preventDefault();
});
The Javascript for the post
Can someone advise me on how I could resolve the problem I am having. Thanks for the time and help.
Did you ask the same question yesterday and then delete it? I swear I just answered the same question.
You're not sending your data as a JSON string. If you want to send as JSON, you need to encode data as a JSON string, or else you're just sending it as a query string.
data: JSON.stringify(postdata),
HOWERVER, your request handler is actually processing the request properly as query string instead of JSON, so you probably don't want to do that.
For starters, the ajax call is pretty close. The full path
"http:://localhost:27080/json"
is not necessary, the relative path will work, but that is not the problem.
Your callback, as it stands, will work as 'success':
success: function(response) {
alert(response);
// Clear out the posted message...
$("#nickname").val('');
}
However, this callback is being phased out in favor of other methods. 'Done' should be chained like so:
$.ajax({
type: "POST",
url: "/json",
data: postData,
dataType: "json"
}).done(function(data){
console.log(data);
});
Also, there might be problems on the server. If you use some logging, you will see that the data is indeed being sent to the server.
import json ## we'll get to this below
import logging
class JSONInterface(webapp2.RequestHandler):
def post(self):
name = self.request.get('name')
logging.info(name) ## will print the value of 'name'
Unless your python function getJSONMessages(callback) is returning a json object, your callback will not be called, even after you add the response parameter.
In your python code:
import json
import logging
class JSONInterface(webapp2.RequestHandler):
def post(self):
callback = self.request.get('callback')
logging.info(callback) # will print correctly
self.response.out.write(json.dumps(callback))
Using the json.dumps method encodes the passing object to json, which is what your ajax object is looking for.
Imagine that you need to write some Javascript that simply changes a set of checkboxes when a drop down list is changed.
Depending on which item is selected in the list, some of the checkboxes will become checked/unchecked.
In the back, you have Python code along with some SQLAlchemy.
The Javascript needs to identify the selected item in the list as usual, send it back to the Python module which will then use the variable in some SQLAlchemy to return a list of checkboxes which need to be checked i.e. "User selected 'Ford', so checkboxes 'Focus', 'Mondeo', 'Fiesta' need to be checked"
The issue Im having is that I cant seem to find a way to access the python modules from the Javascript without turning a div into a mini browser page and passing a url containing variables into it!
Does anyone have any ideas on how this should work?
Funny, I've got web pages with JavaScript that talk to Python CGI modules that use SQLAlchemy.
What I do is send AJAX request but with JSON request in the body instead of XML. Python CGI modules use standard json module to deserialize JSON into a dictionary.
JavaScript side looks like this:
function on_request_success(response) {
console.debug('response', response);
}
function on_request_error(r, text_status, error_thrown) {
console.debug('error', text_status + ", " + error_thrown + ":\n" + r.responseText);
}
var request = { ... };
jQuery.ajax({
url: 'http://host/whatever.cgi',
type: 'POST',
cache: false,
data: JSON.stringify(request),
contentType: 'application/json',
processData: false,
success: on_request_success,
error: on_request_error
});
And Python like this:
request = json.load(sys.stdin)
response = handle_request(request)
print("Content-Type: application/json", end="\n\n")
json.dump(response, sys.stdout, indent=2)
Note, it doesn't use Python cgi module, since the whole request is passed as JSON in the body.
python has a json module, which is a perfect fit for this scenario.
using a good old AJAX, with json as the data format will allow you to exchange data between javascript and your python module.
(unless your python module is running on the client side, but then i don't see how you could execute it from the browser...)
Ajax is a good way to pass variables between python and javascript.
Javascript:
param = {a:'hello', b: 'world', c: '!'}
$.ajax({
type: "post",
url: "scpi.py",
cache: false,
async: 'asynchronous',
dataType: 'html',
data: param,
success: function(data) {
console.log(data)
},
error: function(request, status, error){
console.log("Error: " + error)
}
})
Server.py: (You will need a three functions for this to work)
def do_POST(self):
if "scpi.py" in self.path:
form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={'REQUEST_METHOD': 'POST'}
)
a = form['a'].value
b = form['b'].value
c = form['c'].value
content = myfunction(a, b, c)
self.respond(content)
def handle_http(self, data):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
print(data)
return bytes(str(data), 'UTF-8')
def respond(self, data):
response = self.handle_http(data)
print(data)
FYI: "myfunction(a, b, c,)" is a function from another python file, then return the data and passes to self.respond to send back to javascript