Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

flask

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

like image 382
Sebastian Bechtel Avatar asked Aug 15 '13 18:08

Sebastian Bechtel


People also ask

How do I deploy Flask app on localhost?

To install flask, simply type in pip install flask in your computer terminal/command line. Once you have made sure flask is installed, simply run the hello.py script. Once you run the script, the website should now be up and running on your local machine, and it can be viewed by visiting localhost:5000 in your browser.


2 Answers

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.

like image 182
Mike O'Connor Avatar answered Oct 27 '22 09:10

Mike O'Connor


I found a solution! I left the /$1 away from my .htaccess and modified werkzeug a bit because the environment variables in CGI are named a bit different the in WSGI applications. I'll inform the werkzeug developer about it and maybe he'll include my solution into werkzeug.

like image 37
Sebastian Bechtel Avatar answered Oct 27 '22 10:10

Sebastian Bechtel