I'm new to frontend development and website development; the goal is to call a webservice method on a server from web interface (client).
Context
I wrote a Python web service with Flask
and I deployed it on my Raspberry Pi. I tested it with ngrok and Postman and it works fine, all the methods do exactly what they have to.
I have also a web server (Nginx) running on the Raspberry.
The Python web service is exposed on port 5000; Raspberry has IP 192.168.1.4.
addWord is a POST
operation provided my the web service.
Finally, PC and Raspberry are on the same network.
Next step
I want to call a method of the Python web service from a frontend website, a simple HTML page, which I put on my web server.
My code
This is the code of my HTML page:
<head>
<title>prova insert</title>
</head>
<body>
<p id='text'></p>
<script>
var xhr = new XMLHttpRequest();
var url = "http://192.168.1.4:5000/addWord";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
console.log(json.email + ", " + json.password);
text = document.getElementById("text");
text.innerHTML = 'Ooooooooooooook';
}
};
var data = JSON.stringify({"ita": "neve", "eng": "snow", "descr": "", "pos":"nome"});
console.log(data);
xhr.send(data);
</script>
</body>
</html>
Flask code:
from flask import Flask
from flask import request
import json
import db_connection
app = Flask(__name__)
@app.route('/test')
def test():
return "Test succeeded."
@app.route('/vocaboli')
def get_vocaboli():
voc = connection.get_all_words()
return json.dumps(voc)
@app.route('/addWord', methods = ['POST'])
def add_word():
data = request.get_json()
print(data)
print(data.get('ita'))
ita = data.get('ita')
eng = data.get('eng')
descr = data.get('descr') # opzionali
pos = data.get('pos')
connection.add_word(ita, eng, descr, pos)
response = dict(correct='ok')
return json.dumps(response)
if __name__ == '__main__':
connection = db_connection.DatabaseConnection()
app.run()
dbconnection.py:
class DatabaseConnection():
def __init__(self):
self.mariadb_connection = mariadb.connect(user=user, password=password, database='vocabulary')
print('Connection succeeded.')
def get_cursor(self):
return self.mariadb_connection.cursor()
def get_all_words(self):
cursor = self.get_cursor()
cursor.execute("select * from vocaboli")
return cursor.fetchall()
def add_word(self, ita, eng, descr=None, pos=None):
cursor = self.get_cursor()
cursor.execute("insert into vocaboli (ita, eng, description, pos) values ('{}', '{}', '{}', '{}')".format(ita, eng, descr, pos))
self.mariadb_connection.commit()
def update_description(self, ita, eng, descr=None):
cursor = self.get_cursor()
cursor.execute("update vocaboli set description = '{}' where ita = '{}' and eng = '{}'".format(descr, ita, eng))
self.mariadb_connection.commit()
I tried also to do POST
on http://192.168.1.4/addWord
, but it returns a NOT FOUND
.
Question
How can I call the web service from the Javascript code in the proper way? Have I to use the ngrok tunnel as URL, or I have to use the IP of the Raspberry?
Have I to use PHP in some way to work on the server side?
As I said, I'm not familiar with Javascript/PHP, probably the answer is straightfoward but I can't figure it out.
By default, the Flask server is only accessible locally. As per the Flask documentation, try specifying host='0.0.0.0'
when running your app to make it accessible from other devices in the network:
if __name__ == '__main__':
connection = db_connection.DatabaseConnection()
app.run(host='0.0.0.0')
Then try displaying the /test
page from a browser on the PC (http://192.168.1.4:5000/test).
If that doesn't do the trick, make sure port 5000 is open on your Raspberry Pi.
Edit addressing the CORS policy error:
Try using the flask_cors module to allow CORS:
from flask import Flask
from flask_cors import CORS
...
app = Flask(__name__)
CORS(app)
...