I have a website that should send a name to a python script (on a third-party website) when a button is pressed. This python script will then make the name uppercase and return it back to the website.
Right now an XMLHttpRequest is correctly being sent when the button is pressed, but I'm unsure how I correctly send the data with the XMLHttpRequest, and then how this data is accessed in the python script.
XMLHttpRequest:
document.getElementById("myButton").addEventListener("click",
function() {
var myRequest = new XMLHttpRequest();
myRequest.open('GET', 'https://example.com/');
myRequest.onreadystatechange = function () {
if (myRequest.readyState === 4) {
alert(myRequest.responseText);
}
}
myRequest.send("Bob"});
}
);
Python script:
from flask import Flask, jsonify
from flask_cors import CORS
from requests import request
app = Flask(__name__)
CORS(app)
#app.route("/", methods=["GET"])
def hello_world():
return jsonify(name = (name_sent_by_XMLHttpRequest).upper()) # Should return "BOB"
if __name__ == '__main__':
app.run()
I know nothing about javascripts' XMLHTTPRequest but at some point, you need to send the name to the python server, right? HOW to do that is up to you, but a GET based option:
GET request with args: https://example.com/?name=your_name_goes_here
in your flask app, the function listening on route "/" will now have access to that arg, something like
name = request.args.get('name', '')
then you can uppercase() it, and return it in some format - probably XML ?
return Response(my_xml, mimetype='text/xml')
Update based on your comment: usually in a flask function, you would use the flask request object to get your URL parameters. In your example, you're importing the requests module as request, not using it, but clobbering the flask.request namesspace. Change your imports to something like this, and it should work normally:
from flask import Flask, jsonify, request
from flask_cors import CORS
import requests
Related
I am following this tutorial to communicate between python and javascript. I am a beginner to this so I dont understand what exactly I am doing wrong.
Following is my code in index.html which sends a POST request to the python server side when the button is clicked:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript">
// setup some JSON to use
var cars = [
{ "make":"Porsche", "model":"911S" },
{ "make":"Mercedes-Benz", "model":"220SE" },
{ "make":"Jaguar","model": "Mark VII" }
];
window.onload = function() {
// setup the button click
document.getElementById("theButton").onclick = function() {
doWork()
};
}
function doWork() {
console.log("posting data")
// ajax the JSON to the server
$.post("receiver", cars, function(){
});
// stop link reloading the page
event.preventDefault();
}
</script>
This will send data using AJAX to Python:<br /><br />
<button type="button" id="theButton">Click Me!</button>
And this is my code on the python side:
import sys
from flask import Flask, render_template, request, redirect, Response
import random, json
app = Flask(__name__)
#app.route('/')
def output():
# serve index template
return render_template('index.html', name='Joe')
#app.route('/receiver', methods = ['GET', 'POST'])
def worker():
print("got some data")
# read json + reply
data = request.get_json()
result = ''
for item in data:
# loop over every row
result += str(item['make']) + ''
return result
if __name__ == '__main__':
app.run()
So, when I press the button in the index.html file, the tutorial says that I will be able to see a server response in the web browser. But even though my server is running, this is what I see in the network tab of developer tools for index.html in the Firefox web browser:
I don't understand what I am doing wrong and how I am supposed to see the communication between the client and server. Any help would be appreciated
Your request is not sending JSON, you have to stringify the cars object to send it as JSON.
function doWork() {
console.log("posting data")
// ajax the JSON to the server
$.post("receiver", JSON.stringify(cars), function(){
}, 'application/json');
// stop link reloading the page
event.preventDefault();
}
I also set the content type to application/json as this is required by request.get_json().
For your network tab issue, you have JS selected so you would not see ajax requests only javascript files. You have to have XHR selected or All.
i wanted to make a small script that download "maps" automatically when the user open the ingame link.
Once the link Open in chrome, the extension get the current URL and send it to python(this is where i'm stuck right now) and then close the tab if successful (since it will fail if the python script isn't running?).
once in python i then proceed to download the map in question and add it to the Songs folder where the only thing he will to do is push F5
right now, i have these pieces of code:
Manifest.json:
{
"name": "Osu!AltDownload",
"version": "1.0",
"description": "A requirement to make osu!AltDownload work",
"permissions": ["tabs","http://localhost:5000/"],
"background": {
"scripts": ["Osu!AltDownload.js"],
"persistant": false
},
"manifest_version": 2
}
Osu!AltDownload.js
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
chrome.tabs.query({active: true, currentWindow: true}, tabs => {
let url = tabs[0].url;
});
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:5000/",true);
xhr.send(url);
}
})
The script that receive the links and download the "maps":
import browser_cookie3
import requests
from bs4 import BeautifulSoup as BS
import re
import os
def maplink(osupath):
link = link #obtain link from POST ?
if link.split("/",4[:4]) == ['https:', '', 'osu.ppy.sh', 'beatmapsets']:
Download_map(osupath, link.split("#osu")[0])
def Download_map(osupath, link):
cj = browser_cookie3.load()
print("Downloading", link)
headers = {"referer": link}
with requests.get(link) as r:
t = BS(r.text, 'html.parser').title.text.split("ยท")[0]
with requests.get(link+"/download", stream=True, cookies=cj, headers=headers) as r:
if r.status_code == 200:
try:
id = re.sub("[^0-9]", "", link)
with open(os.path.abspath(osupath+"/Songs/"+id+" "+t+".osz"), "wb") as otp:
otp.write(r.content)
except:
print("You either aren't connected on osu!'s website or you're limited by the API, in which case you now have to wait 1h and then try again.")
i would like to add in that i used these lines of codes in my extension:
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:5000/",true);
xhr.send(url);
they come from one of my google searches but i don't really understand how i can handle POST request in python with that and i don't even know if i going the right way.
Some may say i haven't done much research at this subject but out of about 50 chrome tabs, i haven't really found anything that would really give me an idea of the right approach for this subject.
You have to run web server to get http requests
You can use Flask for this.
from flask import Flask, request
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
#print(request.form)
print(request.data)
return "OK"
if __name__ == '__main__':
app.run(port=5000)
If you want to send only url then you can use even GET instead of POST and send as
http://localhost:5000/?data=your_url
where your_url is what you get with tab[0].url.
xhr.open("GET", "http://localhost:5000/?data=" + url, true);
xhr.send(); // or maybe xhr.send(null);
And then you can get it with
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def index():
print(request.args.get('data'))
return "OK"
if __name__ == '__main__':
app.run(port=5000)
EDIT:
Example which tests Flask using directly JavaScript when you visit http://localhost:5000/test
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def index():
print(request.args.get('data'))
return "OK"
#app.route('/test/')
def test():
return """
<script>
var url = "https://stackoverflow.com/questions/65867136/need-help-about-sending-variable-from-chrome-extension-to-python/";
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://localhost:5000/?data=" + url, true);
xhr.send();
</script>
"""
if __name__ == '__main__':
app.run(port=5000)
Eventually I can test it with bookmarklet
javascript:{window.location='http://localhost:5000/?data='+encodeURIComponent(window.location.href)}
which I put as url in bookmark in favorites - but this reload page
or using modern fetch() (instead of old XMLHttpRequest()) and it doesn't reload page.
javascript:{fetch('http://localhost:5000/?data='+encodeURIComponent(window.location.href))}
I have an old application based on Python SimpleHTTPServer that I'm trying to convert to Flask.
In the old application, I had an HTML form that was submitting a POST request to the SimpleHTTPServer. The form also had an iframe. There, I had a do_POST method that was reading the values in the text boxes and producing some results. I then wrapped the results into a JSON object and wrote to the wfile method of SIMPLEHTTPServer. This caused the result to get populated into the iframe. The iframe had an onload method on the JS side and here, the results would be read from it and populated into various text-boxes.
I now want to convert this to Flask from SimpleHTTPServer. What is the best way to translate the logic I have in place to Flask? Basically, what is the equivalent of writing to the wfile object?
Also, on the Flask side, I also have some #app.route methods where I can form a URL with input parameters and get the results as JSON objects (example: http://localhost/calculate?input1=3&input2=5). Is it possible to leverage these URLs instead of the POST request to get the result into JavaScript?
Here is hello world of flask to get the data from URL parameters and do the stuff and return a json
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route('/')
def hello_world():
param1 = request.args.get('param1')
param2 = request.args.get('param2')
res = param1 + param2
return jsonify({
"result": res
})
if __name__ == '__main__':
app.run()
example request
GET http://127.0.0.1:5000/?param1=hi¶m2=there
Example response
{
"result": "hithere"
}
I have setup a simple flask server using the following code:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
#app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
if __name__ == '__main__':
app.run(host = '0.0.0.0', port='5000')
From js I am making a request to the address using the follwing code
const theUrl="<myip>:5000/";
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false);
xmlHttp.send();
console.log(xmlHttp.response);
The console shows
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <title>404 Not Found</title> <h1>Not Found</h1> <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
When I try to access the same url from the browser, it returns
Hello, cross-origin-world!
Is there something wrong I am doing with the server? I have tried the js code on a dummy address and I am able to get the contents of that website. There is something wrong with the Flask server.
Just wrote something for file uploads.
Hope this helps.
$('.custom-file-input').change(function () {
console.log($(this)[0].files[0].name);
$('.custom-file-label').text($(this)[0].files[0].name);
var formData = new FormData();
formData.append('file', $(this)[0].files[0]);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/', true);
xhr.send(formData)
I don't understand why one would use XHR for get requests, couldn't you just use Ajax instead?
The last parameter is whether the connection is asynchronous. Perhaps that's what wrong?
Also, don't use Flask built-in webserver for production environment, it just isn't made to cope with more than one user testing for example.
Furthermore, perhaps someone can tell me why not, however, I think you would be better off simply having url as the section of the url after the port declaration, in my example, notice that I only tell jquery or js to post data to / and this is because that means local server, or is interpreted to mean itself, so by default is prepended with your server IP and in this case the port 5000 aswell
I have looked all over Stack Overflow but I have not found an answer to this question.
How can a python script dynamically receive a url based on a javascript function call?
For example, in this Stack Overflow question (Code reproduced below) how could I dynamically receive the url (which is hardcoded in this case) if the name of the python file was abc.py and I called
xhttp = new XMLHttpRequest(); and then
xhttp.open("GET", "abc.py?token=123", true); in some html file with javascript?
from urllib.parse import urlparse
from urllib.parse import parse_qs
from urllib.parse import urlencode
url = 'http://example.com?param1=a&token=TOKEN_TO_REPLACE¶m2=c'
o = urlparse(url)
query = parse_qs(o.query)
if query.get('token'):
query['token'] = ['NEW_TOKEN', ]
new_query = urlencode(query, doseq=True)
url.split('?')[0] + '?' + new_query
>>> http://example.com?param2=c¶m1=a&token=NEW_TOKEN
You need to use framework to do this, python script alone with no networking/socket functionality could not communicate with the front-end (js side), below is a simple backend to received your javascript request using bottle.py
Here is a simple implementation that receives a POST request from client and do the logic you need, updated url is returned to the calling code.
Note the request is POST and the data is json with the token and url
from bottle import post, run, request
import json
from urllib.parse import urlparse
from urllib.parse import parse_qs
from urllib.parse import urlencode
def replace_token(data):
url = data['url']
token = data['token']
o = urlparse(url)
query = parse_qs(o.query)
if query.get('token'):
query['token'] = [token]
new_query = urlencode(query, doseq=True)
return url.split('?')[0] + '?' + new_query
#post('/token')
def index():
data = json.load(request.body)
return replace_token(data)
run(host='localhost', port=8080, debug=True)
Then you can test it by simple using a curl
curl -X POST http://localhost:8080/token -d '{"token":"NEW_TOKEN", "url":"http://example.com?param1=a&token=TOKEN_TO_REPLACE¶m2=c"}'