Отправить XML-файл в REST API в Python3 - PullRequest
0 голосов
/ 11 мая 2018

Я пытаюсь взаимодействовать с REST API с помощью библиотеки requests.

Мне нужно передать большой XML-файл в API - я могу легко сделать это с помощью curl в Linux, но я хочу сделать это с помощью pythonic.

В curl мой синтаксис выглядит следующим образом:

curl -k https://10.244.1.2:4444/webconsole/APIController? -F "reqxml=MYxml.xml"

Примечание: флаг -k просто игнорирует ошибку ssl

Итак, вот что я придумал:

import requests    
url = r'https://10.244.1.2:4444/webconsole/APIController?reqxml='    
x = open('MYxml.xml', 'r').read()

q = requests.post(url, data=x, verify=False)    
print(q.text)

Если я изменю эту переменную q на эту: q = requests.post(url + x, verify=False), тогда команда будет работать.Однако с более длинными XML-файлами это не удастся.

Я просмотрел эти два связанных поста: Первый , Второй , но предложения выглядят так же, как мой синтаксис, если я не пропускаю что-то очевидное

Любая помощь приветствуется!

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Хорошо, это потребовало много проб и ошибок, чтобы выяснить правильные части здесь, но я наконец понял это. Ответ @Brennen Sprimont очень помог в понимании того, что делал cURL.

Как он указал - cURL фактически отправлял полный файл, а мои первоначальные запросы не были.

Моя первая подсказка пришла с сайта, который я нашел, который конвертирует команды cURL в python - Ссылка

Когда я поместил свою команду cURL на этот сайт, она вернула это как часть результата:

data = {'reqxml' : (None, open(xml_file, 'rb'))} ( примечание: в своем вопросе я использовал 'x', но здесь я использовал 'data' для этой переменной )

Параметр None отсутствовал в моем оригинале - также я сейчас читаю двоичный файл.

Моя следующая главная проблема заключалась в том, как я передавал файл - когда я выполняю это из браузера, синтаксис:

https://<ipaddress><port>/webconsole/APIController?reqxml=<Login></Login>

Здесь мы можем видеть данные, определенные атрибутом reqxml=

В cURL это выглядит следующим образом:

curl -k https://10.244.1.2:4444/webconsole/APIController? -F "reqxml=MYxml.xml"

Там мы можем указать, что атрибут фактически не передается в URL, а с файлом

Последней ошибкой, которую я сделал, была попытка передать атрибут reqxml со знаком '='. В отличие от cURL или через браузер, запросы не хотят этого. В этом случае он хотел, чтобы значения передавались в виде словаря без символа равенства.

Ниже приведена небольшая функция, которую я использовал для тестирования и работает с Sophos XG v17

data_file = 'Myxml.xml'
ipaddress = '10.244.1.2'

def api_call(api_ip, xml_file):
    api_url = r'https://{}:4444/webconsole/APIController?'.format(api_ip)
    data = {'reqxml' : (None, open(xml_file, 'rb'))}
    r = requests.post(api_url, files=data, verify=False)   
    print(r.text)

api_call(ipaddress, data_file)
0 голосов
/ 12 мая 2018

(перемещение обсуждения комментариев в ответ)

Взаимодействие с веб-серверами, у которых нет хорошей документации или служб отчетов об ошибках, - это всегда боль.

Однако, если у вас есть методэто работает (команда curl), у вас есть нога в дверь.curl имеет флаг -v, который можно использовать для просмотра заголовков, отправленных с полезной нагрузкой.

Кроме того, просматривая команду curl, вы отправляете весь файл заново.Принимая во внимание, что ваш скрипт на python считывает данные в текстовую строку и отправляет их.

Если веб-сервер принимает данные XML, вам может понадобиться просто добавить заголовок типа содержимого XML и посмотреть, работает ли он:

q = requests.post(url, data=x, verify=False, headers={"Content-Type":"application/xml"})

В противном случае, если веб-сервер принимает только файлы / формы, вам придется открыть файл как двоичный объект (это больше похоже на рабочую команду curl):

# Create a dictionary of files to post with your file in it.
x_files = {"file": ("file", open('MYxml.xml', 'rb'))}
...
q = requests.post(url, files=x_files, verify=False, headers={"Content-Type":"multipart/form-data"})

Если ни один из вышеперечисленных способов не работает и вы все еще в тупике, сбросьте все заголовки из рабочего запроса curl и отредактируйте их в своем ответе, что-то еще должно быть там.

Удачи

...