微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

反斜杠编码不正确

如何解决反斜杠编码不正确

我不知所措。

我的场景是我使用 python 请求与 Icinga2 API 交互,并且我正在尝试安排停机时间。所以我知道它应该如何工作,并且大部分时间都有效。但不幸的是,当 Icinga2 服务尝试设置停机时间以使其名称中带有反斜杠时,我完全不走运。

我的测试环境:

  • Icinga2 2.9.0
  • Python 3.6.8/Python 3.8.11
  • 请求 2.27.0

先决条件:在 Icinga 中创建一个主机。在 Icinga 中创建一个带有“\”字符的服务。

用于复制的 Python 代码

import requests
session = requests.Session()
session.hooks = {
             "response": lambda r,*args,**kwargs: r.raise_for_status()
         }

session.headers.update(
             {
                 "Accept": "application/json","Content-Type": "application/json","cache-control": "no-cache",}
         )

session.auth = requests.auth.HTTPBasicAuth("user","password")
url = "https://icinga2-server.com:5665/v1/actions/schedule-downtime"

body = {
   'comment': 'Downtime','author': ('icingaadmin',),'start_time': 1605196800.0,'filter': 'host.name==\"HOSTNAME\" && service.name==\"SERVICE\\NAME\"','end_time': 1605286800.0,'fixed': True,'type': 'Service'}

session.post(url,json=body,verify=False)

结果:

Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
  File "/root/.pyenv/versions/3.8.11/lib/python3.8/site-packages/requests/sessions.py",line 590,in post
    return self.request('POST',url,data=data,json=json,**kwargs)
  File "/root/.pyenv/versions/3.8.11/lib/python3.8/site-packages/requests/sessions.py",line 542,in request
    resp = self.send(prep,**send_kwargs)
  File "/root/.pyenv/versions/3.8.11/lib/python3.8/site-packages/requests/sessions.py",line 662,in send
    r = dispatch_hook('response',hooks,r,**kwargs)
  File "/root/.pyenv/versions/3.8.11/lib/python3.8/site-packages/requests/hooks.py",line 31,in dispatch_hook
    _hook_data = hook(hook_data,**kwargs)
  File "<stdin>",line 2,in <lambda>
  File "/root/.pyenv/versions/3.8.11/lib/python3.8/site-packages/requests/models.py",line 953,in raise_for_status
    raise HTTPError(http_error_msg,response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://icinga2-server.com:5665/v1/actions/schedule-downtime

我很清楚此错误消息表明 Icinga2 无法找到/匹配服务。但是通过 curl 执行命令显然对我有用,而且我得到了适当的预定停机时间!

卷曲请求:

curl -k -s -u user:password -H 'Accept: application/json'  -X POST 'https://icinga2-server.com:5665/v1/actions/schedule-downtime'  -d '{"comment": "Downtime","author": ["icingaadmin"],"start_time": 1605196800.0,"filter": "host.name==\"MSsqlSERVER\" && service.name==\"MSsqlSERVER\\\\INSTANCE2\"","end_time": 1605286800.0,"fixed": true,"type": "Service"}'

卷曲答案(成功):

{"results":[{"code":200.0,"legacy_id":8.0,"name":"MSsqlSERVER!MSsqlSERVER\\INSTANCE2!137c9ef9-3150-4e57-ba0b-a22ddc6611d4","status":"Successfully scheduled downtime 'MSsqlSERVER!MSsqlSERVER\\INSTANCE2!137c9ef9-3150-4e57-ba0b-a22ddc6611d4' for object 'MSsqlSERVER!MSsqlSERVER\\INSTANCE2'."}]}

没有帮助的替代方法

session.post(url,data=json.dumps(body),verify=False)

string_body = json.dumps(body)
session.post(url,data=string_body,verify=False)

解决方法

您可以尝试在过滤键后的字符串前面添加一个 r。另外,我认为这个闭括号是不必要的。

Python 将字符串中的反斜杠视为特殊字符,在字符串前添加 'r' 使其不会将它们视为特殊字符,而是将其视为反斜杠 'filter': r'host.name=="HOSTNAME" && service.name=="SERVICE\NAME"'),

https://www.journaldev.com/23598/python-raw-string

body1 = {
   'comment': 'Downtime','author': ('icingaadmin',),'start_time': 1605196800.0,'filter': 'host.name==\"HOSTNAME\" && service.name==\"SERVICE\\NAME\"','end_time': 1605286800.0,'fixed': True,'type': 'Service'}

body2 = {
   'comment': 'Downtime','filter': r'host.name==\"HOSTNAME\" && service.name==\"SERVICE\\NAME\"','type': 'Service'}

body1==body2 -> False

body1['filter'] = 'host.name=="HOSTNAME" && service.name=="SERVICE\\NAME"'

body2['filter'] = 'host.name==\\"HOSTNAME\\" && service.name==\\"SERVICE\\\\NAME\\"'
,

非常感谢您的支持。我想到了。我能够使用 Leo Wotzak 击败我的以下命令成功设置停机时间。

body1 = {
   'comment': 'Downtime','filter': 'host.name==\"HOSTNAME\" && service.name==\"SERVICE\\\\NAME\"','type': 'Service'}

我不知道为什么我没有早先用 4 个反斜杠运行测试。

并为这种情况添加一些背景。最初的问题是,我正在读取可用的 icinga 服务的输出,这给了我:

>>>> resp.json()['results'][1]['name']
'MSSQLSERVER!SERVICE\\NAME'

如果我将该答案放入正文,它将失败,因为 json 转换器不会将 2 个反斜杠转换为 4 个反斜杠。问题是,告诉 json 2 个反斜杠需要 4 个反斜杠的最佳方法是什么?我的想法是使用编码:

svc_name = resp.json()['results'][1]['name'].encode("unicode-escape").decode("utf-8")

我不知道这是否是最好的方法,但它有效。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。