【问题标题】:Backslashes are not correctly encoded反斜杠未正确编码
【发布时间】:2021-07-23 15:29:15
【问题描述】:

我已经束手无策了。

我的情况是我正在使用 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 请求:

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)

【问题讨论】:

  • 您确定在您创建服务时由于缺少反斜杠而没有出现问题吗?您可能使用换行符而不是反斜杠创建了服务。 Icinga 是否有可用于检索实际服务名称的 API?
  • 当然,我创建了服务(在 API 之外)并通过 API 读取服务。服务以“\”显示。

标签: python-requests icinga2


【解决方案1】:

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

Python 将字符串中的反斜杠视为特殊字符,在字符串前添加一个 'r' 使其不将其视为特殊字符,而是将其视为反斜杠 '过滤器': 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\\"'

【讨论】:

  • 同样的错误。将你的提案带入正文 (body1) 并将其与我的正文 (body2) 进行比较。在python cli中:body1 == body2 >>> True
  • 真的吗?当我在我的 CLI 中进行直接比较时,它说它们不相等
【解决方案2】:

非常感谢您的支持。我想到了。我能够使用 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")

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    • 1970-01-01
    • 1970-01-01
    • 2015-05-26
    • 2021-12-31
    • 1970-01-01
    相关资源
    最近更新 更多