强制内容类型或在Flask中公开request.data以获取已知内容类型

时间:2011-08-16 23:42:53

标签: python base64 content-type flask

我正在Python / Flask中重新创建一个服务,并且遇到了现有客户端验证方式的问题。出于兼容性原因,我必须匹配现有的客户端方案。

现有客户端使用用户名,密码和base64对其进行编码。尽管声音相似,但这不是HTTP基本身份验证。下面是一些创建此登录请求的示例代码。

credentials = {
            'username': 'test@example.com',
            'password': 'password'
}
data = b64encode(urlencode(credentials))
request = urllib2.Request(loginURL)
request.add_data(data)
# request.add_header('Content-Type', 'application/gooblygop')
# 'application/x-www-form-urlencoded' seems to be a default Content-Type
login = urllib2.urlopen(request)

在服务器端,我接受POST数据并对其进行解码,以便再次获取用户名和密码信息。

flask server:
@app.route('/login', methods=['POST'])
def login():
    error = None
    if request.method == 'POST':
        # post data: cGFzc3dvcmQ9ZGVmYXVsdCZlbWFpbD10ZXN0JTQwZXhhbXBsZS5jb20=
        data = b64decode(request.data)
        # decoded data: password=default&email=test%40example.com
        return('ok')

问题是内容类型。如果我在客户端(application / gooblygop)中指定了未知的Content-Type,Flask会将POST数据暴露给request.data,我可以解码base64字符串。如果我将Content-Type保留为默认值(application / x-www-form-urlencoded),原始数据不会暴露给request.data,我不知道如何检索base64编码的字符串并使用它。

现有的客户端软件几乎默认为x-www-form-urlencoded,但我不能完全依赖于这种情况。

基本上,无论客户端程序指出什么Content-Type,我都需要一个可靠的服务器端方法来访问该编码字符串。

其他说明:我是Python的新手,来自PHP背景。所以我对建议很开放。此外,该项目主要供个人使用。

2 个答案:

答案 0 :(得分:2)

您希望在处理具有正常mimetypes的urlencoded帖子时查看request.form对象。在这种情况下,你有一个不寻常的形式,但这是一种方法:

# mkreq.py
from urllib import urlencode
import urllib2
from base64 import b64encode

credentials = {
            'username': 'test@example.com',
            'password': 'password'
}
data = b64encode(urlencode(credentials))
request = urllib2.Request("http://localhost:5000/login")
request.add_data(data)
request.add_header('Content-Type', 'application/gooblygop')
# 'application/x-www-form-urlencoded' seems to be a default Content-Type
login1 = urllib2.urlopen(request).read()
print(login1)
request2 = urllib2.Request("http://localhost:5000/login")
request2.add_data(data)
login2 = urllib2.urlopen(request2).read()
print(login2)

您可能希望修改登录位以检查mimetype,这是一个对当前设置进行最小更改的版本:

@app.route('/login', methods=['POST'])
def login():
    error = None
    if request.method == 'POST':
        # post data: cGFzc3dvcmQ9ZGVmYXVsdCZlbWFpbD10ZXN0JTQwZXhhbXBsZS5jb20=
        data = b64decode(request.data)
        # decoded data: password=default&email=test%40example.com
        if not data:
            data = b64decode(request.form.keys()[0])
        special_mimetype = request.mimetype
        return(special_mimetype + '\n' + data)

这是第一个代码示例的输出,有两个请求:

bvm$ python mkreq.py
application/gooblygop
username=test%40example.com&password=password
application/x-www-form-urlencoded
username=test%40example.com&password=password

答案 1 :(得分:1)

您是否考虑过使用json在POST中传递数据? Flask内置了对传递json数据的支持。另外,如果你将标题中的Content-Type设置为application / json,那么flask将自动为你删除POST数据并将其放入request.json

这是请求申请

import urllib2
import json

if __name__ == "__main__":
  headers = {'Content-Type':'application/json'}
  post_data = {"user":"test_user"}
  print "Posting request"
  req = urllib2.Request("http://localhost:5000/login", json.dumps(post_data), headers)
  resp = urllib2.urlopen(req)
  print "Response was %s" % resp.read()  

这是Flask视图

from flask import request

@app.route('/login', methods=['POST'])
 def login():

  user = request.json['user']
  return user

如果您使用的是linux终端,我建议您使用curl进行测试。这是一个例子

curl -X POST -H "Content-Type:application/json" -s -d '{"user":"This is the username"}' 'localhost:5000/login'

This is the username