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

前端 未结 3 433
暗喜
暗喜 2020-12-03 01:59

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 m

相关标签:
3条回答
  • 2020-12-03 02:29

    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.

    0 讨论(0)
  • 2020-12-03 02:48

    I will try to show what I've done and it is working in Godaddy sharing host account:

    In the cgi-bin folder in MYSITE folder, I added the following cgi file:

    #!/home/USERNAME/.local/bin/python3
    from wsgiref.handlers import CGIHandler
    
    from sys import path
    path.insert(0, '/home/USERNAME/public_html/MYSITE/')
    from __init__ import app
    
    class ProxyFix(object):
       def __init__(self, app):
           self.app = app
    
       def __call__(self, environ, start_response):
           environ['SERVER_NAME'] = ""
           environ['SERVER_PORT'] = "80"
           environ['REQUEST_METHOD'] = "GET"
           environ['SCRIPT_NAME'] = ""
           environ['PATH_INFO'] = "/"
           environ['QUERY_STRING'] = ""
           environ['SERVER_PROTOCOL'] = "HTTP/1.1"
           return self.app(environ, start_response)
    
    if __name__ == '__main__':
        app.wsgi_app = ProxyFix(app.wsgi_app)
        CGIHandler().run(app)
    

    As you can see the init file in the MYSITE folder have the flask app.

    The most important thing is to set the permissions right. I setted 755 to this folder permission AS WELL AS to "/home/USERNAME/.local/bin/python3" folder!! Remember that the system needs this permission to open flask and all python packages.

    For debugging I recommend visiting via ssh terminal your site and just run the CGI alone. If it works, but in the web don't, it means probably you need to give more permissions or you wrote wrong the .htaccess file.

    To open the cgi I have the following .htaccess file in MYSITE folder:

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f 
    RewriteRule ^(.*)$ /home/USERNAME/public_html/MYSITE/cgi-bin/application.cgi/$1 [L]
    

    So it will render the cgi file when someone enters your page.

    0 讨论(0)
  • 2020-12-03 02:52

    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.

    0 讨论(0)
提交回复
热议问题