Содержание

Блок HTTP-запрос


Блок HTTP-запрос позволяет боту обмениваться данными со сторонними системами и сервисами, а также сохранять полученные данные в переменные.

Добавление блока

Чтобы добавить блок в сценарий, выберите HTTP-запрос в палитре блоков.

Настройте обязательные параметры запроса:

  • Выберите один из типов запроса:
    • GET (по умолчанию)
    • POST
    • DELETE
    • PUT
  • Укажите URL, на который будет отправляться запрос.

Дополнительно вы можете заполнить вкладки RESPONSE, BODY и HEADERS.

Подробнее об HTTP

URL запроса

По указанному URL бот будет получать либо отправлять данные.

Вы можете добавлять переменные в URL запроса. Формат может быть разным, например:

  • https://example.com?query=${varname}
  • https://${varname}/endpoint
  • ${varname} (если в переменной хранится полный URL запроса)

Здесь varname — имя переменной.

Фигурные скобки необходимы при подставлении переменных в адрес. Если в вашем URL есть другие фигурные скобки, то их необходимо заменить на

%7B и %7D соответственно для левой и правой скобки.

Чтобы передать в URL текст последнего ввода клиента, в качестве переменной в URL укажите queryText, например: https://example.com?query=${queryText}. Бот автоматически подставит его в URL перед выполнением запроса.

$queryText — это переменная, в которой хранится текст последнего запроса клиента.

При помощи переменных в URL, например, можно читать данные из разных Google Таблиц, не создавая несколько HTTP-запросов.

На вкладке HEADERS вы можете добавить заголовки запроса, заполнив поля

Заголовок и Значение.

В заголовках вы также можете использовать переменные.

При добавлении переменных в значение заголовка указывайте их без фигурных скобок и добавляйте $ перед именем переменной.

Тело запроса

Для всех методов вы можете передать тело запроса.

Тело запроса заполняется на вкладке BODY. Здесь можно указывать данные в любом формате (JSON, XML, произвольный текст), а также добавлять переменные.

В примере тело запроса указано в формате JSON. Бот автоматически подставит в тело запроса значения переменных

$age и $name.

При добавлении переменных в объект JSON необходимо учитывать, какой тип данных содержится в переменной.
В примере переменная $age указана без кавычек, потому что она содержит число, а переменная $name указана в кавычках, потому что содержит данные строкового типа.

Обработка ответа

В ответ на запрос сервер возвращает данные, которые можно обработать или вывести клиенту.

Для этого на вкладке RESPONSE вы можете указать, какие данные вы хотите получить из ответа на запрос, и сохранить их в новые переменные.

Например, по адресу https://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=ru сервер возвращает ответ в формате JSON:

{
    "quoteText": "Текст цитаты",
    "quoteAuthor": "Автор цитаты",
    "senderName": "Кто опубликовал цитату",
    "senderLink": "Ссылка на профиль",
    "quoteLink": "Ссылка на саму цитату на сайте"
}

Этот объект JSON сохраняется в системную переменную $httpResponse.

Чтобы сохранить данные из определенного поля объекта, укажите:

  • Имя переменной, в которую сохранятся данные.
  • Значение переменной через переменную
    $httpResponse
    .

Если запрос будет выполнен успешно, бот создаст переменные $quoteText и $quoteAuthor и запишет в них значения из ответа сервера.

httpResponse

Aimylogic сохраняет ответ от сервера в системную переменную $httpResponse.

Если сервер вернул ответ в формате JSON или XML, то Aimylogic автоматически конвертирует его в JavaScript-объект, с которым можно производить различные операции с помощью JavaScript-функций.

Из ответа можно получить нужные данные, обратившись к соответствующим полям объекта.

Например, чтобы сохранить в новую переменную значение из поля quoteText, укажите $httpResponse.quoteText в качестве ее значения.

Здесь quoteText — поле из ответа, которое необходимо получить.

Если сервер вернет ответ не в формате JSON или XML, то в переменную $httpResponse сохранится вся строка без какой-либо обработки.

JavaScript

При создании переменных вы можете использовать любые JavaScript-выражения и функции, а также функции библиотеки Underscore, которая позволяет упростить работу с объектами и массивами.

Предположим, в результате запроса сервер вернул следующий объект JSON:

{
    "items": [
        {
            "name": "апельсины",
            "price": 150
        },
        {
            "name": "мандарины",
            "price": 200
        }
    ]
}

Также предположим, что до этого в сценарии бот спросил у клиента, какой фрукт ему нужен, и сохранил ответ в переменную $choice.

Чтобы записать в переменную объект из массива items, потребуется следующее JavaScript-выражение:

_.findWhere($httpResponse.items, {name: "$choice"})

Функция будет искать в ответе объект, у которого значение поля name совпадает со значением переменной $choice.

Переходы после запроса

Блок HTTP-запрос имеет два выхода:

  • Завершен успешно, если в ответ на запрос сервер вернул код ответа от 200 до 299 включительно.
  • Завершен с ошибкой, если сервер вернул любой другой ответ.

Код ответа автоматически сохраняется в системную переменную $httpStatus.

    документация на русском, get и post

    Прежде чем начать, убедитесь, что установлена последняя версия Requests.

    Для начала, давайте рассмотрим простые примеры.

    Создание GET и POST запроса

    Импортируйте модуль Requests:

    Копировать Скопировано Use a different Browser

    import requests 
    

    Попробуем получить веб-страницу с помощью get-запроса. В этом примере давайте рассмотрим общий тайм-лайн GitHub:

    Копировать Скопировано Use a different Browser

    r = requests.get('https://api.github.com/events')
    

    Мы получили объект Response с именем r. С помощью этого объекта можно получить всю необходимую информацию.

    Простой API Requests означает, что все типы HTTP запросов очевидны. Ниже приведен пример того, как вы можете сделать POST запрос:

    Копировать Скопировано Use a different Browser

    r = requests.post('https://httpbin.org/post', data = {'key':'value'})  
    

    Другие типы HTTP запросов, такие как : PUT, DELETE, HEAD и OPTIONS так же очень легко выполнить:

    Копировать Скопировано Use a different Browser

    r = requests.put('https://httpbin.org/put', data = {'key':'value'})  
    r = requests.delete('https://httpbin.org/delete')  
    r = requests.head('https://httpbin.org/get')  
    r = requests.options('https://httpbin. org/get')  
    

    Передача параметров в URL

    Часто вам может понадобится отправить какие-то данные в строке запроса URL. Если вы настраиваете URL вручную, эти данные будут представлены в нем в виде пар ключ/значение после знака вопроса. Например,

    httpbin.org/get?key=val. Requests позволяет передать эти аргументы в качестве словаря, используя аргумент params. Если вы хотите передать key1=value1 и key2=value2 ресурсу httpbin.org/get, вы должны использовать следующий код:

    Копировать Скопировано Use a different Browser

    payload = {'key1': 'value1', 'key2': 'value2'}  
    r = requests.get('https://httpbin.org/get', params=payload)
    print(r.url) 
    

    Как видно, URL был сформирован правильно:

    https://httpbin.org/get?key2=value2&key1=value1

    Ключ словаря, значение которого None, не будет добавлен в строке запроса URL.

    Вы можете передать список параметров в качестве значения:

    Копировать Скопировано Use a different Browser

    >>> payload = {'key1': 'value1', 'key2': ['value2', 'value3']}  
    >>> r = requests. get('https://httpbin.org/get', params=payload)  
    >>> print(r.url)  
    https://httpbin.org/get?key1=value1&key2=value2&key2=value3 
    

    Содержимое ответа (response)

    Мы можем прочитать содержимое ответа сервера. Рассмотрим снова тайм-лайн GitHub:

    Копировать Скопировано Use a different Browser

    >>> import requests
    >>> r = requests.get('https://api.github.com/events')
    >>> r.text
    '[{"repository":{"open_issues":0,"url":"https://github.com/...
    

    Requests будет автоматически декодировать содержимое ответа сервера. Большинство кодировок unicode декодируются без проблем.
    Когда вы делаете запрос, Requests делает предположение о кодировке, основанное на заголовках HTTP. Эта же кодировка текста, используется при обращение к r.text. Можно узнать, какую кодировку использует Requests, и изменить её с помощью r.encoding:

    Копировать Скопировано Use a different Browser

    >>> r. encoding
    'utf-8'
    >>> r.encoding = 'ISO-8859-1'
    

    Если вы измените кодировку, Requests будет использовать новое значение r.encoding всякий раз, когда вы будете использовать r.text. Вы можете сделать это в любой ситуации, где нужна более специализированная логика работы с кодировкой содержимого ответа.

    Например, в HTML и XML есть возможность задавать кодировку прямо в теле документа. В подобных ситуациях вы должны использовать r.content, чтобы найти кодировку, а затем установить r.encoding. Это позволит вам использовать r.text с правильной кодировкой.

    Requests может также использовать пользовательские кодировки в случае, если в них есть потребность. Если вы создали свою собственную кодировку и зарегистрировали ее в модуле codecs, используйте имя кодека в качестве значения r.encoding.

    Бинарное содержимое ответа

    Вы можете также получить доступ к телу ответа в виде байтов для не текстовых ответов:

    Копировать Скопировано Use a different Browser

    >>> r. content
    b'[{"repository":{"open_issues":0,"url":"https://github.com/...
    

    Передача со сжатием gzip и deflate автоматически декодируются для вас.

    Например, чтобы создать изображение на основе бинарных данных, возвращаемых при ответе на запрос, используйте следующий код:

    Копировать Скопировано Use a different Browser

    from PIL import Image  
    from io import BytesIO  
    i = Image.open(BytesIO(r.content))
    

    Содержимое ответа в JSON

    Если вы работаете с данными в формате JSON, воспользуйтесь встроенным JSON декодером:


    Копировать Скопировано Use a different Browser

    >>> import requests
    >>> r = requests.get('https://api.github.com/events')
    >>> r.json()
    [{'repository': {'open_issues': 0, 'url': 'https://github.com/...
    

    Если декодирование в JSON не удалось, r.json() вернет исключение. Например, если ответ с кодом 204 (No Content), или на случай если ответ содержит не валидный JSON, попытка обращения к r. json() будет возвращать ValueError: No JSON object could be decoded.

    Следует отметить, что успешный вызов r.json() не указывает на успешный ответ сервера. Некоторые серверы могут возвращать объект JSON при неудачном ответе (например, сведения об ошибке HTTP 500). Такой JSON будет декодирован и возвращен. Для того, чтобы проверить успешен ли запрос, используйте r.raise_for_status() или проверьте какой r.status_code.

    Необработанное содержимое ответа

    В тех редких случаях, когда вы хотите получить доступ к “сырому” ответу сервера на уровне сокета, обратитесь к r.raw. Если вы хотите сделать это, убедитесь, что вы указали stream=True в вашем первом запросе. После этого вы уже можете проделать следующее:

    Копировать Скопировано Use a different Browser

    >>> r = requests.get('https://api.github.com/events', stream=True)
    >>> r.raw
    
    >>> r.raw. read(10)
    '\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
    

    Однако, можно использовать подобный код как шаблон, чтобы сохранить результат в файл:

    Копировать Скопировано Use a different Browser

    with open(filename, 'wb') as fd:
        for chunk in r.iter_content(chunk_size=128):
            fd.write(chunk)
    

    Использование r.iter_content обработает многое из того, с чем бы вам пришлось иметь дело при использовании r.raw напрямую. Для извлечения содержимого при потоковой загрузке, используйте способ, описанный выше. Обратите внимание, что chunk_size можно свободно скорректировать до числа, которое лучше подходит в вашем случае.

    Важное замечание об использовании Response.iter_content и Response.raw. Response.iter_content будет автоматически декодировать gzip и deflate. Response.raw — необработанный поток байтов, он не меняет содержимое ответа. Если вам действительно нужен доступ к байтам по мере их возврата, используйте Response.raw.

    Пользовательские заголовки

    Если вы хотите добавить HTTP заголовки в запрос, просто передайте соответствующий dict в параметре headers.
    Например, мы не указали наш user-agent в предыдущем примере:

    Копировать Скопировано Use a different Browser

    url = 'https://api.github.com/some/endpoint'  
    headers = {'user-agent': 'my-app/0.0.1'}  
    r = requests.get(url, headers=headers)
    

    Заголовкам дается меньший приоритет, чем более конкретным источникам информации. Например:

    • Заголовки авторизации, установленные с помощью headers= будут переопределены, если учетные данные указаны .netrc, которые, в свою очередь переопределены параметром auth=.
    • Они же будут удалены при редиректе.
    • Заголовки авторизации с прокси будут переопределены учетными данными прокси-сервера, которые указаны в вашем URL.
    • Content-Length будут переопределены, когда вы определите длину содержимого.

    Кроме того, запросы не меняют свое поведение вообще, основываясь на указанных пользовательских заголовках.

    Значения заголовка должны быть string, bytestring или unicode. Хотя это разрешено, рекомендуется избегать передачи значений заголовков unicode.

    Более сложные POST запросы

    Часто вы хотите послать некоторые form-encoded данные таким же образом, как это делается в HTML форме. Для этого просто передайте соответствующий словарь в аргументе data. Ваш словарь данных в таком случае будет автоматически закодирован как HTML форма, когда будет сделан запрос:

    Копировать Скопировано Use a different Browser

    >>> payload = {'key1': 'value1', 'key2': 'value2'}
    >>> r = requests.post("https://httpbin.org/post", data=payload)
    >>> print(r.text)
    {
      ...
      "form": {
        "key2": "value2",
        "key1": "value1"
      },
      . ..
    }
    

    Аргумент data также может иметь несколько значений для каждого ключа. Это можно сделать, указав data в формате tuple, либо в виде словаря со списками в качестве значений. Особенно полезно, когда форма имеет несколько элементов, которые используют один и тот же ключ:


    Копировать Скопировано Use a different Browser

    >>> payload_tuples = [('key1', 'value1'), ('key1', 'value2')]
    >>> r1 = requests.post('https://httpbin.org/post', data=payload_tuples)
    >>> payload_dict = {'key1': ['value1', 'value2']}
    >>> r2 = requests.post('https://httpbin.org/post', data=payload_dict)
    >>> print(r1.text)
    {
      ...
      "form": {
        "key1": [
          "value1",
          "value2"
        ]
      },
      ...
    }
    >>> r1.text == r2.text
    True
    

    Бывают случаи, когда нужно отправить данные не закодированные методом form-encoded. Если вы передадите в запрос строку вместо словаря, эти данные отправятся в не измененном виде.

    К примеру, GitHub API v3 принимает закодированные JSON POST/PATCH данные:

    Копировать Скопировано Use a different Browser

    import json
    url = 'https://api.github.com/some/endpoint'  
    payload = {'some': 'data'}  
    r = requests.post(url, data=json.dumps(payload))  
    

    Вместо того, чтобы кодировать dict, вы можете передать его напрямую, используя параметр json (добавленный в версии 2.4.2), и он будет автоматически закодирован:

    Копировать Скопировано Use a different Browser

    url = 'https://api.github.com/some/endpoint'  
    payload = {'some': 'data'}  
    r = requests.post(url, json=payload) 
    

    Обратите внимание, параметр json игнорируется, если передаются data или files.
    Использование параметра json в запросе изменит заголовок Content-Type на application/json.

    POST отправка Multipart-Encoded файла

    Запросы упрощают загрузку файлов с многостраничным кодированием (Multipart-Encoded) :

    Копировать Скопировано Use a different Browser

    >>> url = 'https://httpbin. org/post'
    >>> files = {'file': open('report.xls', 'rb')}
    >>> r = requests.post(url, files=files)
    >>> r.text
    {
      ...
      "files": {
        "file": ""
      },
      ...
    }
    

    Вы можете установить имя файла, content_type и заголовки в явном виде:

    Копировать Скопировано Use a different Browser

    >>> url = 'https://httpbin.org/post'
    >>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
    >>> r = requests.post(url, files=files)
    >>> r.text
    {
      ...
      "files": {
        "file": ""
      },
      ...
    }
    

    Можете отправить строки, которые будут приняты в виде файлов:

    Копировать Скопировано Use a different Browser

    >>> url = 'https://httpbin.org/post'
    >>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}
    >>> r = requests.post(url, files=files)
    >>> r.text
    {
      ... 
      "files": {
        "file": "some,data,to,send\\nanother,row,to,send\\n"
      },
      ...
    }
    

    В случае, если вы отправляете очень большой файл как запрос multipart/form-data, возможно понадобиться отправить запрос потоком. По умолчанию, requests не поддерживает этого, но есть отдельный пакет, который это делает — requests-toolbelt. Ознакомьтесь с документацией toolbelt для получения более детальной информации о том, как им пользоваться.

    Для отправки нескольких файлов в одном запросе, обратитесь к расширенной документации.

    Предупреждение!
    Настоятельно рекомендуется открывать файлы в бинарном режиме. Это связано с тем, что запросы могут пытаться предоставить для вас заголовок Content-Length, и если это значение будет установлено на количество байтов в файле будут возникать ошибки, при открытии файла в текстовом режиме.

    Коды состояния ответа

    Мы можем проверить код состояния ответа:

    Копировать Скопировано Use a different Browser

    >>> r = requests. get('https://httpbin.org/get')
    >>> r.status_code
    200
    

    У requests есть встроенный объект вывода кодов состояния:

    Копировать Скопировано Use a different Browser

    >>> r.status_code == requests.codes.ok
    True
    

    Если мы сделали неудачный запрос (ошибка 4XX или 5XX), то можем вызвать исключение с помощью r.raise_for_status():

    Копировать Скопировано Use a different Browser

    >>> bad_r = requests.get('https://httpbin.org/status/404')
    >>> bad_r.status_code
    404
    >>> bad_r.raise_for_status()
    Traceback (most recent call last):
      File "requests/models.py", line 832, in raise_for_status
        raise http_error
    requests.exceptions.HTTPError: 404 Client Error
    

    Но если status_code для r оказался 200, то когда мы вызываем raise_for_status() мы получаем:


    Копировать Скопировано Use a different Browser

    >>> r. raise_for_status()
    None
    

    Заголовки ответов

    Мы можем просматривать заголовки ответа сервера, используя словарь Python:

    Копировать Скопировано Use a different Browser

    >>> r.headers
    {
        'content-encoding': 'gzip',
        'transfer-encoding': 'chunked',
        'connection': 'close',
        'server': 'nginx/1.0.4',
        'x-runtime': '148ms',
        'etag': '"e1ca502697e5c9317743dc078f67693f"',
        'content-type': 'application/json'
    }
    

    Это словарь особого рода, он создан специально для HTTP заголовков. Согласно с RFC 7230, имена заголовков HTTP нечувствительны к регистру.

    Теперь мы можем получить доступ к заголовкам с большим буквами или без, если захотим:

    Копировать Скопировано Use a different Browser

    >>> r.headers['Content-Type']
    'application/json'
    >>> r.headers.get('content-type')
    'application/json'
    

    Cookies

    Если в запросе есть cookies, вы сможете быстро получить к ним доступ:

    Копировать Скопировано Use a different Browser

    >>> url = 'https://example. com/some/cookie/setting/url'
    >>> r = requests.get(url)
    >>> r.cookies['example_cookie_name']
    'example_cookie_value'
    

    Чтобы отправить собственные cookies на сервер, используйте параметр cookies:

    Копировать Скопировано Use a different Browser

    >>> url = 'https://httpbin.org/cookies'
    >>> cookies = dict(cookies_are='working')
    >>> r = requests.get(url, cookies=cookies)
    >>> r.text
    '{"cookies": {"cookies_are": "working"}}'
    

    Cookies возвращаются в RequestsCookieJar, который работает как dict, но также предлагает более полный интерфейс, подходящий для использования в нескольких доменах или путях. Словарь с cookie может также передаваться в запросы:

    Копировать Скопировано Use a different Browser

    >>> jar = requests.cookies.RequestsCookieJar()
    >>> jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
    >>> jar. set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
    >>> url = 'https://httpbin.org/cookies'
    >>> r = requests.get(url, cookies=jar)
    >>> r.text
    '{"cookies": {"tasty_cookie": "yum"}}'
    

    Редиректы и история

    По умолчанию Requests будет выполнять редиректы для всех HTTP глаголов, кроме HEAD.

    Мы можем использовать свойство history объекта Response, чтобы отслеживать редиректы .

    Список Response.history содержит объекты Response, которые были созданы для того, чтобы выполнить запрос. Список сортируется от более ранних, до более поздних ответов.

    Например, GitHub перенаправляет все запросы HTTP на HTTPS:

    Копировать Скопировано Use a different Browser

    >>> r = requests.get('https://github.com/')
    >>> r.url
    'https://github.com/'
    >>> r.status_code
    200
    >>> r.history
    []
    

    Если вы используете запросы GET, OPTIONS, POST, PUT, PATCH или DELETE, вы можете отключить обработку редиректа с помощью параметра allow_redirects:

    Копировать Скопировано Use a different Browser

    >>> r = requests. get('https://github.com/', allow_redirects=False)
    >>> r.status_code
    301
    >>> r.history
    []
    

    Если вы используете HEAD, вы также можете включить редирект:

    Копировать Скопировано Use a different Browser

    >>> r = requests.head('https://github.com/', allow_redirects=True)
    >>> r.url
    'https://github.com/'
    >>> r.history
    []
    

    Тайм-ауты

    Вы можете сделать так, чтобы Requests прекратил ожидание ответа после определенного количества секунд с помощью параметра timeout.

    Почти весь код должен использовать этот параметр в запросах. Несоблюдение этого требования может привести к зависанию вашей программы:

    Копировать Скопировано Use a different Browser

    >>> requests.get('https://github.com/', timeout=0.001)
    Traceback (most recent call last):
      File "", line 1, in 
    requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out.  (timeout=0.001)
    

    Timeout это не ограничение по времени полной загрузки ответа. Исключение возникает, если сервер не дал ответ за timeout секунд (точнее, если ни одного байта не было получено от основного сокета за timeout секунд).

    Ошибки и исключения

    В случае неполадок в сети (например, отказа DNS, отказа соединения и т.д.), Requests вызовет исключение ConnectionError.

    Response.raise_for_status() вызовет HTTPError если в запросе HTTP возникнет статус код ошибки.

    Если выйдет время запроса, вызывается исключение Timeout. Если запрос превышает заданное значение максимального количества редиректов, то вызывают исключение TooManyRedirects.

    Все исключения, которые вызывает непосредственно Requests унаследованы от requests.exceptions.RequestException.

    Тест на знание основ Requests

    Какой из HTTP-запросов является правильным?

    requests. post(url, data={‘key’:’value’})

    Все запросы верны

    requests.get(url, params={‘key’:’value’})

    requests.post(url, params={‘key’:’value’})

    Какое из утверждений верно?

    response.json() возвращает содержимое ответа в виде объекта dict

    response.text возвращает содержимое ответа в виде байтового объекта

    response.content возвращает содержимое ответа в виде строкового объекта

    response.json возвращает содержимое ответа в виде объекта dict

    Все не верно

    Как получить куки из ответа на запрос?

    response.cookie

    response(«cookies»)

    response.get_cookies

    response.cookies

    Что вернет метод status_code объекта Response?

    Ошибку, если запрос неудачный

    OK или ERROR

    Код ответа

    True или None

    Какой код сформирует url «https://test.com/page?key1=value1&key2=value21,value22»

    r.get(‘https://test.com/page’, params={‘key1’: ‘value1’, ‘key2’: [‘value21’, ‘value22’]})

    r.get(‘https://test.com/page’, params={‘key1’: ‘value1’, ‘key2’: ‘value21,value22’})

    r. get(‘https://test.com/page’, params={‘key1’: ‘value1’, ‘key2’: ‘value21’, ‘key2’: ‘value22’})

    Это невозможно

    {{title}}

    {{image}}

    {{content}}

    {{/global}}

    Поделиться результатами через

    Facebook Twitter VK

    Как сделать POST-запрос в Postman

    POST-запрос с помощью Postman

    В предыдущих руководствах мы узнали о том, как отправить запрос GET , а также узнали о параметрах запроса . Из наших основ отдыха мы уже знаем, что такое HTTP-запрос и HTTP-ответ . Если вы еще не прочитали эти два руководства, сделайте это, прежде чем продолжить. В этой главе мы сосредоточимся на другом типе метода запроса — 9.0005 POST-запрос в почтальоне .

    Что такое POST-запрос?

    POST — это HTTP-команда , аналогичная запросу GET , это указывает, что клиент отправляет данные на заданную конечную точку . Запрос POST — это метод, который используется, когда нам нужно отправить некоторую дополнительную информацию внутри тела запроса на сервер. Когда мы отправляем POST-запрос, мы, как правило, намереваемся внести некоторые изменения на сервер, например, обновление, удаление или добавление . Одним из классических примеров POST-запроса является страница входа. Когда вы впервые подписываетесь на что-либо, скажем, на Facebook, вы отправляете на сервер свою личную информацию, такую ​​как пароль. Сервер создает новую учетную запись с теми же данными, и эта учетная запись постоянно добавляется на сервер Facebook. Вы только что создали новый ресурс на сервере. Запросы POST очень популярны и в основном используются всякий раз, когда вы отправляете некоторую конфиденциальную информацию, такую ​​как отправка формы или отправка конфиденциальной информации на сервер.

    В этом уроке мы рассмотрим различные функции POST Запросы и то, как мы можем создать их в Postman. Прежде чем мы попытаемся использовать пример, чтобы получить четкое представление о POST Request .

    POST-запрос у почтальона

    Каждая конечная точка REST имеет связанную с ней собственную HTTP-команду . Если конечная точка указывает, что ее следует вызывать с помощью команды HTTP POST, то клиенты обязаны вызывать конечную точку с Только глагол POST HTTP . Давайте сначала проверим, что происходит, когда мы запрашиваем метод GET вместо метода POST для конечной точки POST . Также проверить, что происходит, когда мы делаем POST Request без Body .

    Запрос GET на конечной точке POST
    1. Использовать API http://restapi.demoqa. com/customer/register ( Этот API используется для регистрации нового клиента) в панели конечной точки Postman и нажмите Отправить . Убедитесь, что в раскрывающемся списке Тип метода выбрано значение GET .

    1. См. код состояния HTTP, это будет 405 Метод не разрешен.  Это означает, что мы обращаемся к конечной точке с неправильным типом метода. На изображении ниже показаны детали.

    1. См. ответ ниже на вкладке Body и сосредоточьтесь на ошибке .

    Это означает, что используемый нами тип метода недействителен и ожидается другой тип метода. Поэтому мы попытаемся изменить это и посмотрим, получим ли мы правильный ответ.

    Запрос POST без тела
    1. Измените тип метода на POST и нажмите ОТПРАВИТЬ

    1. Теперь взгляните на тело ответа и код состояния ответа .

    Fault Invalid Post Request означает, что введенные нами данные поста недействительны . Напомним, что мы добавляем информацию в тело запроса, поэтому нам нужно что-то ввести в тело запроса и посмотреть, соответствует ли этот формат ожидаемому формату. Кроме того, вы можете увидеть код состояния, который говорит 400 ПЛОХОЙ запрос . Это означает, что параметры запроса не соответствуют параметрам сервера для получения ответа.

    Почтовый запрос в почтальоне
    1. Теперь давайте добавим тело запроса в наш POST-запрос. Каждая конечная точка будет задокументирована с типом метода и форматом тела, который она ожидает. Давайте посмотрим, какое тело ожидает этот запрос и как его добавить. Для этого нажмите на Кузов табл.

    1. Нажмите на raw и выберите тип формата JSON , так как мы должны отправить неправильный формат, который ожидает сервер.

    1. Эта конечная точка ожидает тело Json , содержащее сведения о новом пользователе. Ниже приведен образец тела Json . Скопируйте и вставьте следующее на вкладке body Postman.

    {

    * «Имя»: «значение»*

    * «Фамилия : «значение»,*

    «Имя пользователя: «значение»,

    «Пароль»: «значение»,

    «Электронная почта»: «Значение»

    }

    Измените значение атрибута на любое значение, которое вы хотите ( см. на изображении ниже ).

    1. Нажмите Отправьте и посмотрите тело ответа и Статус ответа.

    Ошибка Ошибка пользователя уже выходит  означает, что в базе данных уже была создана аналогичная запись вами или кем-либо еще ранее. Принимая во внимание, что если вы видите, что статус ответа равен 200 OK, , это означает, что сервер принял запрос и отправил успешный ответ. Из этого мы также можем сделать вывод, что тело ответа было правильным и сервер смог его интерпретировать. Теперь в этом запросе API адрес электронной почты и имя пользователя должны быть уникальными. Таким образом, вы можете изменить эти значения ( сработает и любой ).

    Если значения уникальны, вы получите этот ответ

    Операция успешно завершена  означает, что ваша запись успешно создана в базе данных.

    Итак, на этом примере видно, что всякий раз, когда нам нужно отправить POST-запрос , он должен сопровождаться Body. Тело должно быть в правильном формате и с правильными ключами, чтобы получить правильный ответ от сервера. Теперь мы подробно узнаем о каждой функции почтового запроса в Postman.

    Различные способы отправки данных в запросе POST в Postman

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

    1. Выберите тип запроса метода как POST в построителе, как показано.

    Как только вы выберете тип запроса POST в Postman, вы увидите, что включена опция Body, которая имеет различные параметры для отправки данных внутри тела. Эти параметры:

    • Данные формы
    • X-www-form-urlencoded
    • Необработанный
    • Двоичный

    Данные формы

    Данные формы, как следует из названия, используются для отправки данных, которые вы заключаете в форму, например сведений, которые вы вводите при заполнении формы. Эти данные отправляются путем записи их в виде пар KEY-VALUE , где ключом является « имя » записи, которую вы отправляете, а значением является ее значение . Следующие шаги прояснят ситуацию.

    1. Выберите данные формы

    1. Добавьте следующую пару КЛЮЧ-ЗНАЧЕНИЕ
    • Имя : Хариш
    • Фамилия :  Rajora

    Здесь первое имя в поле некоторой формы ( текстовое поле здесь ), которое необходимо ввести, и Harish  является его значением, то есть значением, которое ввел пользователь. То же самое касается идентификатора фамилии.

    x-www-form-urlencoded

    Данные форм и x-www-form-urlencoded очень похожи. Оба они используются практически для одних и тех же целей. Но разница между данными формы и x-www-form-urlencoded заключается в том, что URL-адрес будет закодирован при отправке через x-www-form-urlencoded . Кодировка означает, что отправляемые данные будут закодированы в разные символы, чтобы их нельзя было распознать, даже если они подверглись атаке.

    Необработанный

    Raw — наиболее часто используемая часть или параметр при отправке тела методом POST. Это важно с точки зрения Почтальона. Необработанный означает, что сообщение тела отображается как поток битов, представляющий тело запроса. Эти биты будут интерпретироваться как строковый сервер.

    1. Нажмите на раскрывающийся список, кроме двоичный  и там вы увидите все варианты, в которых вы можете отправить запрос

    1. Нажмите JSON (приложение/json)

    1. В редакторе ниже скопируйте и вставьте этот

    {

    «имя»: «суровый»,

    «фамилия»: «Раджора»

    }

    Это те же данные, которые ранее отправлялись с данными формы, но теперь они отправляются в формате JSON.

    Двоичный

    Binary предназначен для отправки информации в формате, который нельзя ввести вручную. Поскольку все в компьютере преобразуется в двоичный файл, мы используем эти параметры, которые нельзя записать вручную, такие как изображение, файл и т. д. Чтобы использовать этот параметр

    1. Нажмите на двоичный файл , будет доступна опция ВЫБРАТЬ ФАЙЛЫ

    1. Выберите любой файл, например файл изображения.

    Примечание : Если вы хотите отправить на сервер некоторые данные вместе с файлом, это также можно сделать в форме данных.

    Нажмите на форму-данные

    Введите файл в качестве ключа

    , и вы увидите скрытый раскрывающийся список, в котором по умолчанию указано «Текст». Вы можете выбрать любой формат файла, а затем выбрать файл из системы.

    Всегда помните, что ожидает ваш сервер. Вы не можете отправить другой формат, отличный от того, который ожидает ваш сервер, в противном случае не будет ответа или неверный ответ, который, очевидно, можно увидеть по коду состояния ответа. Итак, теперь мы узнали о методе POST и о том, как его использовать в Postman. Мы перейдем к следующему уроку, который сейчас Коллекции .

    Существуют и другие типы REST-запросов, если вы хотите узнать о них больше, см. следующие видеоролики:

    Запрос PUT у почтальона

    УДАЛИТЬ Запрос в почтальоне

    Что такое контрабанда HTTP-запросов? Учебник и примеры

    Твиттер WhatsApp Фейсбук Реддит LinkedIn Электронная почта

    В этом разделе мы объясним атаки контрабанды HTTP-запросов и опишем, как могут возникать распространенные уязвимости, связанные с контрабандой запросов.

    Что такое контрабанда HTTP-запросов?

    Контрабанда HTTP-запросов — это метод вмешательства в то, как веб-сайт обрабатывает последовательности HTTP-запросов, полученных от один или несколько пользователей. Уязвимости для контрабанды запросов часто носят критический характер, позволяя злоумышленнику обойти элементы управления безопасностью, получить несанкционированный доступ к конфиденциальным данным и непосредственная компрометация других пользователей приложения.

    Примечание

    Контрабанда HTTP-запросов была впервые задокументирована в 2005 году и недавно вновь стала популярной благодаря исследованию PortSwigger по этой теме.

    Что происходит при контрабанде HTTP-запросов?

    Современные веб-приложения часто используют цепочки HTTP-серверов между пользователями и конечной логикой приложения. Пользователи отправляют запросы на внешний сервер (иногда называемый балансировщиком нагрузки или обратным прокси-сервером), и этот сервер перенаправляет запросы на один или несколько внутренних серверов. Этот тип архитектуры становится все более распространенным, а в некоторых случаях неизбежным в современных облачных приложениях.

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

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

    Здесь злоумышленник заставляет часть своего внешнего запроса интерпретироваться внутренним сервером как начало следующего запроса. Это эффективно добавляется к следующему запросу и поэтому может мешать тому, как приложение обрабатывает этот запрос. это запрос нападение контрабанды, и это может иметь разрушительные результаты.

    Как возникают уязвимости, связанные с контрабандой HTTP-запросов?

    Большинство уязвимостей, связанных с контрабандой HTTP-запросов, возникают из-за того, что спецификация HTTP предоставляет два разных способа указать, где находится запрос. заканчивается: заголовок Content-Length и заголовок Transfer-Encoding .

    Заголовок Content-Length прост: он указывает длину тела сообщения в байтах. Для пример:

    POST/поиск HTTP/1.1 Хост: normal-website.com Content-Type: application/x-www-form-urlencoded Длина содержимого: 11 q=контрабанда

    Заголовок Transfer-Encoding можно использовать для указания того, что тело сообщения использует кодирование по частям. Этот означает, что тело сообщения содержит один или несколько фрагментов данных. Каждый фрагмент состоит из размера фрагмента в байтах (выраженного в шестнадцатеричный), за которым следует новая строка, за которой следует содержимое фрагмента. Сообщение завершается фрагментом нулевого размера. Например:

    POST/поиск HTTP/1.1 Хост: normal-website.com Content-Type: application/x-www-form-urlencoded Передача-кодирование: по частям б q = контрабанда 0

    Примечание

    Многие тестировщики безопасности не знают, что кодирование по частям может использоваться в HTTP-запросах по двум причинам:

    • Burp Suite автоматически распаковывает фрагменты кодировки, чтобы упростить просмотр и редактирование сообщений.
    • Браузеры обычно не используют фрагментированное кодирование в запросах, и оно обычно видно только в ответах сервера.

    Поскольку спецификация HTTP предоставляет два разных метода указания длины HTTP-сообщений, можно использовать один сообщение использовать оба метода одновременно, чтобы они конфликтовали друг с другом. Спецификация HTTP пытается предотвратить эту проблему путем заявив, что если оба Content-Length и Заголовки Transfer-Encoding присутствует, то заголовок Content-Length следует игнорировать. Этого может быть достаточно, чтобы избежать двусмысленности когда в игре находится только один сервер, но не когда два или более сервера соединены вместе. В этой ситуации могут возникнуть проблемы для двоих. причины:

    • Некоторые серверы не поддерживают заголовок Transfer-Encoding в запросах.
    • Некоторые серверы, поддерживающие заголовок Transfer-Encoding , могут не обрабатывать его, если заголовок каким-то образом запутан.

    Если внешний и внутренний серверы ведут себя по-разному в отношении (возможно, запутанного) Transfer-Encoding заголовок, то они могут не согласиться с границами между последовательными запросами, что приведет к уязвимостям контрабанды запросов.

    Как выполнить контрабандную атаку HTTP-запроса

    Атаки с контрабандой запросов включают размещение как заголовка Content-Length , так и Transfer-Encoding . заголовка в один HTTP-запрос и манипулировать ими, чтобы внешний и внутренний серверы обрабатывали запрос по-разному. точный способ, которым это делается, зависит от поведения двух серверов:

    • CL.TE: внешний сервер использует Content-Length , а внутренний сервер использует заголовок Transfer-Encoding .
    • TE.CL: внешний сервер использует заголовок Transfer-Encoding , а внутренний сервер использует заголовок Content-Length .
    • TE.TE: внешний и внутренний серверы поддерживают заголовок Transfer-Encoding , но один из серверы можно заставить не обрабатывать его, каким-то образом запутав заголовок.
    Примечание

    Эти методы возможны только с использованием запросов HTTP/1. Браузеры и другие клиенты, включая Burp, по умолчанию используют HTTP/2 для связи с серверами, которые явно объявляют о своей поддержке через ALPN как часть рукопожатия TLS. В результате при тестировании сайтов с поддержкой HTTP/2 нужно вручную переключать протоколы в Burp Repeater. Это можно сделать в разделе Атрибуты запроса панели Inspector .

    Уязвимости CL.TE

    Здесь внешний сервер использует заголовок Content-Length , а внутренний сервер использует заголовок Transfer-Encoding . Мы можем выполнить простую атаку контрабанды HTTP-запросов следующим образом:

    ПОЧТА/HTTP/1. 1 Хост: уязвимый-website.com Длина содержимого: 13 Передача-кодирование: по частям 0 КОНТРАБАНТА

    Интерфейсный сервер обрабатывает заголовок Content-Length и определяет, что тело запроса составляет 13 байт. долго, до конца КОНТРАБАНТА . Этот запрос перенаправляется на внутренний сервер.

    Внутренний сервер обрабатывает заголовок Transfer-Encoding и, таким образом, обрабатывает тело сообщения как использующее фрагментарное кодирование. Он обрабатывает первый фрагмент, который имеет нулевую длину, и поэтому рассматривается как завершение запроса. следующие байты, SMUGGLED , остаются необработанными, и внутренний сервер будет рассматривать их как начало следующего запроса в последовательности.

    ЛАБОРАТОРИЯ

    ПРАКТИК Контрабанда HTTP-запросов, базовая уязвимость CL. TE

    Уязвимости TE.CL

    Здесь внешний сервер использует заголовок Transfer-Encoding , а внутренний сервер использует заголовок Content-Length . Мы можем выполнить простую атаку контрабанды HTTP-запросов следующим образом:

    ПОЧТА/HTTP/1.1 Хост: уязвимый-website.com Длина содержимого: 3 Передача-кодирование: по частям 8 КОНТРАБАНТА 0

    Примечание

    Чтобы отправить этот запрос с помощью Burp Repeater, вам сначала нужно перейти в меню Repeater и убедиться, что «Update Content-Length» опция не отмечена.

    Вам необходимо включить конечную последовательность \r\n\r\n после финальной 0 .

    Интерфейсный сервер обрабатывает заголовок Transfer-Encoding и, таким образом, обрабатывает тело сообщения как использующее фрагментарное кодирование. Он обрабатывает первый фрагмент, длина которого заявлена ​​как 8 байт, до начала строки, следующей за 9.0613 КОНТРАБАНТА . Он обрабатывает второй фрагмент, который, как указано, имеет нулевую длину и поэтому рассматривается как завершающий. запрос. Этот запрос перенаправляется на внутренний сервер.

    Внутренний сервер обрабатывает заголовок Content-Length и определяет, что тело запроса составляет 3 байта. длинный, до начала строки, следующей за 8 . Следующие байты, начиная с SMUGGLED , остаются необработанными, и внутренний сервер будет рассматривать их как начало следующего запрос в последовательности.

    ЛАБОРАТОРИЯ

    ПРАКТИК Контрабанда HTTP-запросов, базовая уязвимость TE.CL

    Здесь внешний и внутренний серверы поддерживают заголовок Transfer-Encoding , но один из серверов можно заставить не обрабатывать его, каким-то образом запутав заголовок.

    Существует потенциально бесконечное количество способов запутать заголовок Transfer-Encoding . Например:

    Кодирование передачи: xchunked Передача-кодирование: по частям Передача-кодирование: по частям Передача-кодирование: x Передача-кодирование:[tab]разделено на части [пробел]Кодирование передачи: фрагментировано X: X[\n]Transfer-Encoding: фрагментировано Передача-кодирование : по частям

    Каждый из этих методов предполагает тонкое отклонение от спецификации HTTP. Реальный код, реализующий спецификацию протокола редко придерживается его с абсолютной точностью, и обычно разные реализации допускают разные отклонения от Спецификация. Чтобы обнаружить уязвимость TE.TE, необходимо найти какую-либо вариацию Transfer-Encoding заголовок таким образом, что его обрабатывает только один из интерфейсных или внутренних серверов, в то время как другой сервер его игнорирует.

    В зависимости от того, является ли внешний или внутренний сервер необработанным для обработки запутанного заголовка Transfer-Encoding , оставшаяся часть атаки будет иметь ту же форму, что и для CL.TE или TE. КЛ уже описанные уязвимости.

    ЛАБОРАТОРИЯ

    ПРАКТИК Контрабанда HTTP-запросов, обфускация заголовка TE

    Как выявить уязвимости, связанные с контрабандой HTTP-запросов

    В следующем разделе вы найдете несколько советов о том, как самостоятельно определить уязвимости, связанные с контрабандой HTTP-запросов. Мы также предоставили несколько интерактивных ЛАБОРАТОРИЙ, чтобы вы могли увидеть, как это работает на практике.

    Подробнее
    Поиск уязвимостей, связанных с контрабандой HTTP-запросов

    Как использовать уязвимости, связанные с контрабандой HTTP-запросов

    Теперь, когда вы знакомы с основными понятиями, давайте посмотрим, как контрабанда HTTP-запросов может использоваться для создания ряда атак высокой степени серьезности. Как обычно, есть много полностью интерактивных ЛАБОРАТОРИЙ, поэтому вы можете попробовать свои силы в атаке реалистичных целей.

    Подробнее
    Использование уязвимостей контрабанды HTTP-запросов

    Расширенная контрабанда HTTP-запросов

    Если вы уже завершили остальные наши лабораторные работы по контрабанде по запросам, вы готовы изучить некоторые более продвинутые методы. Мы создали ряд интерактивных ЛАБОРАТОРИЙ на основе реальных уязвимостей, обнаруженных исследователями PortSwigger. У вас даже будет возможность опробовать уникальные функции Burp для тестирования на основе HTTP/2.

    Подробнее
    Расширенные уязвимости, связанные с контрабандой HTTP-запросов

    Контрабанда запросов через браузер

    Методы контрабанды запросов, которые вы уже изучили, основаны на отправке преднамеренно искаженных запросов с использованием специальных хакерских инструментов, таких как Burp Repeater. На самом деле, те же самые атаки можно выполнять, используя полностью совместимые с браузером запросы, которые рассинхронизируют два сервера, используя совершенно обычный заголовок Content-Length .

    Это даже позволяет вам запускать варианты этих атак на стороне клиента, которые побуждают браузер жертвы отравить свое собственное соединение с уязвимым веб-сайтом. Это не только подвергает сайты с одним сервером запросам атак в стиле контрабанды, но даже позволяет вам атаковать сайты, к которым у вас нет прямого доступа. Ознакомьтесь с учебными материалами и лабораторными работами, чтобы узнать, как это сделать.

    Подробнее
    Контрабанда запросов через браузер

    Как предотвратить уязвимости, связанные с контрабандой HTTP-запросов

    Уязвимости, связанные с контрабандой HTTP-запросов, возникают в ситуациях, когда внешний и внутренний серверы используют разные механизмы для определения границ между запросами. Это может быть связано с несоответствием между тем, используют ли серверы HTTP/1 заголовок Content-Length или кодирование передачи по частям, чтобы определить, где заканчивается каждый запрос. В средах HTTP/2 обычная практика понижения запросов HTTP/2 для серверной части также сопряжена с проблемами и позволяет или упрощает ряд дополнительных атак.

    Чтобы предотвратить уязвимости, связанные с контрабандой HTTP-запросов, мы рекомендуем следующие высокоуровневые меры:

    • Используйте сквозной протокол HTTP/2 и отключите переход на более раннюю версию HTTP, если это возможно. HTTP/2 использует надежный механизм для определения длины запросов и при сквозном использовании защищен от контрабанды запросов. Если вы не можете избежать перехода на более раннюю версию HTTP, убедитесь, что вы проверяете переписанный запрос на соответствие спецификации HTTP/1.1. Например, отклоняйте запросы, содержащие символы новой строки в заголовках, двоеточия в именах заголовков и пробелы в методе запроса.

    • Заставьте интерфейсный сервер нормализовать неоднозначные запросы и заставить внутренний сервер отклонить любые неоднозначные запросы, закрыв TCP-соединение в процессе.

    • Никогда не предполагайте, что запросы не будут иметь тела. Это основная причина как CL.0, так и уязвимостей десинхронизации на стороне клиента.

    • По умолчанию соединение разрывается, если при обработке запросов возникают исключения на уровне сервера.

    • Если вы направляете трафик через прямой прокси-сервер, убедитесь, что восходящий HTTP/2 включен, если это возможно.

    Как мы показали в учебных материалах, отключение повторного использования внутренних подключений поможет смягчить определенные виды атак, но это все равно не защитит вас от атак с туннелированием запросов.