flask + ngrok - redirect doesn't work - python

I've got the following app:
server.py
#app.route('/')
def main():
return render_template('index.html')
#app.route('/login')
def login():
return 'hey'
index.html
<body>
<form action="http://localhost:5000/login" , method="post">
<input type="submit" value="submit">
</body>
Now I run ngrok:
ngrok http 5000
After typing address (generated by ngrok) into web browser I can see index.html page with button, but when I press the button it redirects me to http://localhost:5000/login where I can see: "connection refused".
My question is how to set ngrok and flask server the way they can communicate?
P.S. I've put only a part of my code just for better reading

Btw, I've figured out how to make it other way. After running command:
ngrok http 5000
I get ngrok address thanks to this python script:
import json
import os
def get_ngrok_address():
os.system("curl http://localhost:4040/api/tunnels > tunnels.json")
with open('tunnels.json') as data_file:
datajson = json.load(data_file)
return dict(zip(['http', 'https'], [i['public_url'] for i in datajson['tunnels']]))
It just gets json object and converts it to python dict:
'http' -> ngrok_http_address
'https' -> ngrok_https_address
Before server start I pass generated address to all html templates e.x.:
<body>
<form action="{{ ngrok_address }}/login", method="post">
<input type="submit" value="submit">
</body>

What happens if you add the POST method to the login route
#app.route('/login', methods=['POST'])
def login():
return 'hey'
and change the form action to
<body>
<form action="/login", method="post">
<input type="submit" value="submit">
</body>
hm?

Try to change your host of application.
app.run(host='0.0.0.0')
and then run the command ngrok http 5000
also add POST method for the your route.
#app.route('/login', methods=['POST'])
def login():
return 'hey'

Try Flask-PyNgrok to use ngrok as flask application extension.

Related

cannot get html front end to pass input to python script using flask

So, I am building a webapp which takes a link from a shopping website then runs it through a python script which interprets the data, stores it in a database and that populates a table for reference.
I am running into a couple issues:
if I put the link into the front end input (html) then submit it just takes me to "page isn't working HTTP error 405". I'm not sure what to do about that one.
the more pressing issue is that even though I believe I routed the input properly through flask I get this issue when I run the python script alongside the frontend
"RuntimeError: Working outside of request context."
I tried some of the advice mentioned in these existing posts to no avail:
Sending data from HTML form to a Python script in Flask
Connecting python script with html button and flask
I also tried changing the script itself to use getvalue() instead of getvalue when associating it as an input variable for the python script to work with.
this is my route code from app.py
#app.route("/", methods=['POST'])
def getvalue():
HTML_Info = request.form['data_bridge']
return HTML_Info
code for the HTML input
<form name="passdata" action="{{ url_for('getvalue') }}" method="POST">
<input type='text' name="data_bridge" placeholder="paste shoe link here">
<input type="submit">
</form>
and the python code just imports the app file and the getvalue function and then assigns it to a variable.
if you guys could help me sort this out I would greatly appreciate it.
I assume you want to take an input (e.g. shoe link) from the user and then do some operations based on the input.
To access the HTML form from / path you need to enable both GET and POST requests in that route. Otherwise, when you try to access the root path / from your browser, you will get the HTTP Method not allowed error.
app.py:
from flask import Flask, render_template, request
app = Flask(__name__)
def get_value_related_info(value):
return f"You have entered {value}"
#app.route('/', methods=['POST', 'GET'])
def getvalue():
if request.method == "POST":
HTML_Info = request.form['data_bridge']
return get_value_related_info(HTML_Info)
return render_template('form.html', text="")
if __name__ == "__main__":
app.run(debug=True)
Output:
Before form submission:
After form submission:
templates/form.html:
<html>
<head>
<title>Form example</title>
</head>
<body>
<form name="passdata" action="{{ url_for('getvalue') }}" method="POST">
<input type='text' name="data_bridge" placeholder="paste shoe link here">
<input type="submit">
</form>
</body>
</html>
Explanation:
I have mocked the functionality on the user input in get_value_related_info method.
References:
Flask documentation for request object

How to use recaptcha without Flask-WTF

I have been making a file sharing website for quite a while and I want to implement recaptcha when people register to the website. The problem is that I can't use Flask-WTF because I will have to change a lot of my code (I have been programming without it).
I have found this Flask recaptcha that doesn't include the use of Flask-WTF but I can't seem to make it work (it doesn't show the recaptcha itself):
https://github.com/mardix/flask-recaptcha
I have followed step by step and still, it doesn't work. The only thing that I didn't do is the config.
EDIT:
The captcha is not working. Everytime that I enter the right info for the registration and mark the captcha, it says that the username/password is incorrect. If I don't mark it, it does the same.
Here is the captcha code (the others worked before):
recaptcha = ReCaptcha(app=app)
if recaptcha.verify() is False:
flash('Captcha is incorrect')
return redirect(url_for('register'))
<div id="captcha"">
{{ recaptcha }} - HTML PART
</div>
EDIT: After getting help from Nurzhan, I have changed the code and the captcha always returns false, no matter what.
You didn't try the config, but you need to indicate the keys in order to make your recaptcha work. These 2 options are NOT optional in the config:
RECAPTCHA_SITE_KEY : Public key
RECAPTCHA_SECRET_KEY: Private key
Set them with proper values and it see if it works.
EDIT:
It's working now. This is app.py:
import requests
import json
from flask import Flask, render_template, request
from flask_recaptcha import ReCaptcha
app = Flask(__name__)
app.config.update({'RECAPTCHA_ENABLED': True,
'RECAPTCHA_SITE_KEY':
'site_key',
'RECAPTCHA_SECRET_KEY':
'secret_key'})
recaptcha = ReCaptcha(app=app)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/submit', methods=['GET', 'POST'])
def submit():
print('SUBMIT CALLED')
username = ''
password = ''
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
print(request.form)
if username == 'username' and password == 'password':
print('CREDENTIALS ARE OK')
r = requests.post('https://www.google.com/recaptcha/api/siteverify',
data = {'secret' :
'secret_key',
'response' :
request.form['g-recaptcha-response']})
google_response = json.loads(r.text)
print('JSON: ', google_response)
if google_response['success']:
print('SUCCESS')
return render_template('profile.html')
else:
# FAILED
print('FAILED')
return render_template('index.html')
# if recaptcha.verify():
# # SUCCESS
app.run(debug=True)
This is the index.html page:
<!DOCTYPE html>
<html>
<head>
<script src='https://www.google.com/recaptcha/api.js'></script>
</head>
<body>
<h1>Flask Recaptcha</h1>
<p>Flask Recaptcha Test</p>
<form method="post" action="/submit">
Username:<br>
<input type="text" name="username"><br>
Password:<br>
<input type="password" name="password">
{{ recaptcha }}
<input type="submit" value="Submit">
<div class="g-recaptcha" data-sitekey="site_key"></div>
</form>
</body>
</html>
This is the profile.html page if you pass the validation:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Profile page</h1>
<p>Registration is ok</p>
</body>
</html>
I couldn't make recaptcha.verify() work. In the official docs of Google Recaptcha it is stated that you need to send a post request to google recaptcha api separately after the client submits your form with your secret_key and g-recaptcha-response which you receive when user puts a tick in recaptcha.
Note that this is just an example code. You need to add your own site_key and secret_key to the app.py and index.html and also add a proper checking of user credentials for the registation like double entering password etc.

Python Tornado XSRF cookie issue with Chrome

I am new to Tornado and I am trying to build a very simple login form with xsrf cookie.
Code as below:
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html")
def post(self):
self.write("You ahve submitted the form.!")
class App(tornado.web.Application):
def __init__(self):
handlers = [
(r"/", MainHandler),
]
settings = dict(xsrf_cookies=True)
tornado.web.Application.__init__(self, handlers, **settings)
if __name__ == "__main__":
app = App()
server = tornado.httpserver.HTTPServer(app)
server.listen(7001)
tornado.ioloop.IOLoop.current().start()
The form is also very simple:
<html>
<head><title>Text XSRF</title></head>
<body>
<form method="post">
{% module xsrf_form_html() %}
{% raw xsrf_form_html() %}
Username:<input type="text" name="username">
Password:<input type="password" name="pwd">
<input type="submit" value="submit">
</form>
</body>
</body>
</html>
I am adding to the host file a domain:
127.0.0.1 xsrf.test.com
And when I open Chrome and type in hxxp://xsrf.test.com:7001, I can see the login form, but when sending the POST request I get a
403 (XSRF cookie does not match POST argument)
However, if I hit hxxp://localhost:7001, I can submit the form as expected. IE and Safari works fine for both domains. So I am wondering is there anything I did wrong to make this work using "xsrf.test.com" in Chrome?
I did check Chrome->Settings->Content Settings->Cookies->Allow local data to be set is properly selected.

Flask not activating function

I've been using python flask as well as html, in order to create a small website, (just as a hobby while I'm off school), I created a form in html, and saved it within the templates folder of the project. I also then added a function within the python script, so when a button is clicked of the webpage it would redirect the user back to the home page (index.html), however when I have tested the webpage and clicked on the button on the webpage (with the flask server running) a "400 bad request" page is shown
Python Code:
#Python code behind the website
import datetime
from flask import Flask, session, redirect, url_for, escape, request, render_template
print ("started")
def Log(prefix, LogMessage):
timeOfLog = datetime.datetime.now().strftime("%d-%m-%Y %H:%M:%S" + " : ")
logFile = open("Log.log", 'a')
logFile.write("[" + timeOfLog + "][" + prefix + "][" + LogMessage + "] \n")
logFile.close()
app = Flask(__name__)
#app.route('/')
def my_form():
print ("Acessed index")
return render_template("index.html")
#app.route('/', methods=['POST'])
def my_form_post():
text = request.form['text']#requests text from the text form
processed_text = text #does nothing
user = "" #use poss in future to determin user
logFile = open("MessageLog.msglog", 'a')#opens the message log file in append mode
logFile.write(text + "\n")#stores the inputted message in the message log file
logFile.close()
#print (text)
Log("User Message", (user + text))#uses the main log file to store messages aswell as errors
print ("Accessing index")
return render_template("test.html")
#app.route('/test', methods=['POST'])
def test():
#text = request.form['text']
print ("Test page function")
#return "hello"
return render_template("index.html")
if __name__ == '__main__':
app.debug = True
app.run(host='0.0.0.0')
HTML code:
-->
<body>
<h1>Test Page</h1>
<form method="POST">
<input type="submit" name="my-form" value="Send">
</form>
</body>
Stack Track:
You need to post your form to the correct URL:
<body>
<h1>Test Page</h1>
<form method="POST" action='/test'>
<input type="submit" name="my-form" value="Send">
</form>
</body>
By default if you don't add an action attribute to an HTML form it will just perform it's defined method to the URL you are currently on. You can add an action attribute to change that behavior.
You can also do this with the url_for() function. This is a bit safer as URL's tend to change more often than your view method names:
<body>
<h1>Test Page</h1>
<form method="POST" action="{{ url_for('test') }}">
<input type="submit" name="my-form" value="Send">
</form>
</body>
You pass the name of the view method (not it's URL) as a string to the function. Be careful to use the right quotes.
Note that it's slightly confusing to have 2 views for the same URL. Usually something like this is done although YMMV but consider it for your application:
#app.route('/someurl')
def some_view():
if request.method == "POST":
# handle POST
else:
# handle GET

Method Not Allowed flask error 405

I am developing a flask registration form, and I receive an error:
error 405 method not found.
Code:
import os
# Flask
from flask import Flask, request, session, g, redirect, url_for, abort, \
render_template, flash, Markup, send_from_directory, escape
from werkzeug import secure_filename
from cultura import app
# My app
from include import User
#app.route('/')
def index():
return render_template('hello.html')
#app.route('/registrazione', methods=['POST'])
def registration():
if request.method == 'POST':
username= request.form.username.data
return render_template('registration.html', username=username)
else :
return render_template('registration.html')
registration.html:
<html>
<head> <title>Form di registrazione </title>
</head>
<body>
{{ username }}
<form id='registration' action='/registrazione' method='post'>
<fieldset >
<legend>Registrazione utente</legend>
<input type='hidden' name='submitted' id='submitted' value='1'/>
<label for='name' >Nome: </label>
<input type='text' name='name' id='name' maxlength="50" /> <br>
<label for='email' >Indirizzo mail:</label>
<input type='text' name='email' id='email' maxlength="50" />
<br>
<label for='username' >UserName*:</label>
<input type='text' name='username' id='username' maxlength="50" />
<br>
<label for='password' >Password*:</label>
<input type='password' name='password' id='password' maxlength="50" />
<br>
<input type='submit' name='Submit' value='Submit' />
</fieldset>
</form>
</body>
</html>
when I visit localhost:5000/registrazione, I receive the error. What am I doing wrong?
This is because you only allow POST requests when defining your route.
When you visit /registrazione in your browser, it will do a GET request first. Only once you submit the form your browser will do a POST. So for a self-submitting form like yours, you need to handle both.
Using
#app.route('/registrazione', methods=['GET', 'POST'])
should work.
change name of method registration
#app.route('/registrazione', methods=['POST'])
def registrazione():
if request.method == 'POST':
username= request.form.username.data
return render_template('registration.html', username=username)
else :
return render_template('registration.html')
Just for people reading on it now.
You have to render the /registrazione first, befor you can access the form data. Just write.
#app.route("/registrazione")
def render_registrazione() -> "html":
return render_template("registrazione.html")
before you define def registration(). Sequence is key. You can't access data before the even are available. This is my understanding of the problem.
For the error 500 (internal server error) in
username = request.form.username
write instead
username = request.args.get("username")
Example of a flask app using wsgi with JQuery, Ajax and json:
activecalls.py
from flask import Flask, jsonify
application = Flask(__name__, static_url_path='')
#application.route('/')
def activecalls():
return application.send_static_file('activecalls/active_calls_map.html')
#application.route('/_getData', methods=['GET', 'POST'])
def getData():
#hit the data, package it, put it into json.
#ajax would have to hit this every so often to get latest data.
arr = {}
arr["blah"] = []
arr["blah"].append("stuff");
return jsonify(response=arr)
if __name__ == '__main__':
application.run()
Javascript json, /static/activecalls/active_calls_map.html:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<script>
$.ajax({
//url : "http://dev.consumerunited.com/wsgi/activecalls.py/_getData",
url : "activecalls.py/_getData",
type: "POST",
data : formData,
datatype : "jsonp",
success: function(data, textStatus, jqXHR)
{
//data - response from server
alert("'" + data.response.blah + "'");
},
error: function (jqXHR, textStatus, errorThrown)
{
alert("error: " + errorThrown);
}
});
</script>
When you run this. The alert box prints: "stuff".
I was also getting this error, I was going through all of this documentation and trying to sort this out, but at the end it was a silly mistake.
Below code was generating the 405 Method Not Allowed error
import requests
import json
URL = "http://hostname.com.sa/fetchdata/"
PARAMS = '{ "id":"111", "age":30, "city":"New Heaven"}'
response = requests.post(url = URL, json = PARAMS)
print(response.content)
It was due to an extra / at the end of url, when I removed it, it was gone. The below update on the requesting URL fixed it
URL = "http://hostname.com.sa/fetchdata"
I was stuck over same issue, I am showing my Login page route as default route and when I try to submit with default route then I got the issue because I had configured POST request on login route but not on the default application route and when I had added the 'POST' method configuration for my default route too, everything is working as expected. The configuration I had done is as follows:
#routes.route("/", methods=['GET', 'POST'] )
#routes.route("/admin-login", methods=['GET', 'POST'])
def admin_login():
...
Hope, this would help anyone facing the similar issue.

Categories