当 url 作为参数传递时 Flask urllib 403 错误,但在 hard-coded 或浏览器上有效

Flask urllib 403 error when url passed as parameter, but works when hard-coded or on browser

我正在尝试通过 Flask 应用从 Firebase 存储下载文件。

目标 URL 在浏览器上工作 并且 当我对它进行硬编码时 .

但是,当我从前端传递目标 URL 作为参数时,它说 urllib.error.HTTPError: HTTP Error 403: Forbidden.

前端代码(JavaScript)

      async function testTriggerLocalFunction(downloadURL) {
        const response = await fetch(
        // downloadURL is a string like "https://firebasestorage.googleapis.com...."
          "http://127.0.0.1:5001?audioURL=" + downloadURL
        );
        // console.log(response);
      }

后端代码(Flask)

@app.route('/')
def handle_request():
    result = analyze(request.args.get("audioURL"))

def analyze(audioURL):
    # Download sound file
    # url = audioURL
    input_name = "input.wav"
    input_path = get_file_path(input_name)

    # 403 error when audioURL passed from url parameter passed!
    urllib.request.urlretrieve(audioURL, input_path)
    # But it will work if I do something like "audioURL = "https://firebasestorage.googleapis.com...."

可能的错误点

  1. 可能您缺少适当的授权?
  2. 可能你缺少合适的header?
  1. URL 编码?

还有什么可能导致此问题?

127.0.0.1 - - [09/Dec/2021 14:08:59] "GET /?audioURL=https://firebasestorage.googleapis.com/MY_TARGET_AUDIO_URL" 500 -
Traceback (most recent call last):
  File "/Users/leochoo/.virtualenvs/py-vocal-journal/lib/python3.9/site-packages/flask/app.py", line 2091, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/leochoo/.virtualenvs/py-vocal-journal/lib/python3.9/site-packages/flask/app.py", line 2076, in wsgi_app
    response = self.handle_exception(e)
  File "/Users/leochoo/.virtualenvs/py-vocal-journal/lib/python3.9/site-packages/flask/app.py", line 2073, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/leochoo/.virtualenvs/py-vocal-journal/lib/python3.9/site-packages/flask/app.py", line 1518, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/leochoo/.virtualenvs/py-vocal-journal/lib/python3.9/site-packages/flask/app.py", line 1516, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/leochoo/.virtualenvs/py-vocal-journal/lib/python3.9/site-packages/flask/app.py", line 1502, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/Users/leochoo/dev/vocal-journal/backend/playground/py-vocal-journal/app.py", line 68, in handle_request
    result = analyze(request.args.get("audioURL"))
  File "/Users/leochoo/dev/vocal-journal/backend/playground/py-vocal-journal/app.py", line 98, in analyze
    urllib.request.urlretrieve(audioURL, input_path)
  File "/Users/leochoo/.pyenv/versions/3.9.1/lib/python3.9/urllib/request.py", line 239, in urlretrieve
    with contextlib.closing(urlopen(url, data)) as fp:
  File "/Users/leochoo/.pyenv/versions/3.9.1/lib/python3.9/urllib/request.py", line 214, in urlopen
    return opener.open(url, data, timeout)
  File "/Users/leochoo/.pyenv/versions/3.9.1/lib/python3.9/urllib/request.py", line 523, in open
    response = meth(req, response)
  File "/Users/leochoo/.pyenv/versions/3.9.1/lib/python3.9/urllib/request.py", line 632, in http_response
    response = self.parent.error(
  File "/Users/leochoo/.pyenv/versions/3.9.1/lib/python3.9/urllib/request.py", line 561, in error
    return self._call_chain(*args)
  File "/Users/leochoo/.pyenv/versions/3.9.1/lib/python3.9/urllib/request.py", line 494, in _call_chain
    result = func(*args)
  File "/Users/leochoo/.pyenv/versions/3.9.1/lib/python3.9/urllib/request.py", line 641, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden

我看过类似的问题,但我找不到适合我的情况的解决方案。

403 error when passing url as a parameter

有几种方法可以做到这一点,因为 ?audioURL={url} 参数作为两个参数,因为它包含一个 & 符号:

  1. 合并在 python 服务器代码上接收的两个查询参数,而不是您打算通过的单个参数

  2. 在客户端使用 base64 对 audioURL 数据变量进行编码,然后在服务器端进行解码以保留扰乱查询参数格式的特殊字符

很高兴帮到你!