【问题标题】:Adding Data to urllib2.Request向 urllib2.Request 添加数据
【发布时间】:2012-12-19 20:23:29
【问题描述】:

朋友。

我正在编写一个简短的脚本,它将获取一个人的 Github 登录名并使用它来查询 Github API 以获取授权令牌。代码如下:

def getGithubAuth():
    "Get a Github auth token and return it"
    gist_data = json.dumps({"scopes":["gist"]})
    req = urllib2.Request(auth_url)
    base64str = base64.encodestring("%s:%s" % \
        (github_user, github_pass)).replace('\n','') # user/pass vars are declared elsewhere
    req.add_header("Authorization", "Basic %s" % base64str);
    req.add_data(gist_data) # <- including this makes problems

    try:
        response = urllib2.urlopen(req)
    except urllib2.URLError, e:
        print "Something broke connecting to Github: %s" % e
        return None

    if response.getcode() == 200:
        jresp = json.loads('\n'.join(response.readlines()))[0]
        return jresp['token']
    return None 

如果我删除了add_data 调用,请求将起作用并返回一个身份验证令牌。问题是,我需要包含传递给 add_data 的数据,以便接收能够与 Github 的 gist 工具交互的身份验证令牌。

我的两个问题

  1. 如何将此数据添加到我的请求中,以便 Github 识别并接受它?
  2. 我预计很快会发现自己处于类似情况,需要发送大量数据;我将如何传递一组更复杂的值(例如带有嵌套值的大型字典等)?

我的尝试

我发现一些互联网上的东西说我应该在发送值之前使用urllib.urlencode 对值进行编码,但是我无法完成这项工作,因为scopes 需要一个列表而urlencode 需要一个列表元组列表。

我 100% 确定我在这里做了一些愚蠢的事情,所以如果你能告诉我那是什么,我将不胜感激 :)

谢谢——如果提供更多信息会使回答更容易,请告诉我。

【问题讨论】:

  • 你遇到了什么错误?
  • 当我在add_data 中包含这些内容时,API 会返回 404“未找到”错误。如果省略 add_data,我会得到 200。

标签: python github urllib2 github-api


【解决方案1】:

基本上,您所做的一切都是正确的。我试过你的代码,它工作正常,稍作修改。

会发生什么:

当您不包含数据时,发出的请求实际上是一个 GET 请求,它获取授权列表。这不是您想要的,因为它不会创建新的授权。

当您确实包含数据时,发出的请求是一个 POST 请求,这正是您想要的。但是,返回的状态码不是 200,而是 201。因此,只需修改代码以检查 201 并从 JSON 正文中获取令牌。

【讨论】:

  • (我为我的第一个回复道歉,我完全编辑了它——我犯了和你一样的错误——假设回复是 200,而不是 201)
【解决方案2】:

使用requests 会更好一些:

app_name = 'your_app'

import requests, json

def create_github_oauth_token(user, password):

    # Check there isn't already an auth code for your app:
    r = requests.get('https://api.github.com/authorizations',
        auth=(user, password))
    for auth in r.json():
        if auth['note'] == app_name \
            and 'repo' in auth['scopes']:
            print "Retrieving existing token"
            print json.dumps(auth, indent=4)
            return auth['token']

    print "Creating new token"
    # Otherwise create a new token
    r = requests.post('https://api.github.com/authorizations',
        data=json.dumps({
            'scopes':['repo'],
            'note':app_name
            }),
        headers={'content-type':'application/json'},
        auth=(user, password)
    )
    return r.json()['token']

【讨论】:

    猜你喜欢
    • 2016-07-01
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    相关资源
    最近更新 更多