Формування URL для HTTP запитів в ZennoPoster

Відправити запит методом GET чи POST програмою ZennoPoster не складно. Напевне складніше все таки знайти в консолі розробника Chrome чи Fiddler необхідний запит, який захочеться повторити. Проте буває і так, що нібито все сформовано, відправляєш – а сервер не приймає і не повертає очікуваний результат. Так от в цей момент і приходиться шаманити над параметрами, щоб привести їх до бажаного вигляду.

Один із параметрів, який потрібно сформувати, це URL.
Звичайно, що він може бути простим, наприклад https://nghttp2.org/httpbin/get
В цьому випадку нічого придумувати не потрібно, можна сміливо вказувати його за допомогою літерала (рядка одягнутого в подвійні кавички), або змінної.
Тут важливо помітити, що важливо вказувати протокол http або https в залежності від того, на якому працює сайт, до якого необхідно звернутись. Справа в тому, що сайт може працювати на https, а ми можемо відправляти запит використовуючи http (це може бути випадково, а може бути спеціально). Так от сервіс може автоматично за допомогою PHP переадресації відправити на необхідний протокол, а може цього не зробити. Може повернути в результаті необхідні cookie для наступних запитів, а може не повернути.
Зустрічаються навіть такі, які замість результату повертають перевірку CloudFlare чи каптчу. Тому, потрібно пам’ятати що протокол важливий. До мене колись навіть замовник звертався, який автоматизовував щось на Amazon, свормував необхідний ланцюжок запитів самостійно, але в якийсь момент сайт не повертав необхідні дані. І коли розглядали кожний запит і параметри які він використовував, виявилось що замість https він в одному запиті використовував http, що і було проблемою. А через вставновлене значення UseRedirect: true він не міг побачити що щось відбувається не за його планом.
Такий простий URL може закінчуватись на знак слеш ( / ), може закінчуватись на page.php чи будь-яке інше розширення, або без нього. Зазвичай коли закінчується на ( / ) це означає що ми звертаємось до сторінки яка встановлена за-змовчуванням на сервері, наприклад index.php чи index.html, хоча може бути переопреділена розробниками сервісу на будь-яку іншу.
Якщо закінчується не на слеш – значить ми звертаємось до сторінки, наприклад page.php.
Якщо .php немає, значить в налаштуваннях сервера спеціально .php замінюється на пусте значення.
Є ще варіанти, коли на стороні PHP всі значення які ідуть після першого слеша, який іде після доменного імені, розглядаються сервером як параметри (тобто піддаються на сервері якійсь додатковій обробці).
Цю інформацію потрібно тримати в своїх думках тоді, коли ми формуємо URL, тому що ми повинні хоча б приблизно уявляти що буде відбуватись з даними дальше вже на стороні сервера. В одному випадку, коли є page.php, то скоріш за все значення page.php не буде піддаватись ніякій додатковій обробці, а в інших випадках – до значення може бути примінено щось на кшталт перетворення htmlentities, urldecode чи punycode.

URL може бути також складеним з двух частин розділених знаком питання ( ? ), після якого йдуть пари ключ=значення, які можуть з’єднуватись через амперсанд ( & ). В залежності від сервера до якого ми звертаємось і розробників які на його стороні приймають значення параметри ключ=значення також можуть піддаватись обробці, або не піддаватись їй. В одному випадку послідовність таких пар не важлива, а у інших випадках вони повинні бути відсортовані в алфавітному порядку по значенню ключа. Також потрібно брати до уваги, що якщо сайт знаходиться за CloudFlare, то параметри можуть бути відсортованими на його стороні без нашої участі.

Приведу приклади фрагментів коду, які позволяють формувати URL:

// Варіант формування рядка з параметрами без сортування
var url_params = new Dictionary<string, string>();
	url_params.Add("key1","value1" );
	url_params.Add("key2","value2"); 
string query = string.Join("&", url_params.Select(x=>string.Join("=", new[] { x.Key, x.Value })));
// Варіант формування рядка з параметрами з сортуванням по значенню ключа в алфавітному порядку
var url_params = new Dictionary<string, string>();
	url_params.Add("key1","value1" );
	url_params.Add("key2","value2"); 
string query = string.Join("&", url_params.OrderBy(x=>x.Key).Select(x=>string.Join("=", new[] { x.Key, x.Value })));

Власне код, який використовувався вище приміняється тоді, коли в налаштуваннях запитів встановлено властивість, яка вказує програмі ZennoPoster самостійно привести параметри URL до вигляду URLencode.

	UseOriginalUrl: true // змінювати параметри url

Але, в деяких випадках, виявляється що такі зміни програмою ZennoPoster проводяться не корректно, і запит відправляється, а необхідний результат не одержується. Тому, в цей момент потрібно заборонити програмі ZennoPoster змінювати параметри нашого запиту.

	UseOriginalUrl: false // не змінювати параметри url

В цьому випадку, спочатку пробуємо відправляти запит без змін. І якщо бачимо що результат не одержується, то розуміємо, що потрібно перевести параметри в URLencode.

// Варіант формування рядка з параметрами з сортуванням по значенню ключа в алфавітному порядку
// Додатково параметри переводяться в UrlEncode
// Можливо в GAS потрібно добавити посилання на бібліотеку System.Web.dll
var url_params = new Dictionary<string, string>();
	url_params.Add("key1",System.Web.HttpUtility.UrlEncode("value1", Encoding.UTF8));
	url_params.Add("key2",System.Web.HttpUtility.UrlEncode("value2", Encoding.UTF8)); 
string query = string.Join("&", url_params.OrderBy(x=>x.Key).Select(x=>string.Join("=", new[] { x.Key, x.Value })));

Важливо, що при використанні UseOriginalUrl: true параметри будуть переведені в UrlEncode спочатку нами, а потім програмою ZennoPoster, після чого сервер не зможе їх правильно розпізнати. Тому на це потрібно звертати увагу – або ми самостійно переводимо в UrlEncode, або довіряємо це програмі ZennoPoster. Також деякі сайти напевне через помилки розробників потребують перевести в UrlEncode два рази (перевести в UrlEncode, і потім результат ще раз перевести в UrlEncode), і хоча таке зустрічається рідко, все таки також про це потрібно пам’ятати, коли виконуємо запит, а результат одержати не виходить.

Є ще декілька варіантів кодування параметрів, які можуть зустрічатись при формуванні URL, тому залишу їх тут:

string  value1 = System.Web.Security.AntiXss.AntiXssEncoder.HtmlFormUrlEncode("value1", Encoding.UTF8); // application/x-www-form-urlencoded
string  value2 = System.Web.HttpUtility.UrlEncode("value2", Encoding.UTF8);
string  value3 = Uri.EscapeDataString("value3");
string  value4 = Uri.EscapeUriString("value4");
string  value5 = Macros.TextProcessing.UrlEncode("value5", "windows-1251");

Також, інколи приходиться переводити в UrlEncode не тільки значення, але і ключі, можливо ще і в якомусь специфічному кодуванні. Можливий варіант що робити це потрібно вже з кінцевим сформованим варіантом, а не як формувалось вище, де зміни вносились саме для кожного значення окремо. Приклад такого формування приведу нижче:

// Варіант формування рядка з параметрами з сортуванням по значенню ключа в алфавітному порядку
// Випадок, коли потрібно переводити і ключі і значення в специфічному кодуванні
// Можливо в GAS потрібно добавити посилання на бібліотеку System.Web.dll
var url_params = new Dictionary<string, string>();
	url_params.Add("key1","value1" );
	url_params.Add("key2","value2"); 
string query = string.Join("&", url_params.OrderBy(x=>x.Key).Select(x=>string.Join("=", new[] { x.Key, x.Value })));
	   query = System.Web.HttpUtility.HttpUtility.UrlEncode(query) ,Encoding.GetEncoding("ISO-8859-1"));
// Варіант формування рядка з параметрами
// Використовується сортування по ключу
// можливо потрібно добавити в GAS бібліотеку System.Net.Http.dll
var url_params = new Dictionary<string, string>();
	url_params.Add("key1","value1" );
	url_params.Add("key2","value2"); 
var url_params_data = new System.Net.Http.FormUrlEncodedContent(url_params.OrderBy(x=>x.Key));
string query = url_params_data.ReadAsStringAsync().Result;

Після чого вже можна з’єднати параметри, і одержати необхідний URL

string url = string.Join("?", new[]{"https://nghttp2.org/httpbin/get", query});

А дальше вже використовувати його для відправки запитів. Додаткову інформацію про відправку HTTP запитів програмою ZennoPoster розміщував в публікаціях:

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *