☆☆ 新着記事 ☆☆

2019年1月1日火曜日

mod_wsgiを管理する VirtualHost の配下で、2つのFlask Appを動かす

Flask APP Routingの基本:

これで、ルーティング@app.route が機能するんだよね。

mossymob.tk.conf

LoadModule wsgi_module /usr/lib64/httpd/modules/mod_wsgi.so

<VirtualHost *:80>
   ServerName mossymob.tk
   ServerAlias www.mossymob.tk
   DocumentRoot /var/www/html/firstapp
   WSGIScriptAlias / /var/www/html/firstapp/myapp.wsgi
   <Directory "/var/www/html/firstapp/">
    Options Includes ExecCGI FollowSymLinks
    Require all granted
   </Directory>
 </VirtualHost>


app.py

from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def index():
    message=" Hi, there! "
    return render_template("sample01.html", message=message)
   
@app.route('/add',methods=['POST'])
def add():
    if request.method =='POST':
        result = request.form['new_wish']
    #else:
    #    result = "No wish! Ah?"
       
    return render_template("sample02.html", result=result)
if __name__ == '__main__':
    app.run()
 
sample01.html

<html> <head>  <meta charset="utf-8"> </head>
 <body>
 {{message}}
<form action="/add" method="post"> 
<p>Input the num you like:</p>
<input type="text" name="new_wish" >
<input type="submit" value="Do">
</form>
 </body>
</html>


イメージとしては、/firstapp のディレクトリ以下で表示したいので、conf ファイルのドキュメント・ルートなどを変更してみる。


①   DocumentRoot /var/www/html/ にしただけでは相変わらず mossymob.tkにアクセスしただけでflask appが表示されてしまう。

であれば、app側の設定をかえる。

②app.py の routing decorator の変更。
   @app.route('/firstapp')
   @app.route('/firstapp/add',methods=['POST'])

これをやると, mossymob.tk にアクセスしても、mossymob.tk/firstapp にアクセスしても、両方、404 Errorになってしまう。 @app.route('/') というのは、ドキュメント・ルートを指すものだと理解していたが、そうでもないらしい。

route(rule, **options)
A decorator that is used to register a view function for a given URL rule. This does the same thing as add_url_rule() but is intended for decorator usage:
@app.route is a decorator used to match URLs to view functions in Flask apps.

としか書いていない。ちょっと良く分からない。

③WSGIScriptAlias / /var/www/html/firstapp/myapp.wsgiで、wsgiのマウンティング・ポイントを明記してみる。
WSGIScriptAlias /firstapp /var/www/html/firstapp/myapp.wsgi

すると、mossymob.tk にアクセスするとapacheのデフォルト・ページが表示されるようになった。
mossymob.tk /firstapp は、404 Error のまま。

加えて、さっきのapp.py側の
@app.route('/firstapp')
@app.route('/firstapp/add',methods=['POST'])

@app.route('/')
@app.route('/add',methods=['POST'])
に、戻す、sample01.htmlは上手く表示できるようになった。 

表示されるsample01.htmlに数字を入れて送信(post)すると、mossymob.tk/addに遷移してしまうので、@app.route('/firstapp/add',methods=['POST']) に変更してみる。

それでも、mossymob.tk/addに遷移してしまう。 もちろん、404 Error。

sample01.htmlの
<form action="/add" method="post">               も、
<form action="/firstapp/add" method="post"> に、

変更してみるも、やっぱりダメだよ。 mossymob.tk/addに移ってしまう。

(この設定で、mossymob.tk/add に移るか、mossymob.tk/firstapp/addに移るかは不安定だね。
 何か、読み込む順番でも影響するのだろうか?

むむ、mossymob.tk/firstapp/add に遷移する場合もある。(というか、ほぼ/firstapp/addに移る) でも、flaskからrender_templateを機能させてsample02.htmlを呼び出せたりはしない。

では、form action ="/firstapp/app.py" として、ファイルそのものを呼びだしてみる。

すると、「http://mossymob.tk/firstapp/app.py」に遷移するのだが、これもsample02.htmlを呼び出したりはできない。

このpost後のurlをどうするか、については、
https://github.com/jeff1evesque/machine-learning/issues/20
に、長いback and forceの末、未解決のまま放置されているスレッドがある。 
(2014年。 結局、phpで受けるようにしたようだ、)

こんなのもある。 
ここで、自分がトライしている方法をリコメンドしている。 いや、それをやっても、動きませんから。

https://stackoverflow.com/questions/48589360/404-requested-url-not-found-flask-app-on-apache
Yes, presumably because your form is posting to a URL that isn't under the root path. As I say, the best thing to do is to host your app under /, not under /flasktest.


form action から送られてきているルーティングの処理に、みんなが困っているようなので、
もう少し、細かくやってみる。

What is an 'endpoint' in Flask?

@app.route('/greeting/<name>')
def give_greeting(name):
    return 'Hello, {0}!'.format(name)

と、いかは同じなのだそうだ。

def give_greeting(name):
    return 'Hello, {0}!'.format(name)
app.add_url_rule('/greeting/<name>', 'give_greeting', give_greeting)

app.add_url_rule
http://flask.pocoo.org/docs/1.0/api/

add_url_rule(rule, endpoint=None, view_func=None, options)

なので
@app.route('/firstapp/add',methods=['POST'])
def add():
    if request.method =='POST':
        result = request.form['new_wish']
    else:
        result = "Function add() is alive, but not a intended way."
    return render_template("sample02.html", result=result)

は、

def add():
    if request.method =='POST':
        result = request.form['new_wish']
    else:
        result = "Function add() is alive, but not a intended way."
    return render_template("sample02.html", result=result)
app.add_url_rule('/firstapp/add', 'firstapp', add, methods=['POST'])


だめだね。

http://werkzeug.pocoo.org/docs/0.14/routing/#werkzeug.routing.Rule

も、あるけど、ここまでは。

こんな基本的なことなのに、こんなに苦労するなら、
どうもFlaskというのが、選択ミスのような気がしてきた。


<そうだ、絶対パスで書いてみよう。>
@app.route('/firstapp')
@app.route('/firstapp/add',methods=['POST'])
<form action ="/firstapp/add">

と、パスを指定する箇所は3か所あるけど、<form action>は、form の submit button押下時のリダイレクトするURLだから、これは上手く機能しているとして、
@app.route('/firstapp/add',methods=['POST'])
を、絶対パスで書いてみる。

そんなの、やっぱりダメだようねー。


<-----諦めようと思ったその時、できたーーーーー。----->

conf.


LoadModule wsgi_module /usr/lib64/httpd/modules/mod_wsgi.so
 <VirtualHost *:80>
   ServerName mossymob.tk
   ServerAlias www.mossymob.tk
   WSGIScriptAlias /firstapp /var/www/html/firstapp/myapp.wsgi
   <Directory "/var/www/html/firstapp/">
    Options Includes ExecCGI FollowSymLinks
    Require all granted
   </Directory>
   CustomLog /var/www/html/access.log common
   ErrorLog /var/www/html/error.log
   LogLevel info
 </VirtualHost>
 

app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def index():
    message="Hi, There!"
    return render_template("sample01.html", message=message)

@app.route('/add',methods=['POST'])
def add():
    if request.method =='POST':
        result = request.form['new_wish']
    else:
        result = "Function add() is alive, but not a intended way."
    return render_template("sample02.html", result=result)

if __name__ == '__main__':
    app.run(debug=true)


<html>
 <head>
   <meta charset="utf-8">
 </head>
 <body>
 {{message}}
<form action="/firstapp/add" method="post">
<p>Input the num you like:</p>
<input type="text" name="new_wish" >
<input type="submit" value="Do">
</form>
 </body>
</html>

終わってみれば、このパターンを試してないのがおかしい!というようなものですね。
結論としては、htmlのフォームのアクションを書き換えるくらいですね


良かったーーーー。

3日以上かかってるなー。 確実に。


因みに、
WSGIScriptAlias /firstapp /var/www/html/firstapp/myapp.wsgi
エンドポイント(/firstapp) を明記しないで、 / だけにすると上手くいかない
ここも大事ですね。






(以下は、全て検証過程のメモです。 不要です。)

LoadModule wsgi_module /usr/lib64/httpd/modules/mod_wsgi.so

 <VirtualHost *:80>
    ServerName mossymob.tk

    DocumentRoot /var/www/html/firstapp
    WSGIDaemonProcess first
    WSGIScriptAlias /firstapp /var/www/html/firstapp/myapp.wsgi
    <Location /firstapp>
     WSGIProcessGroup first
    </Location>
    <Directory "/var/www/html/firstapp">
     Require all granted
    </Directory>

    DocumentRoot /var/www/html/secondapp
    WSGIDaemonProcess second
    WSGIScriptAlias /secondapp /var/www/html/secondapp/myapp.wsgi
    <Location /secondapp>
     WSGIProcessGroup second
    </Location>
    <Directory "/var/www/html/secondapp/">
     Options Includes ExecCGI FollowSymLinks
     Require all granted
    </Directory>
  </VirtualHost>

<app.py>

from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def index():
    message="Hi, Charlie!"
    return render_template("sample01.html", message=message)

@app.route('/var/www/html/secondapp/add',methods=['POST'])
def add():
    if request.method =='POST':
        result = request.form['new_wish']
    #else:
    #    result = "No wish! Ah?"
    return render_template("sample02.html", result=result)
if __name__ == '__main__':
    app.run()




<templates 配下の sample01.html>

<html>
 <head>
   <meta charset="utf-8">
 </head>
 <body>
 {{message}}
<form action="/secondapp/add" method="post">
<p>Input new make you wish to add to the list:</p>
<input type="text" name="new_wish" >
<input type="submit" value="Do">
</form>
 </body>
</html>

これを実行すると、directoryが http://mossymob.tk/addに飛んでしまう。

<app.pyの変更>
1) @app.route('/secondapp/add/',methods=['POST'])
http://mossymob.tk/add
404
2)


========この設定で、secondapp/add までは出るけど405 error ========

http://mossymob.tk/secondapp/add (404Error)

LoadModule wsgi_module /usr/lib64/httpd/modules/mod_wsgi.so

  <VirtualHost *:80>
    ServerName mossymob.tk

    DocumentRoot /var/www/html/firstapp
   
    WSGIDaemonProcess first
    WSGIScriptAlias /firstapp /var/www/html/firstapp/myapp.wsgi

    <Location /firstapp>
     WSGIProcessGroup first
    </Location>

    <Directory "/var/www/html/firstapp">
     Require all granted
    </Directory>

    DocumentRoot /var/www/html/secondapp

    WSGIDaemonProcess second
    WSGIScriptAlias /secondapp /var/www/html/secondapp/myapp.wsgi

    <Location /secondapp>
     WSGIProcessGroup second
    </Location>

    <Directory "/var/www/html/secondapp/">
     Options Includes ExecCGI FollowSymLinks
     Require all granted
    </Directory>
  </VirtualHost>

**app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def index():
    message="Hi, Charlie!"
    return render_template("sample01.html", message=message)
   
@app.route('/secondapp/add',methods=['POST'])
def add():
    if request.method =='POST':
        result = request.form['new_wish']
    #else:
    #    result = "No wish! Ah?"
       
    return render_template("sample02.html", result=result)
if __name__ == '__main__':
    app.run()
**sample01.ht<html>
 <head>
   <meta charset="utf-8">
 </head>
 <body>
 {{message}}
<form action="/secondapp/add" method="post"> 
<p>Input new make you wish to add to the list:</p>
<input type="text" name="new_wish" >
<input type="submit" value="Do">
</form>
 </body>
</html>

**sample02.html
<html> <head>   <meta charset="utf-8"> </head>
 <body>
<p>Now we know the brand of the car you want is</p>
{{result}}
 </body>
</html>

WSGIApplicationGroup %{GLOBAL}
that would have the effect of forcing each to run in the same sub interpreter instance, and specifically the main interpreter instance for the value of %{GLOBAL}.
That they are running in the same sub interpreter instance isn’t an issue as far as Flask is concerned as each Flask application doesn’t rely on any shared common data.
In case you have this setting, it sounds like your two separate Flask applications are being run within the same sub interpreter instance of mod_wsgi rather than in separate instances as would normally be the case.
https://discuss.newrelic.com/t/support-multiple-configurations-applications-on-the-same-machine/3745/3

0 件のコメント:

コメントを投稿