I am not familiar with CherryPy and Python, but I need to write a very simple web application that performs login ---> do some commands ---> logout. For login I am using the code in the following link:
http://tools.cherrypy.org/wiki/AuthenticationAndAccessRestrictions
the application is:
import cherrypy
import os.path
import struct
from auth import AuthController, require, member_of, name_is
class Server(object):
led_power=0
led_switch=1 #Initial LED on
_cp_config = {
'tools.sessions.on': True,
'tools.auth.on': True
}
auth = AuthController()
#cherrypy.expose
#require()
def index(self, switch='', power=''):
if switch:
self.led_switch = int(switch)
if power:
self.led_power = int(power)
html = open('led.html','r').read()
if self.led_switch:
print "ON"
else:
print "OFF"
if self.led_power:
print "Logout"
cherrypy.session.clear()
return html
index.exposed = True
conf = {
'global' : {
'server.socket_host': '0.0.0.0', #0.0.0.0 or specific IP
'server.socket_port': 8080 #server port
},
'/images': { #images served as static files
'tools.staticdir.on': True,
'tools.staticdir.dir': os.path.abspath('images')
},
'/favicon.ico': { #favorite icon
'tools.staticfile.on': True,
'tools.staticfile.filename': os.path.abspath("images/bulb.ico")
}
}
cherrypy.quickstart(Server(), config=conf)
and the html file is:
<html>
<head>
</head>
<body>
<br>
<img src="images/on.png">
<img src="images/off.png">
<p>
<img src="images/Logout.png">
</body>
</html>
with a folder contain three images.
When I run the application I can see the login page on the localhost with username and password fields, then I can reach to the web page which has three button "ON, OFF, Logout".
The problem is I must click the logout button twice to logout, and when I login again and click on any button even the ON or OFF buttons the page is logout and show me the login page again.
I cannot logout in a right way, any help please ?
Thanks
Try running this code. It calls the AuthController().logout() function.
import cherrypy
import os.path
import struct
from auth import AuthController, require, member_of, name_is
class Server(object):
led_power=0
led_switch=1 #Initial LED on
_cp_config = {
'tools.sessions.on': True,
'tools.auth.on': True
}
auth = AuthController()
#cherrypy.expose
#require()
def index(self, switch='', power=''):
if switch:
self.led_switch = int(switch)
if power:
self.led_power = int(power)
html = open('led.html','r').read()
if self.led_switch:
print "ON"
else:
print "OFF"
if self.led_power:
print "Logout"
AuthController().logout()
return html
index.exposed = True
conf = {
'global' : {
'server.socket_host': '0.0.0.0', #0.0.0.0 or specific IP
'server.socket_port': 8080 #server port
},
'/images': { #images served as static files
'tools.staticdir.on': True,
'tools.staticdir.dir': os.path.abspath('images')
},
'/favicon.ico': { #favorite icon
'tools.staticfile.on': True,
'tools.staticfile.filename': os.path.abspath("images/bulb.ico")
}
}
cherrypy.quickstart(Server(), config=conf)
Hope this helps.
Andrew
Related
I want to post data from Vue to flask
If I don't use parameter data: {},it's no problem.
If I use, error occurs
and this is the server (HTTP Status Code is 200)
Why is this happening? What should I do?
code:
Home.vue
<script>
import axios from 'axios'
export default {
created() {
this.getData();
},
methods: {
getData() {
axios({
baseURL: 'http://127.0.0.1:5001',
url: '/recData',
method: 'post',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
}).then(res=>{
console.log(res);
}).catch(err=>{
console.log(err);
})
}
},
}
</script>
fls_2.py
from flask import Flask, request
from flask_cors import CORS
app = Flask(__name__)
CORS(app, resources={r'/*': {'origins': '*'}})
#app.route('/')
def index():
return 'Hello World!'
#app.route('/recData',methods=['GET','POST'])
def recData():
if request.method=='POST':
return '--- post ---'
if request.method=='GET':
return '--- get ---'
if __name__=='__main__':
app.run(port=5001, debug=True)
You can set a proxy in vue.config.js
module.exports = {
devServer: {
proxy: 'http://127.0.0.1:5001',
}
}
there is a good article about it in this link: https://medium.com/js-dojo/how-to-deal-with-cors-error-on-vue-cli-3-d78c024ce8d3
Add this to vue.config.js and restart your server after the configuration change.
devServer: {
proxy: {
"/": {
target: "http://localhost:5001",
ws: false,
changeOrigin: true,
logLevel: 'debug'
}
}
Use this in your component.
let url = "/recData";
let payload = {
firstName: "Fred",
lastName: "Flintstone"
}
axios.post(url, payload)
.then(res=>{
console.log(res);
})
.catch(err=>{
console.log(err);
});
I hope it works and I was able to help you.
I have a CherryPy server that dispenses a few static HTML/JS/etc. files to /foosball, plus some JSON through a REST API to /.
import cherrypy
config = {
'global': {
'server.socket_host': '0.0.0.0',
'server.socket_port': # my port here,
'tools.json_in.on': True
},
'/foosball': {
'tools.staticdir.on': True,
'tools.staticdir.root': '/var/www/html',
'tools.staticdir.dir': 'foosball',
'tools.staticdir.index': 'index.html'
}
}
#cherrypy.popargs('player_id')
class RESTClient_Player(object):
# stuff
class RESTClient_Game(object):
# stuff
class RESTClient:
players = RESTClient_Player()
games = RESTClient_Game()
#cherrypy.expose
def index(self):
http_method = getattr(self, cherrypy.request.method)
return (http_method)()
cherrypy.quickstart(RESTClient(), '/', config)
I also want to keep these pages protected by a basic access restriction scheme, so I've been examining the excellent tutorial CherryPy provides.
Trouble is, the documentation is geared towards authenticating non-static pages, the kind explicitly declared by def statements. I tried and failed to adapt this documentation to the files in /foosball, but without success. /foosball always ends up loading without any authentication request.
What can I add to give static files some access restriction ability?
Thanks!
EDIT: I got pointed towards auth_tool. With the below config block, I was able to lock up the REST API portion with a login screen, but all static files in /foosball are still openly accessible:
def check_login_and_password(login, password):
cherrypy.log(login)
cherrypy.log(password)
return
config = {
'global': {
'server.socket_host': '0.0.0.0',
'server.socket_port': # my port here,
'tools.json_in.on': True,
'tools.sessions.on': True,
'tools.session_auth.on': True,
'tools.session_auth.check_username_and_password': check_login_and_password
},
'/foosball': {
'tools.staticdir.on': True,
'tools.staticdir.root': '/var/www/html',
'tools.staticdir.dir': 'foosball',
'tools.staticdir.index': 'index.html',
'tools.sessions.on': True,
'tools.session_auth.on': True,
'tools.session_auth.check_username_and_password': check_login_and_password
}
}
Instead of using the "staticdir" in your config, you can create a function in your class that will return static files. If you do that, you can wrap authentication around your function.
import cherrypy
from cherrypy.lib.static import serve_file
import os
class Hello(object):
#cherrypy.expose
def index(self):
return "Hello World"
#cherrypy.expose
def static(self, page):
return serve_file(os.path.join(current_dir, 'static', page), content_type='text/html')
if __name__ == '__main__':
current_dir = os.path.dirname(os.path.abspath(__file__))
cherrypy.quickstart(Hello())
I'm getting the following error from my cherrypy script that is being generated by the submit module.
ValueError: Page handlers MUST return bytes. Use tools.encode if you wish to return unicode
I turned tool.encode on in my config but I'm still getting this error. I'm allowing users to upload content via the jQuery Form Plugin. Anythoughts as to why I'm getting this error?
Here is my cherrypy file:
class Root(object):
#cherrypy.expose
def index(self)
return open('/home/joestox/webapps/freelinreg_static/index.html')
#cherrypy.expose
def submit(self, myfile):
cherrypy.session['myfile'] = myfile
data_name = myfile.filename
#Send back to JQuery with Ajax
#Put in JSON form
data_name= json.dumps(dict(title = data_name))
cherrypy.response.headers['Content-Type'] = 'application/json'
return data_name
cherrypy.config.update({
'tools.staticdir.debug': True,
'log.screen': True,
'server.socket_host': '127.0.0.1',
'server.socket_port': *****,
'tools.sessions.on': True,
'tools.encode.on': True,
'tools.encode.encoding': 'utf-8',
})
config = {
}
cherrypy.tree.mount(Root(), '/', config=config)
cherrypy.engine.start()
HTML:
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript' src='freelinreg_static/google.js'></script>
<script type='text/javascript' src='freelinreg_static/frontend.js'></script>
<script type='text/javascript' src='freelinreg_static/malsup.js'></script>
</head>
<body>
<form id="dataform" action="submit" method="post" enctype="multipart/form-data">
<input type="file" name="myfile" id="myFile"/>
<input type="submit" id="data_submit" value="Continue"/>
</form>
</body>
</html>
jQuery (frontend.js):
$(document).ready(function () {
(function () {
$('#dataform').ajaxForm({
url: "submit",
success: function (data) {
var $a_var = data['title'];
$('body').append($a_var);
}
});
return false;
})();
});
I my case the issue started after switching from python2 to python3.
It was resolved by setting
'tools.encode.text_only': False
In the app global configuration.
Hope it helps
Hi people looking for answers.
I had the same problem but in my case this little addition solved everything.
return <some-json>.encode('utf8')
You need to rearrange global config update to happen after application mount:
config = {
}
cherrypy.tree.mount(Root(), '/', config=config)
cherrypy.config.update({
'tools.staticdir.debug': True,
'log.screen': True,
'server.socket_host': '127.0.0.1',
'server.socket_port': *****,
'tools.sessions.on': True,
'tools.encode.on': True,
'tools.encode.encoding': 'utf-8'
})
cherrypy.engine.start()
Because you were calling config = {} after your config update command you were overriding the update settings for Root application.
Also, change your submit function to this:
#cherrypy.expose
#cherrypy.tools.json_out
def submit(self, myfile):
cherrypy.session['myfile'] = myfile
# Return dict, which will be autoconverted to JSON
# by the json_out tool (see decorator above)
return {'title': myfile.filename}
I need to add a confirm box when I click on logout or restart buttons in my following python/html script. This script is just summary of large one and its work fine with me.any suggestion please?
Thanks in advance.
#!/usr/bin/python
import cherrypy
import os.path
import struct
from auth import AuthController, require, member_of, name_is
import subprocess
import commands
class Server(object):
led_logout=0
led_restart=0
_cp_config = {
'tools.sessions.on': True,
'tools.auth.on': True
}
auth = AuthController()
#cherrypy.expose
#require()
def index(self,logout='', restart=''):
html = """
<html>
<head>
</head>
<body>
<p>{htmlText}
<p>
<img src="images/Logout.png"><a href="?restart=1"><img src="images/Restart.png">
</ul>
</body>
</html>
"""
myText = ''
myText = "Hello"
if logout:
self.led_logout = int(logout)
if self.led_logout:
print "Logout !!!!!"
AuthController().logout('/?logout=0')
if restart:
self.led_restart = int(restart)
#subprocess.call(['sudo shutdown -r now'], shell=True)
myText = "The system is restarting"
return html.format(htmlText=myText)
index.exposed = True
#configuration
conf = {
'global' : {
'server.socket_host': '0.0.0.0', #0.0.0.0 or specific IP
'server.socket_port': 8085 #server port
},
'/images': { #images served as static files
'tools.staticdir.on': True,
'tools.staticdir.dir': os.path.abspath('/home/ubuntu/webserver/images')
}
}
cherrypy.quickstart(Server(), config=conf)
OK I got the solution, I just added
onclick="return confirm('Are you sure you want to logout?');"
So the complete line will be:
<img src="images/Logout.png"><a href="?restart=1" onclick="return confirm('Are you sure you want to restart?');" ><img src="images/Restart.png">
In the following python/html script,I want to refresh the web page automatically when the value of the variable "condition" equal to "1". So that the page show me the new text contains of the variable "myText" automatically. The variable "myText" can have any text, and the following script is just an example.
#!/usr/bin/python
import cherrypy
import os.path
import struct
from auth import AuthController, require, member_of, name_is
import subprocess
import commands
class Server(object):
led_logout=0
led_restart=0
condition=0
_cp_config = {
'tools.sessions.on': True,
'tools.auth.on': True
}
auth = AuthController()
#cherrypy.expose
#require()
def index(self,logout=''):
html = """
<html>
<head>
</head>
<body>
<p>{htmlText}
<p>
<img src="images/Logout.png">
</ul>
</body>
</html>
"""
myText = ''
myText = "Hello"
if logout:
self.led_logout = int(logout)
if self.led_logout:
print "Logout !!!!!"
AuthController().logout('/?logout=0')
return html.format(htmlText=myText)
index.exposed = True
#configuration
conf = {
'global' : {
'server.socket_host': '0.0.0.0', #0.0.0.0 or specific IP
'server.socket_port': 8085 #server port
},
'/images': { #images served as static files
'tools.staticdir.on': True,
'tools.staticdir.dir': os.path.abspath('/home/ubuntu/webserver/images')
}
}
cherrypy.quickstart(Server(), config=conf)
Ok for you to get your text from the server you're going to need some ajax.
Give this a try...
#!/usr/bin/python
import cherrypy
import os.path
import struct
from auth import AuthController, require, member_of, name_is
import subprocess
import commands
class Server(object):
led_logout=0
led_restart=0
condition=0
_cp_config = {
'tools.sessions.on': True,
'tools.auth.on': True
auth = AuthController()
#cherrypy.expose
#require()
def index(self):
html = """
<html>
<head>
</head>
<body>
<script language="javascript" type="text/javascript">
function getMyText()
{
// code for IE7+, Firefox, Chrome, Opera, Safari
if(window.XMLHttpRequest)
xmlhttp=new XMLHttpRequest();
else// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById('message').innerHTML= = xmlhttp.responseText;
}
}
xmlhttp.open("GET","/getMyText?logout=True", true);
xmlhttp.send();
}
</script>
<p id="message"><p>
<img src="images/Logout.png">
</ul>
</body>
</html>
"""
def getMyText(logout=False)
myText = "Hello"
if logout:
self.led_logout = int(logout)
if self.led_logout:
print "Logout !!!!!"
AuthController().logout('/?logout=0')
return myText
index.exposed = True
#configuration
conf = {
'global' : {
'server.socket_host': '0.0.0.0', #0.0.0.0 or specific IP
'server.socket_port': 8085 #server port
},
'/images': { #images served as static files
'tools.staticdir.on': True,
'tools.staticdir.dir': os.path.abspath('/home/ubuntu/webserver/images')
}
}
cherrypy.quickstart(Server(), config=conf)
Hope this helps!
Andrew