I would like to override 404 error page showed in cherrypy to my custom error page. The challenge is to read all subfolders inside the directory that contain my index.html. These subfolders are img, css, js...
According to cherrypy documentation I found that I can custom a 404 error page overriding this function and doing a cherrypy.config.update in the following form:
_cp_config = {
'error_page.404': os.path.join(localDir, "static/index.html")
}
I customised the page with success and cherrypy load my html with success.
Here is my code that loads the html (but not the subdirectories inside that folder).
import cherrypy
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings")
application = get_wsgi_application()
WEBAPP = "/app-web/"
CONF_WEBAPP = {'/':
{'tools.staticdir.on': True,
'tools.staticdir.dir': WEBAPP,
'tools.staticdir.index': 'index.html'}}
WEB_ROOT = '/webclient/'
class ServeWebApp(object):
#cherrypy.expose
def index(self):
pass
if __name__ == '__main__':
cherrypy.tree.graft(application, '/')
cherrypy.tree.mount(ServeWebApp(), '/webapp', config=CONF_WEBAPP)
cherrypy.config.update({'error_page.404': os.path.join(WEB_ROOT, "index.html")})
cherrypy.server.socket_host = "0.0.0.0"
cherrypy.server.socket_port = 8000
cherrypy.server.thread_pool = 100
cherrypy.engine.start()
cherrypy.engine.block()
I am serving a static web site fully functional with css and js declaring CONF_WEBAPP and loading in the line:
cherrypy.tree.mount(ServeWebApp(), '/webapp', config=CONF_WEBAPP)
inside my folder WEB_ROOT I have an index.html file, and a
set of folders {css, js, fonts, img}.
I would like to load the index file and all subdirectories inside that folder. Is it possible? Are there another way to get the same result?
I can not use another tool to show custom page (like Nginx, apache).
Another method to customize but I could not follow that way because it uses functions
Here is how I solved my problem.
First I installed lib requests in my virtualenv.
import requests
from ConfigParser import RawConfigParser
config = RawConfigParser()
#file with my urls I would like to use in my app.
config.read('myparams.ini')
class PlatformAndroid(object):
android_url = config.get('links', 'android')#static url to play store
redir = requests.get(android_url)
if redir.status_code < 400: #case my app is published in play store
raise cherrypy.HTTPRedirect(android_url)
#unpublished app
raise cherrypy.HTTPRedirect(config.get('links','webapp')) #fallback to webapp version of my platform specific app.
if __name__ == '__main__':
cherrypy.tree.mount(PlatformAndroid(), '/android')
cherrypy.engine.start()
cherrypy.engine.block()
myparams.ini
[links]
android : http://play.google.com/store/apps/
ios : http://itunes.apple.com/us/app/
webapp : http://mysite.example.com/webapp/
Related
I'm using apidoc to generate a documentation website. On running, it creates a folder called doc, which contains an index.html file and accompanying css and js.
I'd like to be able to serve this folder with a Flask server, but can't work out how to do it.
My folder structure looks like this
-root
--- doc/ #contains all of the static stuff
--- server.py
I've tried this, but can't get it to work:
app = Flask(__name__, static_url_path="/doc")
#app.route('/')
def root():
return app.send_from_directory('index.html')
One of the problems is that all of the static files referenced in the index.html generated by apidoc are relative to that page, so /js/etc. doesn't work, since it's actually /doc/js...
It would be great if someone could help me with the syntax here. Thanks.
I spot three problems in code.
a) you do not need to use static_url_path, as send_from_directory is independent of it
b) when I try to run above code, and go to /, I get a AttributeError: 'Flask' object has no attribute 'send_from_directory' - this means translates to app.send_from_directory is wrong - you need to import this function from flask, ie from flask import send_from_directory
c) when I then try to run your code, I get a TypeError: send_from_directory() missing 1 required positional argument: 'filename', which means send_from_directory needs another argument; it needs both a directory and a file
Putting this all together you get something like this:
from flask import Flask
from flask import send_from_directory
app = Flask(__name__)
#app.route("/")
def index():
return send_from_directory("doc", "index.html")
As a takeway (for myself):
reading the documentation helps a lot ( https://flask.palletsprojects.com/en/1.1.x/api/ )
having a close look at the - at first scary - error messages gives really good hints on what to do
So I'm creating a website and I was wondering if I could create a button / link to open a FILE, not another website, but a .py file. -Thanks
We have object tag in html. You create one button and an object. When u click on the button then you have to change the data attribute value of object tag.
It will work.
Use any lightweight python web framework like Flask.
Then use a script like this to run it on a website:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
#do your things here
return "It works!"
if __name__ == "__main__":
app.run()
Then run the server :
python script. py
Now the server is running on port 5000
So when you visit (eg: http://rasp_pi_ip:5000/) the website, your script will run.
I'm trying to write a web application and am using Tornado Web for the json xhr calls. But I'm trying to serve a static index.html which is to serve the main app.
How can I serve a simple page and still have requesthandlers for the rest of my application?
Here's what I tried so far:
import tornado.ioloop
import tornado.web
import json
import os
games = [...]
class HomeHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html')
class MatchHandler(tornado.web.RequestHandler):
def get(self):
self.write(json.dumps(games))
path = os.path.join(os.getcwd(), 'app')
if __name__ == "__main__":
application = tornado.web.Application(
[
(r'/', HomeHandler),
(r'/games', MatchHandler),
(r'/*.*', tornado.web.StaticFileHandler, {'path': path})
],
template_path=os.path.join(os.path.dirname(__file__), 'app')
)
application.listen(16001)
tornado.ioloop.IOLoop.current().start()
Thanks in advance!
The StaticFileHandler regex needs to A) contain a capturing group and B) use regex syntax instead of glob syntax:
(r'/(.*\..*)', tornado.web.StaticFileHandler, {'path': path})
This will match any paths containing a dot and send it to the StaticFileHandler.
Your code looks correct to me. Put a file named "index.html" in the "app" subdirectory of your current working directory when you run the app, and the contents of that "index.html" will be the response when you visit http://localhost:16001/
Your code should work fine, as #a-jesse-jiryu-davis answered. To expand a bit on it, you could use tornado.web.StaticFileHandler if you just need to serve your static file. This will make it more flexible, and also take advantage of server-side caching etc.
I am using webpy framefork. I want to serve static file on one of requests. Is there special method in webpy framework or I just have to read and return that file?
If you are running the dev server (without apache):
Create a directory (also known as a folder) called static in the location of the script that runs the web.py server. Then place the static files you wish to serve in the static folder.
For example, the URL http://localhost/static/logo.png will send the image ./static/logo.png to the client.
Reference: http://webpy.org/cookbook/staticfiles
Update. If you really need to serve a static file on / you can simply use a redirect:
#!/usr/bin/env python
import web
urls = (
'/', 'index'
)
class index:
def GET(self):
# redirect to the static file ...
raise web.seeother('/static/index.html')
app = web.application(urls, globals())
if __name__ == "__main__": app.run()
I struggled with this for the last couple of hours... Yuck!
Found two solutions which are both working for me...
1 - in .htaccess add this line before the ModRewrite line:
RewriteCond %{REQUEST_URI} !^/static/.*
This will make sure that requests to the /static/ directory are NOT rewritten to go to your code.py script.
2 - in the code.py add a static handler and a url entry for each of several directories:
urls = (
'/' , 'index' ,
'/add', 'add' ,
'/(js|css|images)/(.*)', 'static',
'/one' , 'one'
)
class static:
def GET(self, media, file):
try:
f = open(media+'/'+file, 'r')
return f.read()
except:
return '' # you can send an 404 error here if you want
Note - I stole this from the web.py google group but can't find the dang post any more!
Either of these worked for me, both within the templates for web.py and for a direct call to a web-page that I put into "static"
I don't recommend serving static files with web.py. You'd better have apache or nginx configured for that.
The other answers did not work for me.
You can first load the html file in app.py or even write the html within app.py.
Then, you can make the index class' GET method return the static html.
index_html = '''<html>hello world!</html>'''
class index:
def GET(self):
return index_html
I am using FCKEditor within a Django app served by Apache/mod-wsgi. I don't want to install php just for FCKEditor andI see FCKEditor offers image uploading and image browsing through Python. I just haven't found good instructions on how to set this all up.
So currently Django is running through a wsgi interface using this setup:
import os, sys
DIRNAME = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-3])
sys.path.append(DIRNAME)
os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
In fckeditor in the editor->filemanager->connectors->py directory there is a file called wsgi.py:
from connector import FCKeditorConnector
from upload import FCKeditorQuickUpload
import cgitb
from cStringIO import StringIO
# Running from WSGI capable server (recomended)
def App(environ, start_response):
"WSGI entry point. Run the connector"
if environ['SCRIPT_NAME'].endswith("connector.py"):
conn = FCKeditorConnector(environ)
elif environ['SCRIPT_NAME'].endswith("upload.py"):
conn = FCKeditorQuickUpload(environ)
else:
start_response ("200 Ok", [('Content-Type','text/html')])
yield "Unknown page requested: "
yield environ['SCRIPT_NAME']
return
try:
# run the connector
data = conn.doResponse()
# Start WSGI response:
start_response ("200 Ok", conn.headers)
# Send response text
yield data
except:
start_response("500 Internal Server Error",[("Content-type","text/html")])
file = StringIO()
cgitb.Hook(file = file).handle()
yield file.getvalue()
I need these two things two work together by means of modifying my django wsgi file to serve the fckeditor parts correctly or make apache serve both django and fckeditor correctly on a single domain.
This describes how to embed the FCK editor and enable image uploading.
First you need to edit fckconfig.js to change the image upload
URL to point to some URL inside your server.
FCKConfig.ImageUploadURL = "/myapp/root/imageUploader";
This will point to the server relative URL to receive the upload.
FCK will send the uploaded file to that handler using the CGI variable
name "NewFile" encoded using multipart/form-data. Unfortunately you
will have to implement /myapp/root/imageUploader, because I don't think
the FCK distribution stuff can be easily adapted to other frameworks.
The imageUploader should extract the NewFile and store it
somewhere on the server.
The response generated by /myapp/root/imageUploader should emulate
the HTML constructed in /editor/.../fckoutput.py.
Something like this (whiff template format)
{{env
whiff.content_type: "text/html",
whiff.headers: [
["Expires","Mon, 26 Jul 1997 05:00:00 GMT"],
["Cache-Control","no-store, no-cache, must-revalidate"],
["Cache-Control","post-check=0, pre-check=0"],
["Pragma","no-cache"]
]
/}}
<script>
//alert("!! RESPONSE RECIEVED");
errorNumber = 0;
fileUrl = "fileurl.png";
fileName = "filename.png";
customMsg = "";
window.parent.OnUploadCompleted(errorNumber, fileUrl, fileName, customMsg);
</script>
The {{env ...}} stuff at the top indicate the content type and
recommended HTTP headers to send. The fileUrl should be the Url to
use to find the image on the server.
Here are the basic steps to get the html fragment which
generates the FCK editor widget. The only tricky part is you have to put the
right client indentification into the os.environ -- it's ugly
but that's the way the FCK library works right now (I filed a bug
report).
import fckeditor # you must have the fck editor python support installed to use this module
import os
inputName = "myInputName" # the name to use for the input element in the form
basePath = "/server/relative/path/to/fck/installation/" # the location of FCK static files
if basePath[-1:]!="/":
basePath+="/" # basepath must end in slash
oFCKeditor = fckeditor.FCKeditor(inputName)
oFCKeditor.BasePath = basePath
oFCKeditor.Height = 300 # the height in pixels of the editor
oFCKeditor.Value = "<h1>initial html to be editted</h1>"
os.environ["HTTP_USER_AGENT"] = "Mozilla/5.0 (Macintosh; U;..." # or whatever
# there must be some way to figure out the user agent in Django right?
htmlOut = oFCKeditor.Create()
# insert htmlOut into your page where you want the editor to appear
return htmlOut
The above is untested, but it's based on the below which is tested.
Here is how to use FCK editor using mod-wsgi:
Technically it uses a couple features of WHIFF (see
WHIFF.sourceforge.net),
-- in fact it is part of the WHIFF distribution --
but
the WHIFF features are easily removed.
I don't know how to install it in Django, but if
Django allows wsgi apps to be installed easily, you
should be able to do it.
NOTE: FCK allows the client to inject pretty much anything
into HTML pages -- you will want to filter the returned value for evil
attacks.
(eg: see whiff.middleware.TestSafeHTML middleware for
an example of how to do this).
"""
Introduce an FCK editor input element. (requires FCKeditor http://www.fckeditor.net/).
Note: this implementation can generate values containing code injection attacks if you
don't filter the output generated for evil tags and values.
"""
import fckeditor # you must have the fck editor python support installed to use this module
from whiff.middleware import misc
import os
class FCKInput(misc.utility):
def __init__(self,
inputName, # name for input element
basePath, # server relative URL root for FCK HTTP install
value = ""): # initial value for input
self.inputName = inputName
self.basePath = basePath
self.value = value
def __call__(self, env, start_response):
inputName = self.param_value(self.inputName, env).strip()
basePath = self.param_value(self.basePath, env).strip()
if basePath[-1:]!="/":
basePath+="/"
value = self.param_value(self.value, env)
oFCKeditor = fckeditor.FCKeditor(inputName)
oFCKeditor.BasePath = basePath
oFCKeditor.Height = 300 # this should be a require!
oFCKeditor.Value = value
# hack around a bug in fck python library: need to put the user agent in os.environ
# XXX this hack is not safe for multi threaded servers (theoretically)... need to lock on os.env
os_environ = os.environ
new_os_env = os_environ.copy()
new_os_env.update(env)
try:
os.environ = new_os_env
htmlOut = oFCKeditor.Create()
finally:
# restore the old os.environ
os.environ = os_environ
start_response("200 OK", [('Content-Type', 'text/html')])
return [htmlOut]
__middleware__ = FCKInput
def test():
env = {
"HTTP_USER_AGENT":
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14"
}
f = FCKInput("INPUTNAME", "/MY/BASE/PATH", "THE HTML VALUE TO START WITH")
r = f(env, misc.ignore)
print "test result"
print "".join(list(r))
if __name__=="__main__":
test()
See this working, for example, at
http://aaron.oirt.rutgers.edu/myapp/docs/W1500.whyIsWhiffCool.
btw: thanks. I needed to look into this anyway.
Edit: Ultimately I was unhappy with this solution also so I made a Django app that takes care of the file uploads and browsing.
This is the solution I finally hacked together after reading the fckeditor code:
import os, sys
def fck_handler(environ, start_response):
path = environ['PATH_INFO']
if path.endswith(('upload.py', 'connector.py')):
sys.path.append('/#correct_path_to#/fckeditor/editor/filemanager/connectors/py/')
if path.endswith('upload.py'):
from upload import FCKeditorQuickUpload
conn = FCKeditorQuickUpload(environ)
else:
from connector import FCKeditorConnector
conn = FCKeditorConnector(environ)
try:
data = conn.doResponse()
start_response('200 Ok', conn.headers)
return data
except:
start_response("500 Internal Server Error",[("Content-type","text/html")])
return "There was an error"
else:
sys.path.append('/path_to_your_django_site/')
os.environ['DJANGO_SETTINGS_MODULE'] = 'your_django_site.settings'
import django.core.handlers.wsgi
handler = django.core.handlers.wsgi.WSGIHandler()
return handler(environ, start_response)
application = fck_handler