使用延续令牌连接到Azure Datalake时出错

时间:2019-05-22 17:09:20

标签: python rest python-requests azure-data-lake

我目前正在尝试使用延续令牌(目前我们的文件夹中有5000多个文件)列出adls2内的文件/目录。我能够发送第一个请求,但是在尝试与响应中的延续令牌连接时收到403错误(可能是格式错误),并且不确定是什么格式问题会导致此错误。

我目前正在尝试删除uri密钥末尾的=符号,因为这是其他人的问题。我也尝试过为请求中的继续创建一个标头,但是没有运气。

adls_request是主要功能。这将运行两次,一次用于初始请求,第二次用于继续。目前,我已经在uri和签名中设置了延续。

def gen_signature(request_time, api_version, storage_account_name, file_system_name, storage_account_key, signature_params):
    string_params = {
        'verb': 'GET',
        'Content-Encoding': '',
        'Content-Language': '',
        'Content-Length': '',
        'Content-MD5': '',
        'Content-Type': '',
        'Date': '',
        'If-Modified-Since': '',
        'If-Match': '',
        'If-None-Match': '',
        'If-Unmodified-Since': '',
        'Range': '',
        'CanonicalizedHeaders': 'x-ms-date:' + request_time + '\nx-ms-version:' + api_version,
        'CanonicalizedResource': '/' + storage_account_name+'/'+file_system_name+signature_params
        }

    string_to_sign = (string_params['verb'] + '\n' 
                      + string_params['Content-Encoding'] + '\n'
                      + string_params['Content-Language'] + '\n'
                      + string_params['Content-Length'] + '\n'
                      + string_params['Content-MD5'] + '\n' 
                      + string_params['Content-Type'] + '\n' 
                      + string_params['Date'] + '\n' 
                      + string_params['If-Modified-Since'] + '\n'
                      + string_params['If-Match'] + '\n'
                          + string_params['If-None-Match'] + '\n'
                      + string_params['If-Unmodified-Since'] + '\n'
                      + string_params['Range'] + '\n'
                      + string_params['CanonicalizedHeaders']+'\n'
                      + string_params['CanonicalizedResource'])

    signed_string = base64.b64encode(hmac.new(base64.b64decode(storage_account_key), msg=string_to_sign.encode('utf-8'), digestmod=hashlib.sha256).digest()).decode()
    return signed_string

def create_headers(request_time, api_version, storage_account_name, signed_string):
    headers = {
        'x-ms-date' : request_time,
        'x-ms-version' : api_version,
        'Authorization' : ('SharedKey ' + storage_account_name + ':' + signed_string)
    }
    return headers

def create_url(storage_account_name, file_system_name, url_params):
    url = ('https://' + storage_account_name + '.dfs.core.windows.net/'+file_system_name+url_params)
    return url

def set_optional_params(list_dir, file_dir, token_continuation):
    if token_continuation != '':
        token_continuation_sig = '\ncontinuation:'+token_continuation
        token_continuation_url = '&continuation='+token_continuation[:-1]
    else:
        token_continuation_sig = ''
        token_continuation_url = ''
    print token_continuation_sig
    print token_continuation_url

    if list_dir:
        print type(token_continuation)
        signature_params = '\ndirectory:'+file_dir+'\nrecursive:true'+token_continuation_sig+'\nresource:filesystem'
        url_params = '?directory='+file_dir+'&recursive=true'+token_continuation_url+'&resource=filesystem'
        return signature_params, url_params
    else:
        signature_params = ''
        url_params = ''
        return signature_params, url_params


def get_request_time():
    return datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')


def adls_request(list_dir,
                 file_system_name,
                 file_dir  = '',
                 storage_account_name = 'account_name',
                 storage_account_key = '123456789==',
                 api_version = '2018-11-09',
                 token_continuation = ''):

    signature_params, url_params = set_optional_params(list_dir, file_dir, token_continuation)
    request_time = get_request_time()
    signature = gen_signature(request_time, api_version, storage_account_name, file_system_name, storage_account_key, signature_params)
    headers = create_headers(request_time, api_version, storage_account_name, signature)
    url = create_url(storage_account_name, file_system_name, url_params)
    r = requests.get(url, headers = headers)
    return r

我希望响应输出达到200,其中包含目录中的其余文件,但目前仍收到403错误。

1 个答案:

答案 0 :(得分:0)

请尝试以下代码,我使用python 3.7进行测试:

import os
os.system( "<your command> & disown " )

测试结果:

enter image description here

我的目录中有6000个文件,请注意,如果您获得延续令牌(如果目录中的文件超过5000个,否则不返回任何令牌),则应该对令牌进行编码,然后将编码的令牌添加到url中

这只是一个简单的测试,请随时更改代码以满足您的需求。