反斜杠编码不正确

Backslashes are not correctly encoded

我已经无计可施了

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

我的测试环境:

先决条件:在 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 无法 find/match 服务。但是通过 curl 执行命令显然对我有用,我得到了适当的计划停机时间!

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"}'

CURL 答案(成功):

{"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',
    'author': ('icingaadmin',),
    'start_time': 1605196800.0,
    'filter': r'host.name==\"HOSTNAME\" && service.name==\"SERVICE\NAME\"',
    'end_time': 1605286800.0,
    'fixed': True,
    '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',
    'author': ('icingaadmin',),
    'start_time': 1605196800.0,
    'filter': 'host.name==\"HOSTNAME\" && service.name==\"SERVICE\\NAME\"',
    'end_time': 1605286800.0,
    'fixed': True,
    '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")

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