我正在构建一个执行API请求的kivy应用程序。
get_token()
函数在启动应用程序时首先运行,以获取所有必要的信息,字典,变量等。令牌在30分钟过期后,应用程序具有一个按钮,on_press会向服务器发送请求调用(如果令牌为过期了,它将无法正常工作。我正在尝试构建装饰器@use_token
,该装饰器将检查是否执行了简单请求并接收到响应200成功代码,如果成功,则返回:返回(装饰函数),否则:调用将刷新令牌的get_token
并返回装饰功能。整个概念有效,打印在每个函数中每个可能的代码块都有效,但是当令牌失效30分钟后,refresh_token()
在if语句中调用get_token()
时,打印仍在起作用,但返回修饰后的样子函数不会发送请求,它会打印测试字符串,但不会做主要的事情。这告诉我函数get_token()
在if语句中执行,但不更新令牌信息...
第一功能,在开始时运行ONES:
def get_token():
url_token = "http://server.com"
payload = "{" \
"\n \"grantType\": \"password\"," \
"\n \"password\": \"string\"," \
"\n \"refreshToken\": \"string\"," \
"\n \"token\": \"string\"," \
"\n \"username\": \"admin\"" \
"\n}"
headers = {
'Content-Type': 'application/json',
'api_key': ''
}
global readyToken
readyToken = requests.request("POST", url_token, headers=headers, data=payload).json()['token']
print("Getting a NEW TOKEN!")
get_token()
装饰功能:
def use_token(func):
@functools.wraps(func)
def refresh_token(*args):
url_check = "simplerequest.com"
response = requests.request("PUT", url_check, headers=HEADERS)
print("This print from url_check block "+str(response))
str_response = str(response)
if '401' in str_response:
print("401 found, Token is Expired, refreshing with get_token")
get_token()
else:
print("200 Code, success, passing, leaving else statement")
pass
print("emptying str_response and calling for decorated function:")
str_response = ""
return func(*args)
return refresh_token
装饰功能:
global URL_QC, HEADERS
URL_QC = "www.server.com"
HEADERS = {
'Content-Type': 'application/json',
'api_key': readyToken
}
@use_token
def change_channel(self, display_mac, ch_number):
print("Hello from DECORATED function!!!")
payload = "{\"deviceIds\": [" + str(display_mac) + "],\"menu\": \"save_sch_channel\", \"productType\": \"string\", \"value\":" + str(ch_number) + "}"
response = requests.request("PUT", URL_QC, headers=HEADERS, data=payload)
答案 0 :(得分:1)
HEADERS
更改时,您没有更新readyToken
变量。
HEADERS = {
'Content-Type': 'application/json',
'api_key': readyToken
}
在python中,字符串按值传递。因此在这里,您只需将HEADERS['api_key']
设置为readyToken
的当前值一次。如果以后更改readyToken
,则HEADERS
不会更新,因为它只保留了readyToken
的原始值。
这可以通过每次更改readyToken
中的HEADERS
来解决:
def get_token():
url_token = "http://server.com"
payload = {
"grantType": "password",
"password": "string",
"refreshToken": "string",
"token": "string",
"username": "admin"
}
headers = {
"Content-Type": 'application/json',
"api_key": ""
}
response = requests.post(url_token, headers=headers, data=payload)
print(f'Got Response: {response.json()}')
global readyToken
readyToken = response.json()['token']
# We also need to update headers!
global HEADERS
HEADERS['api_key'] = readyToken
更好的是,如果仅在HEADERS
中使用readyToken,请完全删除readyToken变量,而只需更新全局HEADERS
变量:
def get_token():
...
response = requests.post(url_token, headers=headers, data=payload)
print(f'Got Response: {response.json()}')
global HEADERS
HEADERS['api_key'] = response.json()['token']
答案 1 :(得分:0)
阿尔法Q非常感谢您,所有的猜测和修正都是正确的!我只在标头中使用令牌,因此我读取了readyToken并将令牌表达式正确放入'api_key'值中。我还重组了代码,并制作了一个实现所有修复程序的类:
token.py:
class Token:
def __init__(self):
self.url_check = "www.check.com"
self.url_token = "www.server.com"
self.payload = "{" \
"\n \"grantType\": \"password\"," \
"\n \"password\": \"password\"," \
"\n \"refreshToken\": \"string\"," \
"\n \"token\": \"string\"," \
"\n \"username\": \"admin\"" \
"\n}"
self.headers_token = {
'Content-Type': 'application/json',
'api_key': self.get_token()
}
def get_token(self):
return requests.post(self.url_token, headers=self.headers, data=self.payload).json()['token']
def use_token(self, func):
@functools.wraps(func)
def refresh_token(*args):
response = requests.put(self.url_check, headers=self.headers_token)
print("This print from url_check block: " + str(response))
if response.status_code == 200:
print('Status 200 | Token OK - No refresh necessary')
return func(*args)
elif response.status_code == 401:
print('Status 401 | Token is Expired - Refreshing')
self.get_token()
return func(*args)
else:
print(f'Status {response.status_code} | Error Occurred')
print("Print from REFRESH_TOKEN")
return refresh_token
main.py:
@token.use_token
def change_channel(self, display_mac, ch_number):
print("Hello from DECORATED function!!!")
payload = "{\"deviceIds\": [" + str(display_mac) + "],\"menu\": \"save_sch_channel\", \"productType\": \"string\", \"value\":" + str(ch_number) + "}"
response = requests.request("PUT", URL_QC, headers=token.headers_token, data=payload)
print(response)