Как изменить http запрос

Is there a way to modify an HTTP request using Chrome dev tools or Firebug? For example when developing locally and testing in Chrome, I have a page that needs an HTTP request to fill some data. Be...

Is there a way to modify an HTTP request using Chrome dev tools or Firebug? For example when developing locally and testing in Chrome, I have a page that needs an HTTP request to fill some data. Because it’s local, that service isn’t available.

Currently the only way of getting around the problem is configuring a proxy pass in Apache so it hits a QA environment for that call. I’m looking or a simpler way to achieve this because I use Jetty to test the app and can’t configure a proxy pass (or that I know of).

In other words, is there a way to create a temporary proxy pass for the current session when testing an app locally?

asked Apr 8, 2014 at 8:34

J. Lin's user avatar

3

This might help in some cases — use fetch command to send another, tampered, request. here’s how to do it in Chrome:

  1. open DevTools, tab Network
  2. clear
  3. create your request normally
  4. right click that request and select Copy > Copy as fetch
  5. go to Console tab and paste
  6. tamper the data and hit Enter

steps 1-4steps 5-6

answered Apr 7, 2020 at 9:26

oriadam's user avatar

oriadamoriadam

7,3572 gold badges47 silver badges48 bronze badges

1

You can use tweak chrome extension and you’ll be able to do exactly that, intercept and modify HTTP requests.

Hvitis's user avatar

Hvitis

4725 silver badges13 bronze badges

answered Feb 21, 2020 at 10:27

Daniel Caldas's user avatar

3

Is there a way to modify an HTTP request using Chrome dev tools or Firebug? For example when developing locally and testing in Chrome, I have a page that needs an HTTP request to fill some data. Because it’s local, that service isn’t available.

Currently the only way of getting around the problem is configuring a proxy pass in Apache so it hits a QA environment for that call. I’m looking or a simpler way to achieve this because I use Jetty to test the app and can’t configure a proxy pass (or that I know of).

In other words, is there a way to create a temporary proxy pass for the current session when testing an app locally?

asked Apr 8, 2014 at 8:34

J. Lin's user avatar

3

This might help in some cases — use fetch command to send another, tampered, request. here’s how to do it in Chrome:

  1. open DevTools, tab Network
  2. clear
  3. create your request normally
  4. right click that request and select Copy > Copy as fetch
  5. go to Console tab and paste
  6. tamper the data and hit Enter

steps 1-4steps 5-6

answered Apr 7, 2020 at 9:26

oriadam's user avatar

oriadamoriadam

7,3572 gold badges47 silver badges48 bronze badges

1

You can use tweak chrome extension and you’ll be able to do exactly that, intercept and modify HTTP requests.

Hvitis's user avatar

Hvitis

4725 silver badges13 bronze badges

answered Feb 21, 2020 at 10:27

Daniel Caldas's user avatar

3

Привет. В данной статье расскажу как и зачем можно изменять HTTP пакеты при отправке на сервер и при получении ответов от сервера.
В статье много практических примеров.

Зачем это делать ?

Пример 1. Анализ трафика.
Пользователи вашей сети пользуются вашим прокси-сервером. Вы можете увидеть на какие сайты заходят пользователи, запрещать дальнейшие переходы на эти сайты.

Пример 2. Сбор данных.
Ваши пользователи пользуются через вас некоторыми веб-ресурсами. Например, они вводят vin-номер своего автомобиля на сайте дилера авто и получают в ответ данные этого автомобиля. Вы можете сохранять эти данные в свою базу данных.

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

Пример 4. Подмена POST-данных.
Вам нужно подправить данные передаваемые на веб-сервер через POST-запрос. Существует множество информации передаваемой в POST-запросах. Пример: отправка логина/пароля на сервер в процессе авторизации. Или онлайн тест отправляет на сервер результаты вашего теста.

Установка Fiddler

  1. Переходим на https://www.telerik.com/download/fiddler, скачиваем Fiddler Classic.

  2. Установка простая и быстрая.

  3. Запускаем программу.

Настройка Fiddler

В меню File есть опция «Capture Traffic«. По умолчанию опция включена. Это означает что Fiddler прописывает в реестре Windows себя в качестве прокси-сервера. Браузеры Internet Explorer, Edge, Chrome используют данную настройку, а значит HTTP-пакеты от этих браузеров пойдут через Fiddler.

Если опция «File -> Capture Traffic» выключена, то Fiddler перестает работать как системный прокси-сервер и перехватывает только те пакеты, которые идут непосредственно на адрес Fiddler. Это может быть когда вы настроили ваше приложение или браузер сами для работы через ip/port Fiddler. По умолчанию Fiddler слушает на порту 127.0.0.1:8888

Опция «Keep: All sessions«.
В данном режиме Fiddler не очищает журнал собранных HTTP-пакетов. Если требуется продолжительная работа Fiddler, то при большой нагрузке этих пакетов будет очень много и Fiddler скушает всю доступную оперативную память компьютера. Чтобы этого не случилось переключите в режим «Keep: 100 sessions».

Опция «Decode«.
По умолчанию выключена. В процессе анализа собранных пакетов рекомендуется включить чтобы пакеты автоматически декодировались. Либо можно выделить собранные пакеты через Ctrl+A, вызвать меню нажатием правой кнопки мыши по выделенным пакетам и нажать «Decode Selected Sessions».

Основные настройки

Переходим в «Tools -> Options…«.

Вкладка «HTTPS».
После установки Fiddler не собирает HTTPS-трафик, это необходимо включить. Ставим галочку в опции «Decrypt HTTPS traffic«. После этого Fiddler сгенерирует самоподписанный сертификат и спросит хотите ли установить данный сертификат. Отвечаем да.

Опция «Ignore server certificate errors (unsafe)» — сразу можно не включать. На некоторых порталах бывают ошибки сертификатов, но это редко. Как увидите так включите )
Настройка протоколов. По умолчанию стоит значение «<client>;ssl3;tls1.0». Советую сразу установить значение на «<client>;ssl3;tls1.0;tls1.1;tls1.2». После изменения настроек необходимо перезапустить программу чтобы настройки вступили в силу.

Кнопка «Actions«:

«Trust Root Certificate» — если сгенерированный Fiddler сертификат вы не установили после включения опции «Decrypt HTTPS traffic», то можно это сделать здесь.

«Export Root Certificate to Desktop» — если вы планируете использовать Fiddler как прокси-сервер локальной сети, то на каждом устройстве пользователя необходимо установить сгенерированный выше сертификат. С помощью этой опции сохраняете сертификат на ваш рабочий стол.

«Reset All Certificates» — в некоторых случаях необходимо сгенерировать новый сертификат взамен старого. В этом случае сбрасываем все Fiddler-сертификаты и генерируем новый сертификат.

Вкладка «Connections».
Здесь устанавливаем на каком порту Fiddler работает как прокси-сервер. Порт по умолчанию «8888».

«Allow remote computers to connect» — включаем опцию чтобы Fiddler начал принимать подключения от других компьютеров.

«Act as system proxy on startup» — по умолчанию опция включена. Если включена, то при запуске опция «File -> Capture Traffic» включена.

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

Вкладка «Gateway».
Здесь устанавливаем куда Fiddler отправляет входящие пакеты, какой прокси использует.

«Use System Proxy (recommended)» — использование системного прокси из реестра текущего пользователя.

«Manual Proxy Configuration» — возможность задать вручную прокси-сервер.

«No proxy» — задаем что выход в Интернет напрямую, без использования прокси.

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

Установка сертификатов на Windows устройствах

После того как сгенерированный сертификат скопирован на рабочий стол этот сертификат необходимо установить на каждое устройство которое будет использовать данный Fiddler в качестве прокси-сервера.

Для установки сертификата используем консоль управления MMC: в коммандной строке вводим команду «mmc».

В меню файл выбираем «Добавить или удалить оснастку«. Из доступных оснасток выбираем «Сертификаты» и с помощью кнопки «Добавить» выбираем данную оснастку. Нажимаем «Ок» и выбираем «учетной записи компьютера«. Это нужно чтобы открыть сертификаты которые установлены для всего компьютера, а затем установить сертификат Fiddler именно в это хранилище. Если открыть сертификаты «моей учетной записи пользователя«, то после установки сертификата Fiddler в это хранилище другие пользователи данного компьютера не смогут подключиться к Fiddler.

Установку сертификата производим в «Доверенные корневые центры сертификации».

Если ваши компьютеры находятся в домене, то используйте инструменты домена для установки сертификата каждому пользователю или на каждый компьютер сети.

Анализ трафика

В процессе работы Fiddler сниффит все HTTP-запросы и их обычно много. Для поиска необходимых запросов можно использовать фильтры. Правой кнопкой мыши выбираем лишний запрос, выбираем «Filter Now» и «Hide ‘…’» чтобы скрыть запросы к данному домену. Можно удалять вручную выделенные запросы используя кнопку «Delete«.

Кроме использования фильтров можно искать отдельный текст в теле запросов/ответов: «Ctrl+F» для открытия меню поиска. Найденные запросы подсвечиваются по умолчанию желтым цветом.

Изменение данных запросов

В Fiddler существует инструмент «Fiddler ScriptEditor» (Редактор скриптов) для создания правил модификации трафика. Запуск редактора скриптов через «Ctrl+R» или выбора пункта меню «Rules -> Customize Rules…«.

В редакторе скриптов есть два основных метода: «OnBeforeRequest» и «OnBeforeResponse«:

«OnBeforeRequest» — выполнение скриптов в этом методе происходит перед отправкой пакетов на веб-сервер.

«OnBeforeResponse» — выполнение скриптов в этом методе происходит после получения ответа от веб-сервера.

Ниже приведены примеры скриптов с указанием в каком методе их расположить.

Задача 1: Запрет сайта

Запрещаем переход на адрес сайта содержащий строку.

// OnBeforeRequest
if (oSession.uriContains("//ya.ru/")) oSession.host = 'access.denied';

Задача 2: Запрет загрузки ресурса

Запрещаем загрузку «.svg» файлов для заданного адреса сайта.

// OnBeforeRequest
if (oSession.uriContains("yastatic.net") && oSession.url.EndsWith(".svg"))
{
		oSession.host = 'na.derevnu.dedushke';
}

// или

// OnBeforeRequest
if (oSession.uriContains("yastatic.net") && oSession.url.EndsWith(".svg"))
{
		oSession.responseBodyBytes = new byte[0];
}

// OnBeforeResponse
if (oSession.uriContains("yastatic.net") && oSession.url.EndsWith(".svg"))
{
		oSession.ResponseBody = null;
}

Задача 3: Переадресация запроса

Переадресация запроса на адрес сайта содержащий строку.

// OnBeforeRequest
if (oSession.uriContains("//ya.ru/")) oSession.url = "yandex.ru"

Задача 4: Сбор данных

Пользователи подключаются через данный прокси-сервер и делают в браузерах некоторые запросы вида «https://myhost.ru?key=abcd&vin=VF38BLFXE81078232&lang=ru«. Задача записать в базу данных событие поиска и передать значение vin-номера. Данный скрипт создает файлы с названием включающем vin-номер. Кроме скрипта необходимо создать утилиту/службу, которая раз в заданный интервал читает каталог «C:vinsearch» и записывает данные в базу данных.

// OnBeforeResponse
if(oSession.uriContains("https://myhost.ru?key=") && oSession.uriContains("&vin="))
{
		oSession.utilDecodeResponse();
		// поиск позиции индекса начала vin-номера
		var startVin = oSession.url.IndexOf("vin=") + 4;

		// поиск позиции индекса конца vin-номера
		var endVin = oSession.url.IndexOf("&", startVin);

  	// поиск подстроки зная индекс начала и индекс конца подстроки
		var vin = oSession.url.Substring(startVin, endVin - startVin);

		// создание файла с именем типа vin_текущееЗначениеМиллисекунд.txt
		oSession.SaveResponseBody("C:\vinsearch\" + vin + "_" + DateTime.Now.Millisecond + ".txt");
}

Задача 5: Изменить текст в ответе

В данном примере меняем текст «Иванов» на «Петров«.

// OnBeforeResponse
if (oSession.uriContains("https://myhost.ru"))
{
		oSession.utilDecodeResponse();
  	oSession.utilReplaceInResponse('Иванов','Петров');
}

Задача 6: Заменить ресурс веб-портала на локальный ресурс

Заменим картинку веб-портала на картинку расположенною на локальном диске.

// OnBeforeResponse
if (oSession.uriContains("/Static/app/img/world.svg"))
{
		oSession.LoadResponseFromFile("c:/scripts/lang.png");	
}

Задача 7: Изменение свойств HTML-объектов

Например, есть картинка с заданными размерами в HTML и нужно эти размеры изменить.

// OnBeforeResponse
oSession.utilReplaceInResponse('/Static/app/img/world.svg" height="15" width="15" style="height: 15px','/Static/app/img/world.svg" height="1" width="1" style="height: 1px');

Задача 8: Скрыть элементы по className меняя css-файлы

В данном примере скрываем элементы зная их className в css-файле добавляя свойство «visibility: hidden;«

// OnBeforeResponse
oSession.utilDecodeResponse();
oSession.utilReplaceInResponse("#header_Area_Right {", "#header_Area_Right { visibility: hidden; ");

Задача 9: Заставить страницу открываться в текущем окне

Пример: существует JavaScript, который открывает ссылку в новом окне. Нужно сделать чтобы ссылка открывалась в текущем окне.

// OnBeforeResponse
if (oSession.uriContains("myhost.ru") && oSession.uriContains(".js"))
{
		oSession.utilDecodeResponse();
		oSession.utilReplaceInResponse("window.open(url, '_blank', option);", "window.open(url);");
}

Задача 10: Выполнение скриптов для определенных IP

В данном примере меняем текст «Иванов» на «Петров» только для IP = «192.168.0.100«

// OnBeforeResponse
if (oSession.clientIP == '192.168.0.100')
{
		oSession.utilDecodeResponse();
		oSession.utilReplaceInResponse('Иванов','Петров');
}

Задача 11: Меняем css-стили портала

Css-файлы веб-портала можно сохранить на локальном диске, отредактировать и настроить скрипт отдавать стили с локального диска, а не с портала.

// OnBeforeResponse	
if (oSession.uriContains("/banner.css"))
{
		oSession.LoadResponseFromFile("c:/scripts/banner.css");	
}

Задача 12: Запрет PUT-команды и аналогичных

Запрет команды по ее типу: «PUT«, «DELETE«, etc.

// OnBeforeRequest
if (oSession.HTTPMethodIs("PUT") && oSession.uriContains("https://myhost.ru/"))
{
		oSession.host = 'access.denied';
}

Задача 13: Изменение тела POST-запроса

Изменить тело POST-запроса для заданного портала. При авторизации на данном портале вне зависимости от введенных пользователем данных на веб-портал отправятся данные из скрипта.

// OnBeforeRequest		
if (oSession.uriContains("https://myhost.ru/") && oSession.RequestMethod == "POST")
{
		oSession.utilSetRequestBody("username=xxx&password=yyy");	
}

Задача 14: Меняем заголовки HTTP-пакета

Заголовки пакетов можно легко редактировать: удалять, добавлять, изменять.

// OnBeforeRequest

// Удалить заголовок с именем 'User-Agent'
oSession.oRequest.headers.Remove("User-Agent");

// Добавить заголовок 'xxx' со значением 'yyy'
oSession.oRequest.headers.Add("xxx", "yyy");

// Изменить значение заголовка с именем 'User-Agent' на значение 'xxx' 
oSession.oRequest.headers["User-Agent"] = "xxx";

Задача 15: Меняем Cookie

Работа с Cookie: добавление, удаление, редактирование

// OnBeforeRequest - добавить в запрос Cookie
oSession.oRequest["Cookie"] = (oSession.oRequest["Cookie"] + ";mycookie=xxx");

// OnBeforeRequest - изменить значение Cookie 'JSESSIONID' на 'xxx'
oSession.oRequest['Cookie'] = oSession.oRequest['Cookie'].Replace("JSESSIONID=","ignoredCookie=") + ";JSESSIONID=xxx";

// OnBeforeRequest - удалить Cookie 'JSESSIONID'
oSession.oRequest['Cookie'] = oSession.oRequest['Cookie'].Replace("JSESSIONID=","ignoredCookie=");
// Всем удачи на полях сниффинга данных )

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

Обратитесь к ссылке HTTP -запроса весной, выберите фильтр, чтобы вызвать запрос и ответ на дешифрование. Просто перехватите условный URL в фильтре.

Как правило, корпус запроса и корпус отклика модифицируется в фильтре. В прошлом класс упаковки обертки был необходим для создания исходного корпуса запроса из исходного объекта запроса запроса. После изменения он был перепункт в новый объект запроса и другие операции … очень хлопотно. Если вы можете определить только функцию дешифрования плюс в фильтре, а затем вызовите API для выполнения этих функций разложения.

1. Аннотация конфигурации начала класса

Новая аннотация@ServletComponentScan

@SpringBootApplication
@ServletComponentScan
public class HttpdecryptApplication {
    public static void main(String[] args) {
        SpringApplication.run(HttpdecryptApplication.class, args);
    }
}

2. Реализация фильтрации

2.1, используйте алгоритм Base64 в качестве примера

@WebFilter(urlPatterns = {"/decrypt/*"}, filterName = "decryptFilter")
@Slf4j
public class DecryptFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /**
                   * 1. Оригинальный объект запроса/ответа принудительно
         */
        HttpServletRequest originalRequest = (HttpServletRequest) request;
        HttpServletResponse originalResponse = (HttpServletResponse) response;

        /**
                   * 2. Прочтите исходный корпус запроса (CipherText), выполните функцию модифицированной функции запроса, чтобы получить модифицированный корпус запроса (Mingwen), а затем создайте новый объект запроса (включая модифицированный корпус запроса)
         */
        String originalRequestBody = ServletUtil.readRequestBody(originalRequest); // Читать исходный корпус запроса (шиферный текст)
        String modifyRequestBody = this.decryptBody(originalRequestBody); // Измените тело запроса (Mingwen)
        HttpServletRequest orginalRequest = (HttpServletRequest) request;
        ModifyRequestBodyWrapper requestWrapper = new ModifyRequestBodyWrapper(orginalRequest, modifyRequestBody);

        /**
                   * 3. Создайте новый объект ответа и выполните цепочку вызовов (используя новые объекты запроса и объекты ответа)
                   * После получения отклика прикладного уровня (Mingwen) выполните модифицированную функцию ответа и, наконец, получите тело ответа, которое необходимо отреагировать на
         */
        ModifyResponseBodyWrapper responseWrapper = new ModifyResponseBodyWrapper(originalResponse);
        chain.doFilter(requestWrapper, responseWrapper);
        String originalResponseBody = responseWrapper.getResponseBody(); // оригинальный ответ (Mingwen)
        String modifyResponseBody = this.encryptBody(originalResponseBody); // модифицированный корпус ответа (зашифрованный текст)

        /**
                   * 4. Экспорт модифицированного корпуса отклика с помощью выходного потока исходного объекта ответа
                   * Для обеспечения согласованности типа ответа и исходного запроса и перезагрузить размер тела ответа
         */
        originalResponse.setContentType(requestWrapper.getOrginalRequest().getContentType()); // Сохраняйте согласие с запросом
        byte[] responseData = modifyResponseBody.getBytes(responseWrapper.getCharacterEncoding()); // кодирование согласуется с фактическим ответом
        originalResponse.setContentLength(responseData.length);
        @Cleanup ServletOutputStream out = originalResponse.getOutputStream();
        out.write(responseData);
    }

    /**
           * Disrycring Function, используйте Base64 для расшифровки
     *
           * @param Originalbody Encrypted Body (Ciphertext)
     * @return
     */
    private String decryptBody(String originalBody) {
        return Base64.decodeToString(originalBody);
    }

    /**
           * Функция шифрования, используйте BASE64 для шифрования
     *
           * @param Оригинал нуждается в зашифрованном ответе (Mingwen)
     * @return
     */
    private String encryptBody(String originalBody) {
        return Base64.encodeToString(originalBody);
    }
}

Шаги для использования

  1. выполнитьFilterинтерфейс.
  2. использовать@WebFilterАннотация указывает URL -адрес Intercept, который можно настроить с помощью нескольких URL -адресов.

Логика обработки

  1. Прочитайте исходный корпус запроса (зашифрованный текст) из сервлета.
  2. Вызовите функцию расшифровки, чтобы получить четкий текст.
  3. Создайте новый объект запроса и корпус запроса (Mingwen) после изменения упаковки.
  4. Создайте новый объект ответа и вызовите уровень приложения, чтобы получить ответ.
  5. Получить ответ от нового объекта ответа (Mingwen).
  6. Вызовите функцию шифрования, чтобы зашифровать тело ответа.
  7. Используйте выходной поток исходного объекта ответа, чтобы вывести зашифрованный корпус отклика зашифрованного текста.

Класс упаковки запроса, используемый в функцииModifyRequestBodyWrapperИ ответная упаковкаModifyResponseBodyWrapperОпубликовано в приложении в конце статьи, вы можете напрямую скопировать его в проекте Project.

3. Проверка теста

@RestController
@Slf4j
@RequestMapping("/decrypt")
public class WebController {
    @PostMapping("/test")
    public String test(@RequestBody String requestBody) {
        log.info("Декорически данные: {}", requestBody);
        return "Успешная успешная транзакция";
    }
}
public class HttpdecryptApplicationTests {
    @Test
    public void test() {
        HttpResponse response = HttpRequest
                .post("http://127.0.0.1:10400/decrypt/test")
                .body("eyJlbmNyeXB0SW5mbyI6IuWKoOWvhuaVsOaNriIsInZlcnNpb24iOiIxLjAifQ==")
                .send();
        String result = response.bodyText();
        System.out.println(Base64.decodeToString(result)); // Успех успешной транзакции
    }
}

4. Оптимизировать улучшение

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

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

Улучшенный фильтр

@WebFilter(urlPatterns = {"/decrypt/*"}, filterName = "decryptFilter")
@Slf4j
public class DecryptFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        Function<String, String> modifyRequestBodyFun = Base64::decodeToString; // функция дешифрования
        Function<String, String> modifyResponseBodyFun = Base64::encodeToString; //  Функция шифрования
        HttpUtil.modifyHttpData(request, response, chain, modifyRequestBodyFun, modifyResponseBodyFun);
    }
}
  1. Вам нужно только настроить список URL -адресов, который необходимо перехватить на фильтре, определить дополнительную секретную функцию, а затем вызовать инкапсулированный API.
  2. Наборы символов, которые не изменяют запрос и ответ в фильтре, используются в оригинале.
  3. Вы можете только расшифровать запрос с помощью телепросного органа.
  4. кроме тогоmodifyHttpDataФункция имеет еще одну тяжелую нагрузку для поддержки модификацииContent-Type

HttpUtilОн также размещен в Приложении в конце статьи и напрямую копируйте проект проекта.

Для студентов, которые не знакомы с функциональным программированием, они могут научиться использовать Java на Javalambda Несколько встроенных функций интерфейсов выражений и Java (JDK1.8 версия и выше); вышеlambda Выражение на самом деле является кратким способом, и оно также может быть представлено своим наиболее общим способом.

Function<String, String> modifyRequestBodyFun = (originalBody) -> {
    return Base64.decodeToString(originalBody);
};
Function<String, String> modifyResponseBodyFun = (originalBody) -> {
    return Base64.encodeToString(originalBody);
};

Ссылка

  • В рамках Springboot используйте фильтр для шифрования и дешифрования

Кодовый адрес

  • github:https://github.com/senlinmu1008/spring-boot/tree/master/httpdecrypt
  • gitee:https://gitee.com/ppbin/spring-boot/tree/master/httpdecrypt

Персональный сайт

  • Gitee Pages
  • Github Pages

Приложение

Запросить упаковку

/**
   * Измените тело HTTP -запроса и ContentType для создания нового объекта запроса
   * Только для типа запроса за запрос на корпус запроса
 *
 * @author zhaoxb
 * @create 2019-09-26 17:49
 */
@Data
public class ModifyRequestBodyWrapper extends HttpServletRequestWrapper {
    /**
           * Оригинальный объект запроса
     */
    private HttpServletRequest orginalRequest;
    /**
           * Модифицированный корпус запроса
     */
    private String modifyRequestBody;
    /**
           * Измененный тип запроса
     */
    private String contentType;

    /**
           * Измените тело запроса, тип запроса используется в исходном
     *
           * @param OrginalRequest исходный объект запроса
           * @param modelRequestbody
     */
    public ModifyRequestBodyWrapper(HttpServletRequest orginalRequest, String modifyRequestBody) {
        this(orginalRequest, modifyRequestBody, null);
    }

    /**
           * Измените тело запроса и тип запроса
     *
           * @param OrginalRequest исходный объект запроса
           * @param modelRequestbody
           * @param ContentType измененный тип запроса
     */
    public ModifyRequestBodyWrapper(HttpServletRequest orginalRequest, String modifyRequestBody, String contentType) {
        super(orginalRequest);
        this.modifyRequestBody = modifyRequestBody;
        this.orginalRequest = orginalRequest;
        this.contentType = contentType;
    }

    /**
           * Создайте новый входной поток и поместите модифицированный корпус запроса в новый входной поток (используя набор символов в исходном запросе)
     *
           * @Новый входной поток return (включая модифицированный корпус запроса)
     */
    @Override
    @SneakyThrows
    public ServletInputStream getInputStream() {
        return new ServletInputStream() {
            private InputStream in = new ByteArrayInputStream(modifyRequestBody.getBytes(orginalRequest.getCharacterEncoding()));

            @Override
            public int read() throws IOException {
                return in.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    /**
           * Получите новый размер тела запроса
     *
     * @return
     */
    @Override
    @SneakyThrows
    public int getContentLength() {
        return modifyRequestBody.getBytes(orginalRequest.getCharacterEncoding()).length;
    }

    /**
           * Получите новый размер тела запроса
     *
     * @return
     */
    @Override
    @SneakyThrows
    public long getContentLengthLong() {
        return modifyRequestBody.getBytes(orginalRequest.getCharacterEncoding()).length;
    }

    /**
           * Получите новый тип запроса, по умолчанию использовать исходный запрос
     *
     * @return
     */
    @Override
    public String getContentType() {
        return StringUtils.isBlank(contentType) ? orginalRequest.getContentType() : contentType;
    }

    /**
           * Изменить ContentType
     *
           * @param name Заголовок запроса
     * @return
     */
    @Override
    public Enumeration<String> getHeaders(String name) {
        if (null != name && name.replace("-", "").toLowerCase().equals("contenttype") && !StringUtils.isBlank(contentType)) {
            return new Enumeration<String>() {
                private boolean hasGetted = false;

                @Override
                public boolean hasMoreElements() {
                    return !hasGetted;
                }

                @Override
                public String nextElement() {
                    if (hasGetted) {
                        throw new NoSuchElementException();
                    } else {
                        hasGetted = true;
                        return contentType;
                    }
                }
            };
        }
        return super.getHeaders(name);
    }
}

Ответная упаковка

/**
   * Создайте новый объект ответа, корпус ответа на кеш
   * Вы можете получить тело отклика через этот объект, а затем изменить его и вернуться к обратной стороне через исходный поток ответа
 *
 * @author zhaoxb
 * @create 2019-09-26 17:52
 */
@Data
public class ModifyResponseBodyWrapper extends HttpServletResponseWrapper {
    /**
           * Оригинальный объект ответа
     */
    private HttpServletResponse originalResponse;
    /**
           * Выходной поток тела отклика кэша (поток низкого уровня)
     */
    private ByteArrayOutputStream baos;
    /**
           * Вывод расширенный поток тела отклика
     */
    private ServletOutputStream out;
    /**
           * Поток символов тела выходного отклика
     */
    private PrintWriter writer;

    /**
           * Создайте новый объект ответа
     *
           * @param resp оригинальный ответ
     */
    @SneakyThrows
    public ModifyResponseBodyWrapper(HttpServletResponse resp) {
        super(resp);
        this.originalResponse = resp;
        this.baos = new ByteArrayOutputStream();
        this.out = new SubServletOutputStream(baos);
        this.writer = new PrintWriter(new OutputStreamWriter(baos));
    }

    /**
           * Получить выходной поток
     *
     * @return
     */
    @Override
    public ServletOutputStream getOutputStream() {
        return out;
    }

    /**
           * Получите выходной поток (символ)
     *
     * @return
     */
    @Override
    public PrintWriter getWriter() {
        return writer;
    }

    /**
           * Получите тело ответа
     *
     * @return
     * @throws IOException
     */
    public String getResponseBody() throws IOException {
        return this.getResponseBody(null);
    }

    /**
           * Получить тело ответа с помощью указанного набора символов
     *
           * @param charset set, укажите формат кодирования корпуса ответа
     * @return
     * @throws IOException
     */
    public String getResponseBody(String charset) throws IOException {
        /**
                   * Приложенный уровень будет использовать ServicetOutputStream или поток символов PrintWriter для вывода ответа
                   * Вам необходимо заставить данные этих двух потоков к потоку BytearRayoutputStream, в противном случае вы не сможете получить данные или данные неполных данных ответа
         */
        out.flush();
        writer.flush();
        return new String(baos.toByteArray(), StringUtils.isBlank(charset) ? this.getCharacterEncoding() : charset);
    }

    /**
           * Выходной поток, приложенный слой будет использовать этот поток для записи корпуса ответа
     */
    class SubServletOutputStream extends ServletOutputStream {
        private ByteArrayOutputStream baos;

        public SubServletOutputStream(ByteArrayOutputStream baos) {
            this.baos = baos;
        }

        @Override
        public void write(int b) {
            baos.write(b);
        }

        @Override
        public void write(byte[] b) {
            baos.write(b, 0, b.length);
        }

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setWriteListener(WriteListener writeListener) {

        }
    }
}

Класс инструментов Httputil Packaging

@Slf4j
public class HttpUtil {
    /**
           * Измените тело HTTP -запроса/корпус ответа
     *
           * @param OriginalRequest Оригинальный объект запроса
           * @param OriginalResponse Оригинальный объект ответа
           * @param cheape wall
           * @param modelRequestbodyfun изменить функцию запроса
           * @param modifyresponsebodyfun modify функцию корпуса ответа
     * @throws IOException
     * @throws ServletException
     */
    public static void modifyHttpData(ServletRequest originalRequest, ServletResponse originalResponse, FilterChain chain,
                                      Function<String, String> modifyRequestBodyFun, Function<String, String> modifyResponseBodyFun) throws IOException, ServletException {
        modifyHttpData(originalRequest, originalResponse, chain, modifyRequestBodyFun, modifyResponseBodyFun, null);
    }

    /**
           * Измените тело HTTP -запроса/корпус ответа
     *
           * @param запросить исходный объект запроса
           * @param ответ исходный объект ответа
           * @param cheape wall
           * @param modelRequestbodyfun изменить функцию запроса
     * @param modifyresponsebodyfun modify функцию корпуса ответа
           * @param requestContentType измененный тип запроса
     * @throws IOException
     * @throws ServletException
     */
    public static void modifyHttpData(ServletRequest request, ServletResponse response, FilterChain chain,
                                      Function<String, String> modifyRequestBodyFun, Function<String, String> modifyResponseBodyFun,
                                      String requestContentType) throws IOException, ServletException {
        /**
                   * 1. Оригинальный объект запроса/ответа принудительно
         */
        HttpServletRequest originalRequest = (HttpServletRequest) request;
        HttpServletResponse originalResponse = (HttpServletResponse) response;

        /**
                   * 2. Прочтите исходный корпус запроса (CipherText), выполните функцию модифицированной функции запроса, чтобы получить модифицированный корпус запроса (Mingwen), а затем создайте новый объект запроса (включая модифицированный корпус запроса)
         */
        String originalRequestBody = ServletUtil.readRequestBody(originalRequest); // Читать исходный корпус запроса (шиферный текст)
        String modifyRequestBody = modifyRequestBodyFun.apply(originalRequestBody); // Измените тело запроса (Mingwen)
        ModifyRequestBodyWrapper requestWrapper = modifyRequestBodyAndContentType(originalRequest, modifyRequestBody, requestContentType);

        /**
                   * 3. Создайте новый объект ответа и выполните цепочку вызовов (используя новые объекты запроса и объекты ответа)
                   * После получения отклика прикладного уровня (Mingwen) выполните модифицированную функцию ответа и, наконец, получите тело ответа, которое необходимо отреагировать на
         */
        ModifyResponseBodyWrapper responseWrapper = getHttpResponseWrapper(originalResponse);
        chain.doFilter(requestWrapper, responseWrapper);
        String originalResponseBody = responseWrapper.getResponseBody(); // оригинальный ответ (Mingwen)
        String modifyResponseBody = modifyResponseBodyFun.apply(originalResponseBody); // модифицированный корпус ответа (зашифрованный текст)

        /**
                   * 4. Экспорт модифицированного корпуса отклика с помощью выходного потока исходного объекта ответа
                   * Для обеспечения согласованности типа ответа и исходного запроса и перезагрузить размер тела ответа
         */
        originalResponse.setContentType(requestWrapper.getOrginalRequest().getContentType()); // Сохраняйте согласие с запросом
        byte[] responseData = modifyResponseBody.getBytes(responseWrapper.getCharacterEncoding()); // кодирование согласуется с фактическим ответом
        originalResponse.setContentLength(responseData.length);
        @Cleanup ServletOutputStream out = originalResponse.getOutputStream();
        out.write(responseData);
    }

    /**
           * Измените тело запроса
     *
           * @param запрос исходный запрос
           * @param modelRequestbody
     * @return
     */
    public static ModifyRequestBodyWrapper modifyRequestBody(ServletRequest request, String modifyRequestBody) {
        return modifyRequestBodyAndContentType(request, modifyRequestBody, null);
    }

    /**
           * Измените тело запроса и тип запроса
     *
           * @param запрос исходный запрос
           * @param modelRequestbody
           * @param ContentType Тип запроса
     * @return
     */
    public static ModifyRequestBodyWrapper modifyRequestBodyAndContentType(ServletRequest request, String modifyRequestBody, String contentType) {
        log.debug("ContentType to-> {}", contentType);
        HttpServletRequest orginalRequest = (HttpServletRequest) request;
        return new ModifyRequestBodyWrapper(orginalRequest, modifyRequestBody, contentType);
    }

    /**
           * Используйте исходный объект ответа, чтобы создать новый объект упаковки HTTP ответа
     *
           * @param ответ исходный объект ответа
     * @return
     */
    public static ModifyResponseBodyWrapper getHttpResponseWrapper(ServletResponse response) {
        HttpServletResponse originalResponse = (HttpServletResponse) response;
        return new ModifyResponseBodyWrapper(originalResponse);
    }
}

Модуль rewrite сервера Apache предоставляет мощные возможности по перенаправленнию запросов. Это позволяет ещё до обработки запроса, к примеру, в коде программы на PHP вашего сайта, выполнить рутинные операции по изменению адреса страницы, параметров запроса и т.п.

В данной статье мы рассмотрим случаи, когда необходимо убрать параметры GET, или наоборот добавить/изменить.

Общие принципы

Если вы уже знаете, что такое mod_rewrite, как им пользоваться под apache, то пропускайте эту часть статьи.

Apache управляется конфигурационными файлами с именем .htaccess в директориях сервера и выполняет соответствующие инструкции. Главным из них является файл находящийся в корне сайта. В подкаталогах вашего сайта также могут находится .htaccess файлы, дополняющие/изменяющие директивы заданные в файлах ближе к корню.

Вот пример типичной переадресации в CMS средствами «мод рерайт»:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

# Типичное перенаправлние всех запросов на скрипт /index.php

# данные инструкции размещаются в корне сайта в файле .htaccess

<IfModule mod_rewrite.c>

#включаем использование модуля

RewriteEngine On

#устанавливаем базовый путь переадресации

RewriteBase /

#правила пишутся друг за другом и выполняются по порядку

#1. Правило № 1

#если запрашивают файл index.php, то ничего не меняем (прочерк)

#это позволяет избежать зацикливания

RewriteRule ^index.php$ [L]

#2. Правило № 2

#Эта переадресация сложнее, она предваряется условиями

#если запрашивают не файл

RewriteCond %{REQUEST_FILENAME} !f

#если запрашивают не каталог

RewriteCond %{REQUEST_FILENAME} !d

#тогда выполняется перенаправление на скрипт index.php

RewriteRule . /index.php [L]

</IfModule>

Этот базовый пример не сможет показать все разнообразие возможностей, посмотрите обязательно полное описание команд модуля Rewrite.

Есть отличие перенаправления от переадресации.

Перенаправление

Отличие заключается в том, что в первом случае происходит обработка запроса, так как будто он был выполнен к указанному в перенаправлении скрипту/файлу/адресу. В нашем случае мы направляем все запросы к index.php

Переадресация

При переадресации, а в этом случае я бы добавил специальный флаг [R]:

RewriteRule . /index.php [R=301,L]

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

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

Добавляем параметры GET к запросу в mod rewrite

Пример запроса:

http://mysite.ru/vazniy-razdel.html

нужно переадресовать на

http://mysite.ru/drugoy-razdel?param1=value

RewriteRule ^vazniyrazdel.html$ /drugoyrazdel?param1=value [R=301,L]

Так мы добавили при переадресации нужный нам параметр GET param1.

Убрать любые GET параметры в запросе в mod rewrite

Пример запроса:

http://mysite.ru/vazniy-razdel.php?param1=value

нужно переадресовать на

http://mysite.ru/new-address.php

# обратите внимание, что условие — это регулярное выражение,

# т.е. нужно экранировать спец символы в нем, если такие используются

# а флаг [NC] — no case, означает,

# что выражение не чувствительно к регистру

RewriteCond %{QUERY_STRING} ^param1=value$ [NC]

# тот факт, что GET параметры передавать не надо

# указывается знаком ? без задания параметров

RewriteRule ^vazniyrazdel.php$ /newaddress.php? [R=301,L]

Так мы переадресуем только запрос, где есть param1=value. Если надо убрать параметры GET и выполнить редирект для любых вариантов запроса скрипта vazniy-razdel.php, то правило будет выглядеть вот так:

RewriteRule ^vazniyrazdel.php$ /newaddress.php? [R=301,L]

Теперь любые запросы на /vazniy-razdel.php переадресуются в новый раздел, при этом параметры GET будут убраны.

Заменить имя GET параметра в запросе на другое в mod rewrite

Пример запроса:

http://mysite.ru/vazniy-razdel.php?param1=value

нужно переадресовать на

http://mysite.ru/new-address.php?prm=value

# нам нужно извлечь значение старого параметра,

# чтобы потом его передать в RewriteRule

RewriteCond %{QUERY_STRING} ^param1=(.*)$ [NC]

# теперь значение value находится у нас в щаблоне %1

RewriteRule ^vazniyrazdel.php$ /newaddress.php?prm=%1 [R=301,L]

Так мы заменили параметр param1 на prm.


Данная запись опубликована в 17.11.2016 16:29 и размещена в Программирование.
Вы можете перейти в конец страницы и оставить ваш комментарий.

Первая часть этой статьи REST интерфейс и HTTP запросы. Часть 1  Получение данных – метод GET  содержит общую информацию об использовании механизма интеграции REST интерфейс из имеющих на диске ИТС материалов , а также некоторые практические примеры  использования  HTTP метода получения данных.

Во второй части я буду рассказывать особенность  организации последовательной записи объектов  REST интерфейс  методом  HTTP соединения:

ОтветHTTP = HTTPСоединение.ВызватьHTTPМетод( HTTPМетод, ЗапросHTTP)

При иллюстрации всех примеров я буду обращаться  к следующей глобальной пользовательской функции ВызватьHTTPМетодНаСервере.

 &НаСервере
 // <Описание функции>
 //
 // Параметры:
 //  <HTTPМетод>  - Строка, содержащая имя HTTP-метода для запроса ("POST"."PATCH", "PUT" ,"GET","DELETE"
 //  <HTTPСоединение>  - объект HTTPСоединение. Если не определено, то создается из параметров соединения
// <ПараметрыСоединения> - Структура параметров соединения 
 //  <АдресРесурса>  - Строка http-ресурса, к которому будет отправлен HTTP запрос.
 //  <ОтправляемыеДанные>  - Структура или соответствие, содержащие данные, отправляемые на указанный адрес для обработки  
 //                     на сервер с использованием указанного HTTP-метода "POST" или "PATCH" или  "PUT" 
 // Возвращаемое значение:
 //   Структура ответа сервера в зависимости от HTTPМетод
 //
 Функция ВызватьHTTPМетодНаСервере(HTTPМетод,HTTPСоединение = Неопределено ,ПараметрыСоединения, АдресРесурса,ОтправляемыеДанные = Неопределено) Экспорт
// 1. Создание HTTPСоединение 
Если HTTPСоединение = Неопределено Тогда
HTTPСоединение = Новый HTTPСоединение(ПараметрыСоединения.Сервер,ПараметрыСоединения.Порт,
                                      ПараметрыСоединения.Пользователь, ПараметрыСоединения.Пароль);
КонецЕсли; 
 // 2. Создание HTTPЗапрос
Заголовки = Новый Соответствие();
Заголовки.Вставить("Content-Type", "application/json");
ЗапросHTTP = Новый HTTPЗапрос( АдресРесурса, Заголовки);
 // 3. ЗаписьJson толка для создания и обновление данных
Если HTTPМетод= "POST" или "PATCH" или "PUT" Тогда
	ЗаписьJSON = Новый ЗаписьJSON; 
	ПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Авто,"",Истина);	
	ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
	ЗаписатьJSON(ЗаписьJSON, ОтправляемыеДанные); // ОтправляемыеДанные обязательны в этом случае
	СтрокаДляТела = ЗаписьJSON.Закрыть();
	ЗапросHTTP.УстановитьТелоИзСтроки(СтрокаДляТела,КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
КонецЕсли;
 //  4  Вызов Метода HTTPСоединение
ОтветHTTP = HTTPСоединение.ВызватьHTTPМетод(HTTPМетод, ЗапросHTTP);
  СтруктураОтвета = Новый Структура;
  СтруктураОтвета.Вставить("КодСостояния", ОтветHTTP.КодСостояния);
  // 5. ЧтениеJSON только для метода GET 
Если HTTPМетод = "GET"  Тогда
    ЧтениеJSON = Новый ЧтениеJSON;
    ОтветСервера = ОтветHTTP.ПолучитьТелоКакСтроку("UTF-8");
    ЧтениеJSON.УстановитьСтроку(ОтветСервера);
    Соответствие = ПрочитатьJSON(ЧтениеJSON,Истина);
    СтруктураОтвета.Вставить("ОтветСервера", Соответствие);
    СтруктураОтвета.Вставить("ОтветСервераНеРасшифрованный", ОтветСервера);
Конецесли;
 // 6. Сообщим пользователю об

Если ОтветHTTP.КодСостояния < 200 и  ОтветHTTP.КодСостояния >= 300 Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Элемент+ " Ошибка "+ ОтветHTTP.КодСостояния+ символы.ПС+
        ОтветHTTP.ПолучитьТелоКакСтроку("UTF-8"));
КонецЕсли;
Возврат СтруктураОтвета;
   КонецФункции // ВызватьHTTPМетодНаСервере()

Основные особенности  программного кода этой функции:

  1. Не обязательно создавать HTTP-Соединение для  каждого HTTP-Запроса. Однако, я рекомендую создавать каждый раз новое HTTP-Соединение для каждого  HTTP-Запроса.   Если не удалить  HTTPСоединение от предыдущего   HTTP -Запроса, то платформа 1С: предприятие может некорректно обрабатывать новый  метод  HTTP-Запрос со старым HTTP -Соединением ,  Например, если сначала удалить запись в регистре сведения, а  потом добавить новую запись методом POST при одном и том же HTTP -Соединении, то  1С  может заменить   метод POST на метод PUT в результате  сервер возвращает код ответа 405 – Использованный HTTP метод запрещен в данном контексте
  2. Я использую формат  JSON для организации чтения и записи данных.  Подробнее о работе с JSON написано в документации здесь .  Для записи объектов и текстов  на сервере  HTTP-методом POST, PATCH, PUT   я использую  объект ЗаписьJSON,  а для получения данных  HTTP-методом GET –  ЧтениеJSON .   Отметим, для  метода DELETE  не требуется JSON.
  3. Для записи ( и получения) данных в формате JSON при обращении к REST интерфейсу прикладного решения нужно  в адресе ресурса указать $format=json. Либо указать MIME тип “application/json” в заголовке, например :
Заголовки = Новый Соответствие(); 
Заголовки.Вставить("Content-Type", "application/json");
АдресРесурса ="WebBuh/odata/standard.odata/?$format=json"
ЗапросHTTP = Новый HTTPЗапрос(АдресРесурса, Заголовки);

4 . Первый параметр АдресРесурса объекта  ЗапросHTTP  является строкой сложной конструкции для программиста и часто на ней делается ошибка в результате которого метод  HTTPСоединение.ВызватьHTTPМетод(HTTPМетод, ЗапросHTTP)  возвращает статус в диапазоне 400-499, который  информирует об ошибках на стороне клиентского приложения. Эти коды могут также означать, что от клиента требуется дополнительная информация.  Коды статусов ответа по протоколу HTTP  можно посмотреть здесь 

Например, код 405 – Использованный HTTP метод запрещен в данном контексте часто связано с тем,  клиент выполняет неверное действие из-за неправильного составленного адреса ресурса в объекте  ЗапросHTTP 

5. Я сообщаю пользователю об ошибке в программном коде этой функции, когда получаю код ответа НЕ пределах 200-299.    Дело в том, есть случай когда код ответа не равно 200, а 204 например и это не ошибка. Такой код можно получить, например  если искомый ответ не найден по полям поиска или идентификационный номер.

Примеры использования  HTTP метод  POST

В качестве сервера будет выступать опубликованная на веб-сервере БД с именем WebBuh  (Демо-база “Бухгалтерия Предприятия 3.0”).

Пример №1   Создать новый элемент справочника если он не найден  по идентификационному номеру или по полям поиска

При обмене данными , часто возникает вопрос о создании нового объекта справочника, только в том случае если его.   Сначала я буду искать его в базе приемника  по идентификационному номеру, а затем по полям поиска. Если его нет , то я его добавлю его в базе приемника с таким же идентификационный номер как в базе источника . Для иллюстрации этого примера я использую  простой  справочник, который имеет только код и наименования, например  Классификатор Стран Мира

// Параметры соединения будем считать, что они определены и база публикации WebBuh существует!
 
GUID= Строка(Страна.УникальныйИдентификатор()) ;
ПоляПоиска= Новый Соответствие();
ПоляПоиска.Вставить("Description",Страна.Наименование);

//1. Поиск по УИДу
Ref_Key="";
АдресРесурса ="WebBuh/odata/standard.odata/Catalog_СтраныМира (guid'"+ GUID+ "')?$format=json&$select=Ref_Key";
Ответ = ВызватьHTTPМетодНаСервере("GET",Неопределено ,ПараметрыСоединения, АдресРесурса,Неопределено);
Массив = Ответ.Соответствие["value"];
Если Массив = Неопределено Тогда
Ref_Key=  Ответ.Соответствие["Ref_Key"];
ИначеЕсли  Массив.Количество()>0 Тогда
Ref_Key Массив[0]["Ref_Key"];
КонецЕсли;
Если НЕ ЗначениеЗаполнено (Ref_Key) Тогда
// 2. Поиск по полям поиска
ТекстЗапроса = "";
Для Каждого КлючЗначение из ПоляПоиска Цикл
ТекстЗапроса = ТекстЗапроса + КлючЗначение.Ключ + " eq '" + КлючЗначение.Значение + "' and ";
КонецЦикла;
ТекстЗапроса = Лев(ТекстЗапроса, СтрДлина(ТекстЗапроса)-5);
АдресРесурса= "WebBuh/odata/standard.odata/Catalog_СтраныМира?$filter=" + ТекстЗапроса + "&$format=json&$select=Ref_Key";
Ответ = ВызватьHTTPМетодНаСервере("GET",Неопределено ,ПараметрыСоединения, АдресРесурса,Неопределено);
Массив = Ответ.Соответствие["value"];
Если Массив = Неопределено Тогда 
Ref_Key=  Ответ.Соответствие["Ref_Key"]; 
ИначеЕсли Массив.Количество()>0 Тогда 
Ref_Key =  Массив[0]["Ref_Key"];
 КонецЕсли;
 КонецЕсли;
ДанныеСправочника = Новый соответствие(); 
ДанныеСправочника.Вставить("Description",Страна.Наименование); 
ДанныеСправочника.Вставить("Code",Страна.Код);
Если ЗначениеЗаполнено (Ref_Key) Тогда
//метод PATCH"
АдресРесурса ="WebBuh/odata/standard.odata/Catalog_СтраныМира (guid'"+ GUID+ "')?$format=json";
Ответ = ВызватьHTTPМетодНаСервере("PATCH",Неопределено ,ПараметрыСоединения, АдресРесурса,ДанныеСправочника);
Иначе //метод POST
ДанныеСправочника.Вставить("Ref_Key",GUID);
АдресРесурса= "WebBuh/odata/standard.odata/Catalog_СтраныМира?$format=json";
Ответ = ВызватьHTTPМетодНаСервере("POST",Неопределено ,ПараметрыСоединения, АдресРесурса,ДанныеСправочника);
КонецЕсли;

Пример №2 Запись в периодическом регистре сведения

В этом примере будет показано как выполнить запись в периодическом и независимом  регистре сведения. Работа с зависимыми   от  документа  регистрами не имеет практического смысла, так как запись в этих регистрах происходит  в процедуре обработки проведения в  модуле объекта документа, которая вызывается при проведении документа.

В качестве примера я буду использовать регистр сведения  Документы физических лиц.

Рис 1 Структура регистра сведения Документы физ лиц

 Данный регистр является независимым и периодическим в пределах дня.

Особенность записи регистра через протокол  odata с помощью технологии интеграции Rest – интерфейс  платформы 1С  заключается в том,  что отсутствие режим замещения  существующей записи с тем же набором значений измерений регистра и с тем же периодом (для периодических регистров). Иными словами,  если запись регистра сведений с таким набором существует, то невозможно выполнять замещение и приходится сначала удалить запись, а затем добавить.  Возможно в будущих платформах 1С такая  возможность появится .Однако, на сколько мне известно последнее  расширение поддержки протокола OData  Реализовано в версии 8.3.8.1652.

Итак, поскольку  через  протокол  OData запись будет только дописана , то метод PATCH, PUT  не применимы для сущности Регистр сведения.  Попытка применять эти методы PATCH  и  PUT  вызывает  код  ответа сервера 405 – Использованный HTTP метод запрещен в данном контексте.  Аналогично ситуация возникает при попытке применять метод POST  в периодическом регистре  с существующей записью   с тем же периодом.

В следующем программном коде, мы будем выполнять сначала метод DELETE,  а затем  метод POST.

Для сокращения  программного кода будем  считать, что все  объекты ссылочного типа (ВидДокумента_Key и ФизическоеЛицо_Key) , на которые ссылается регистр сведения   добавлены в базе приемника с помощью программного кода примера №1

//1 Подготовим Адрес ресурса для удаления
ДанныеСсылочногоТипа = Новый Структура();
ДанныеСсылочногоТипа.Вставить("ВидДокумента_Key",ВидДокумента_Key);
ДанныеСсылочногоТипа.Вставить("Физлицо_Key",ФизическоеЛицо_Key);
ДанныеНЕСылочногоТипа = Неопределено;
Период = ТекущаяДата();
ТекстЗапроса="";
Если Период <> Неопределено Тогда
ФорматированныйПериод = Формат(Период,"ДФ=yyyy-MM-ddTHH:mm:ss");
ТекстЗапроса = ТекстЗапроса+ "Period = datetime'"+ ФорматированныйПериод+ "'" ; 
КонецЕсли;
Если ДанныеСсылочногоТипа <> Неопределено Тогда
Для Каждого КлючЗначение из ДанныеСсылочногоТипа Цикл
Запитая= ?(ЗначениеЗаполнено(ТекстЗапроса),",",""); 
ТекстЗапроса = ТекстЗапроса + Запитая+ КлючЗначение.Ключ + "=guid'"+ КлючЗначение.Значение+ "'";
КонецЦикла;
КонецЕсли;
Если ДанныеНЕСылочногоТипа <> Неопределено Тогда
Для Каждого КлючЗначение из ДанныеНЕСылочногоТипа Цикл
Запитая= ?начениеЗаполнено(ТекстЗапроса),",","");
ТекстЗапроса = ТекстЗапроса + Запитая + КлючЗначение.Ключ + "=" + КлючЗначение.Значение; 
КонецЦикла;
КонецЕсли;

АдресРесурса= "WebBuh/odata/standard.odata/InformationRegister_ДокументыФизическихЛиц(" + ТекстЗапроса+ ")?$format=json";
Ответ = ВызватьHTTPМетодНаСервере("DELETE",Неопределено ,ПараметрыСоединения, АдресРесурса,Неопределено);

//2 Подготовим данные для новой записи
ДанныеДляЗаписи = Новый Структура();
ДанныеДляЗаписи.Вставить("Period",Период);
ДанныеДляЗаписи.Вставить("ВидДокумента_Key",ВидДокумента_Key); 
ДанныеДляЗаписи.Вставить("Физлицо_Key",ФизическоеЛицо_Key);
ДанныеДляЗаписи.Вставить("Серия",СерияДокумента);
ДанныеДляЗаписи.Вставить("Номер",НомерДокумента);
ДанныеДляЗаписи.Вставить("ДатаВыдачи",ДатаВыдачиДокумента);
ДанныеДляЗаписи.Вставить("СрокДействия",СрокДействияДокумента);
ДанныеПаспорта.Вставить("КемВыдан",КемВыданДокумент);
АдресРесурса= "WebBuh/odata/standard.odata/InformationRegister_ДокументыФизическихЛиц?$format=json";
Ответ = ВызватьHTTPМетодНаСервере("POST",Неопределено ,ПараметрыСоединения, АдресРесурса,ДанныеДляЗаписи);


Продолжение следует …….

Понравилась статья? Поделить с друзьями:
  • Как изменить html через php
  • Как изменить homepath
  • Как изменить html файл на телефоне
  • Как изменить html файл на сервере
  • Как изменить html файл python