0
0

More than 5 years have passed since last update.

Flaskでクエリストリングを獲得する際に、思った値が取れない原因と対策

Last updated at Posted at 2019-05-03

はじめに

Flaskを使っているときにGETやPOSTで想定通りのパラメータを取得することができず1時間くらい右往左往したため、忘記録として記述しておく。

問題が起きたプログラム

問題となったのは、パラメータlで受け取ったURLにリダイレクトするだけの以下のAPI。
なお粗末なプログラムですが、GitHubで公開しているので興味のある方はどうぞ。

import string
from flask import Flask, request


HTML = '''\
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>redirect</title>
<meta http-equiv="refresh" content="0; URL='${link}'" />
</head>
<body>
    このページは自動的に転送されます。<br>
    転送されない場合は<a href="${link}">こちら</a>をクリックしてください
</body>
</html>
'''

app = Flask(__name__)


@app.route('/')
def index():
    link = request.args.get('l', '')
    assert link, 'Cannot get l parameter querystring'
    return string.Template(HTML).substitute({'link': link})

上記のWebアプリをhtml://hoge.com/r/に配置して、パラメータlに適当なURLを与えてやる。たとえば、次のような感じで使うことを想定している。

http://hoge.com/r/?l=http:fuga.com/

問題と原因

パラメータlに色々なURLを放り込んでみるが、クエリを持つURLを与えると思った通りのリダイレクトをしてくれない。たとえば、以下のような感じ。

html://hoge.com/r/?l=http:fuga.com/?q=1&date=20190501

問題は明らかで、与えたl内に?や&が入っていること。解決するにはなんとかこれを消してやればよい。
replaceなどの力技も可能だが、極力スマートにやりたい。(あとAPI側をいじりたくない

解決策

リダイレクト先のURLを作ったあとにurllib.parse.quoteをかけてやることで解決する。

import urllib

target = 'http:fuga.com/?q=1&date=20190501'
return 'html://hoge.com/r/?l=' + urllib.parse.quote(target)

これでlで指定したURL(パラメータ付き)に正しくアクセスできる。
あとAPI側での修正は必要ない。よしなにデコードしてくれるようだ。

おまけ

実はこのurllib.parse.quoteは非常に便利で、たとえば、クロールしてきたWebページを保存するときに、そのURLをエンコードしてやることでファイル名として扱えたりできる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0