Парсинг URL

markers 52 3 2

Раскладываем URL по полочкам

Введение

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

Код:

Функция РазложитьURL(URL) Экспорт
	
	Результат = СтруктураURL();
	НачальнаяПозицияПоиска = 1;
	
	// Получим протокол
	ДанныеПарсинга = РаспарситьСтроку(URL, НачальнаяПозицияПоиска,,,, "://");
	
	Если ДанныеПарсинга.Успех Тогда
		
		Результат.Протокол = НРег(ДанныеПарсинга.Вырез);
		
		Если Результат.Протокол <> "https" Тогда
			
			Результат.БезопасноеСоединение = Ложь;
			Результат.Порт = 80;
			
		КонецЕсли;
		
		НачальнаяПозицияПоиска = ДанныеПарсинга.ВырезКонец + 3; // Добавим размер шаблона
		
	КонецЕсли;
	
	// Получим адрес хоста
	ДанныеПарсинга = РаспарситьСтроку(URL, НачальнаяПозицияПоиска,,,, "/");
	ДостигнутКонецСтроки = Ложь;
	
	Если ДанныеПарсинга.Успех Тогда
		
		// Найден конец адреса и он продолжается
		Результат.АдресВебСервера = ДанныеПарсинга.Вырез;
		НачальнаяПозицияПоиска = ДанныеПарсинга.ВырезКонец;
		
	Иначе
		
		// Не найден конец адреса, значит он закончился, берем всю строку
		ДанныеПарсинга = РаспарситьСтроку(URL, НачальнаяПозицияПоиска);
		
		Если ДанныеПарсинга.Успех Тогда
			
			Результат.АдресВебСервера = ДанныеПарсинга.Вырез;
			НачальнаяПозицияПоиска = ДанныеПарсинга.ВырезКонец;
			ДостигнутКонецСтроки = Истина;
			
		КонецЕсли;
		
	КонецЕсли;
	
	// Обработаем адрес веб-сервера
	Если Не ПустаяСтрока(Результат.АдресВебСервера) Тогда
		
		// Если адрес содержит параметры авторизации, выделим их
		ДанныеПарсинга = РаспарситьСтроку(Результат.АдресВебСервера,,,,, "@");
		
		Если ДанныеПарсинга.Успех Тогда
			
			Результат.АдресВебСервера = Сред(Результат.АдресВебСервера, ДанныеПарсинга.ВырезКонец + 1);
			ПараметрыАвторизации = ДанныеПарсинга.Вырез;
			Результат.Авторизация = Новый Структура("ИмяПользователя, Пароль", "", "");
			ДанныеПарсинга = РаспарситьСтроку(ПараметрыАвторизации,,,,, ":");
			
			Если ДанныеПарсинга.Успех Тогда
				
				Результат.Авторизация.ИмяПользователя = ДанныеПарсинга.Вырез;
				Результат.Авторизация.Пароль = Сред(ПараметрыАвторизации, ДанныеПарсинга.ВырезКонец + 1);
				
			Иначе // Есть только логин
				
				Результат.Авторизация.ИмяПользователя = ПараметрыАвторизации;
				
			КонецЕсли;
			
		КонецЕсли;
		
		// Если адрес содержит порт, выделим его
		ДанныеПарсинга = РаспарситьСтроку(Результат.АдресВебСервера,,,,, ":");
		
		Если ДанныеПарсинга.Успех Тогда
			
			Результат.Порт = Число(Сред(Результат.АдресВебСервера, ДанныеПарсинга.ВырезКонец + 1));
			Результат.АдресВебСервера = ДанныеПарсинга.Вырез;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если Не ДостигнутКонецСтроки и СтрДлина(URL) - НачальнаяПозицияПоиска <= 1 Тогда
		
		ДостигнутКонецСтроки = Истина;
		
	КонецЕсли;
	
	Если ДостигнутКонецСтроки Тогда
		
		ВыделитьЯкорьИзURL(Результат);
		ВыделитьПараметрыЗапросаИзURL(Результат);
		
		Возврат Результат;
		
	КонецЕсли;
	
	// Получим текст запроса
	ДанныеПарсинга = РаспарситьСтроку(URL, НачальнаяПозицияПоиска);
	
	Если ДанныеПарсинга.Успех Тогда
		
		Результат.Запрос = ДанныеПарсинга.Вырез;
		
	КонецЕсли;
	
	// Получим путь запроса
	ДанныеПарсинга = РаспарситьСтроку(URL, НачальнаяПозицияПоиска, "/", Истина,, "/", Истина);
	
	Если ДанныеПарсинга.Успех Тогда
		
		Результат.ПутьЗапроса = ?(ДанныеПарсинга.Вырез = "/", "", ДанныеПарсинга.Вырез);
		НачальнаяПозицияПоиска = ДанныеПарсинга.ВырезКонец;
		
		Если СтрНайти(Результат.ПутьЗапроса, "_t", НаправлениеПоиска.СКонца) > 0 Тогда
			
			Результат.ТипБазы = 1; // Тестовая
			
		ИначеЕсли СтрНайти(Результат.ПутьЗапроса, "_n", НаправлениеПоиска.СКонца) > 0 Тогда
			
			Результат.ТипБазы = 2; // Копия (тестовая)
			
		КонецЕсли;
		
	КонецЕсли;
	
	// Получим конечную точку (условно говоря, скрипт)
	ДанныеПарсинга = РаспарситьСтроку(URL, НачальнаяПозицияПоиска);
	
	Если ДанныеПарсинга.Успех Тогда
		
		Результат.КонечнаяТочкаПути = ДанныеПарсинга.Вырез;
		ДанныеПарсинга = РаспарситьСтроку(Результат.КонечнаяТочкаПути,,,,, "?");
		
		Если ДанныеПарсинга.Успех Тогда
			
			Результат.КонечнаяТочкаПути = ДанныеПарсинга.Вырез;
			
		КонецЕсли;
		
	КонецЕсли;
	
	ВыделитьЯкорьИзURL(Результат);
	ВыделитьПараметрыЗапросаИзURL(Результат);
	
	Возврат Результат;
	
КонецФункции

Функция СтруктураURL()
	
	Состав = Новый Структура;
	Состав.Вставить("Авторизация"); //Новый Структура("ИмяПользователя, Пароль");
	Состав.Вставить("Протокол", "https");
	Состав.Вставить("БезопасноеСоединение", Истина);
	Состав.Вставить("АдресВебСервера", "");
	Состав.Вставить("Порт", 443);
	Состав.Вставить("Запрос");
	Состав.Вставить("ПутьЗапроса");
	Состав.Вставить("КонечнаяТочкаПути");
	Состав.Вставить("Параметры", Новый Соответствие);
	Состав.Вставить("ТипБазы", 0); // 0 - Рабочая, 1 - тестовая, 2 - копия рабочей
	Состав.Вставить("Якорь"); // Всё что после #
	
	Возврат Состав;
	
КонецФункции

Процедура ВыделитьПараметрыЗапросаИзURL(ДанныеURL)
	
	ДанныеПарсинга = РаспарситьСтроку(ДанныеURL.Запрос,,,,, "?");
	
	Если Не ДанныеПарсинга.Успех Тогда
		
		Возврат;
		
	КонецЕсли;
	
	ПозицияРазделителя = ДанныеПарсинга.ВырезКонец;
	ДанныеПарсинга = РаспарситьСтроку(ДанныеURL.Запрос,,,, ПозицияРазделителя);
	
	Если Не ДанныеПарсинга.Успех Тогда
		
		Возврат;
		
	КонецЕсли;
	
	ЗапросБезПараметров = ДанныеПарсинга.Вырез;
	ДанныеПарсинга = РаспарситьСтроку(ДанныеURL.Запрос, ПозицияРазделителя + 1);
	ДанныеURL.Запрос = ЗапросБезПараметров;
	
	Если Не ДанныеПарсинга.Успех Тогда
		
		Возврат;
		
	КонецЕсли;
	
	СписокПараметров = СтрРазделить(ДанныеПарсинга.Вырез, "&", Ложь);
	
	Для Каждого ТекПараметр Из СписокПараметров Цикл
		
		КлючИЗначение = СтрРазделить(ТекПараметр, "=", Ложь);
		
		Если КлючИЗначение.Количество() >= 2 Тогда
			
			ДанныеURL.Параметры.Вставить(КлючИЗначение[0], КлючИЗначение[1]);
			
		Иначе
			
			ДанныеURL.Параметры.Вставить(КлючИЗначение[0]);
			
		КонецЕсли;
		
	КонецЦикла;	
	
КонецПроцедуры

Процедура ВыделитьЯкорьИзURL(ДанныеURL)
	
	ДанныеПарсинга = РаспарситьСтроку(ДанныеURL.Запрос,,,,, "#");
	
	Если Не ДанныеПарсинга.Успех Тогда
		
		Возврат;
		
	КонецЕсли;
	
	ДанныеURL.Якорь = Сред(ДанныеURL.Запрос, ДанныеПарсинга.ВырезКонец + 1);
	ДанныеURL.Запрос = ДанныеПарсинга.Вырез;
	
КонецПроцедуры

Примеры:

Вызываем функцию: РазложитьURL("https://test:1234@site.com:211/locator_n/script?f=sa&aa=11#test");
Получаем структуру, содержащая поля:
Авторизация - Если URL содержала параметры авторизации, содержит вложенную структуру с свойсвами "ИмяПользователя" и "Пароль". В противном случае, остается Неопределено. В примере: ИмяПользователя: test, пароль: 1234
Протокол - Выделенный протокол из URL, по умолчанию https. В примере: https
БезопасноеСоединение - Требуется ли безопасное подключение к URL или нет, по умолчанию Истина. Если протокол не равен https, становится Ложь. В примере: Истина
АдресВебСервера - Адрес хоста, в примере: site.com
Порт - Порт подключения, по умолчанию 443, но если порт не указан и БезопасноеСоединение = Ложь, меняется на 80. В примере: 211
Запрос - Содержит полный текст запроса после адреса веб-сервера, В примере: /locator_n/script?f=sa&aa=11#test
ПутьЗапроса - Содержит путь запроса. В примере: /locator_n/
КонечнаяТочкаПути - Условно, имя вызываемого скрипта. В примере: script
Параметры - Содержит Соответствие, состоящее из ключей - имен параметров и значений - значений переданных параметров. В примере:

Ключ Значение
f sa
aa 11

ТипБазы - Это свойство не относится к URL, возвращает цифру 0-2 в зависимости от окончания пути запроса, по умолчанию 0, 1 - если окончание _t, 2 - если окончание _n. Это так у нас определяется тип базы, рабочая, тестовая или копия рабочей. В примере: 1
Якорь - Свойство содержит якорь (Значение после символа #), если он был указан, в примере: test

0

См. также

Упрощенный парсинг строк

Пример использования регулярных выражений RegExp в 1С

Модератору