Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
204 views
in Technique[技术] by (71.8m points)

python - Deploy flask application on 1&1 shared hosting (with CGI)

I've written a web application for my sports club with the flask web framework. I did everything on my local machine with the build-in test server.

Know they told me to deploy it on an 1&1 shared hosting web space. They have python support but it seems like they only allow CGI to run python scripts.

I tried this tutorial: flask via CGI

I ignored the rewrite stuff until now. All requests to my CGI script resulted in a 404 error. I modified my 404 handler in the application to return request.path. When I request /foo/runserver.cgi/ it returns / as output. I have no idea why it doesn't serve the index view. It doesn't work with any view, I always get a 404.

Kind regards, Sebastian

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'm writing in to provide an answer after nearly a year because the given answer is incomplete and because the suggestion to leave off the /$1 is wrong. Other stackoverflow threads that can be reached by an Internet search using the string "deploy flask on cgi" have also ended without satisfactory solutions.

To begin, my .htaccess file is exactly as in the referenced "flask via CGI" doc, except that the comment in the second line for the RewriteCond has to be removed because in .htaccess any comment must occupy an entire line.

I put the .htaccess file in the public_html document root folder and my cgi script is /home/myusername/public_html/scgi-bin/moc/cgiappserver-prod.cgi.

It's Python of course and the shebang at the top had better be right. At my ISP they use cpanel which has a wrapper for CGI that they call "scgi". It's not the real thing, unfortunately. So treat it as ordinary CGI for purposes of running Flask.

I should add that I only have a shared-hosting account.

Here's my cgiappserver-prod.cgi file:

#!/home/myusername/local/bin/python
import cgitb; cgitb.enable()  # This line enables CGI error reporting
from wsgiref.handlers import CGIHandler
import traceback
from settings import LGGR

app = None
try:
    import moc
    app = moc.app
except Exception, e:
    LGGR.info( traceback.format_exc([10]) )
    LGGR.info( 'Problem in cgiappserver-prod with moc import: %s' % e )

class ScriptNameStripper(object):
   def __init__(self, app):
       self.app = app
   def __call__(self, environ, start_response):
       environ['SCRIPT_NAME'] = ''
       return self.app(environ, start_response)

app = ScriptNameStripper(app)

try:
    CGIHandler().run(app)
except Exception, e:
    LGGR.info( traceback.format_exc([10]) )
    LGGR.info( 'Problem in cgiappserver-prod with CGIHandler().run(): %s' % e )

So my app is spread over a few files, with setting.py and moc.py in particular showing in the code above.

My hours of foundering around were partly due to all of the unhelpful posts on this subject that I read, but mainly due to my not getting with the business of getting error messages out early enough. (I have access to an error log that is provided by the ISP but it is seldom helpful.)

To start, I have confirmed that the cgitb.enable() function works. I have deliberately misspelled wsgiref and seen a beautiful error page and I have commented out the cgitb (cgi traceback) line to see the error message turn into a useless 500 status code.

Note that I also set up in settings.py a logger, a rotating file logger LGGR. With it I discovered that I had to do something extra--- not shown here--- to tell the Python interpreter where the sqlite3 library is.

Also, you can simply use print statements, about which the referenced Flask docs on CGI say:

  • With CGI, you will also have to make sure that your code does not contain any print statements, or that sys.stdout is overridden by something that doesn’t write into the HTTP response.

That's true, but it's helpful while debugging to see the print write into the HTTP response.

Finally, when I eventually got it working the location box of the browser sadly had stuff like www.mysite.com/scgi-bin/moc/cgiappserver-prod.cgi/contact in it, whereas I really needed simply www.mysite.com/contact.

The cure was that ScriptNameStripper class in cgiappserver-prod.cgi. I got it from other Flask docs.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...