Как и почему развивались платформы современных веб-приложений для отделения URL-маршрутов от файловой системы?


66

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

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

Вопрос

Как и почему это стало обычным явлением? Как и почему было решено, что «лучше» до такой степени, что когда-то банальный подход к файлу был фактически оставлен?

Другие ответы

Здесь есть аналогичный ответ, который немного касается концепции маршрута, а также некоторых преимуществ и недостатков: почему в PHP-фреймворках используется концепция «маршрута»?

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

Кроме того, большинство из упомянутых преимуществ и недостатков, по-видимому, недостаточно значительны, чтобы оправдать такие глобальные изменения. Единственное преимущество, которое я вижу в этом изменении, возможно, это скрытие системы файлов / папок от конечного пользователя, а также отсутствие ?param=value&param2=value, что делает URL-адреса немного чище. Но были ли они единственной причиной перемен? И если да, то почему эти причины были за этим?

Примеры:

Я наиболее знаком с PHP-фреймворками, и многие популярные современные фреймворки используют этот разделенный подход маршрутизации. Чтобы это работало, вы настраиваете перезапись URL-адреса в Apache или аналогичном веб-сервере, где функциональность веб-приложения обычно не запускается через путь URL-адреса к файлу.

Zend Expressive

https://docs.zendframework.com/zend-expressive/features/router/aura/
https://docs.zendframework.com/zend-expressive/features/router/fast-route/
https: //docs.zendframework. ком / Зенд-выразительный / функция / маршрутизатор / ZF2 /

Zend Framework

https://docs.zendframework.com/zend-mvc/routing/

Laravel

https://laravel.com/docs/5.5/routing

CakePHP

https://book.cakephp.org/3.0/en/development/routing.html


14
было ли действительно такое изменение? или, может быть, большинство языков / сред никогда не использовали прямое сопоставление файловой системы? может быть, это просто PHP, который догоняет остальных вменяемых? Ваши наблюдения по моему мнению неверны, поэтому нет хорошего ответа. также «сдвиг», о котором вы упомянули, произошел только в мире PHP. но это слишком широкий вопрос, на мой взгляд ...
RSM

2
@rsm У меня была похожая первая реакция, но если подумать дальше, это действительно то, что было сделано на многих языках и платформах, что делает его действительно распространенным источником уязвимостей.
JimmyJames

6
@rsm, это может быть более очевидно в PHP-фреймворках, но можно использовать другой путь - в определенное время, до того, как какой-либо фреймворк действительно завоевал популярность, будь то ASP, .NET, PHP, JSP и т. д., в Интернете в основном использовались прямые подход к файлу. Почему все эти фреймворки были разработаны для использования несвязанного подхода? Технически, прямой подход к файлу все еще возможен, и я уверен, что современные фреймворки могут использовать его. Или они могут? Может быть, они не могут, и, может быть, есть веские причины, почему они этого не делают? Каковы будут эти причины ..? Они даже не предоставляют способ или плагин для этого, они просто полностью уничтожили файл.
Деннис

2
Не является ли это (частично) также просмотром URL ( локатор , как найти ресурс) как URI (и идентификатор )?
Хаген фон Айцен

2
Связанное чтение из древней истории: классные URI не меняются - Тим Бернерс-Ли, 1998
Майкл Хэмптон,

Ответы:


71

В своей основной форме веб-сайт обслуживает статические файлы. Отображение пути URL к пути к файлу является наиболее очевидным выбором; по сути, это FTP-сайт только для чтения.

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

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

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

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

Но я думаю, что настоящее изменение произошло, когда пользователи захотели избавиться от расширения файла по пути. Получение myPage.asp или myPage.php было чем-то, что смущало «нормальных» людей и мешало SEO.

Поскольку пользователь видит путь, он стал частью пользовательского интерфейса в Интернете, и поэтому он должен быть полностью свободен от каких-либо технических ограничений. Мы потеряли «www», и практически все это «.com». Несколько URL будут указывать на одну и ту же страницу.

Если я заработаю больше денег с mydomain.com/sale против www.mydomain.co.uk/products/sale.aspx, то я не хочу, чтобы на моем пути стояли какие-либо технические ограничения.


7
Я всегда думал, что желание скрыть расширения файлов было отчасти "безопасностью по незаметности", что усложняло задачу определения того, какая технология использовалась сайтом, чтобы упростить таргетинг на конкретные подключенные / известные эксплойты определенных серверов. и техники в то время
Caius Jard

20
@CaiusJard - это часть этого, но другая часть - технологическая независимость - заменив file.html в наших путях, мы не хотели застрять с другим переключателем позже (например, file.phtml в file.php или даже в file.asp). Но поскольку мы разобщаем URL и путь к файловой системе (используя маршрутизацию или что-то еще) для доступа к ресурсам, созданным из записей базы данных и / или других источников, зачем вообще иметь расширение в URL?
HorusKol

39
@HorusKol Технологический агностицизм - это даже не необходимость менять все файлы на вашем пути. Возможность изменения внутренних технологий без нарушения рабочего процесса и закладок вашего клиента и без разрушения вашего SEO может быть огромной .
Шейн

7
Интересно, что никогда не было рекомендовано иметь расширения имени файла в URI, поэтому они должны были быть отделены от файловой системы на ранней стадии. Самая ранняя ссылка, которую я могу найти для этого, относится к 1998 году , который на самом деле предшествовал большинству событий, описанных в этом ответе.
Конрад Рудольф

8
В старые времена mydomain.com/sale все еще работал; он перенаправлялся в / sale / и загружался просто отлично (ваша страница была mydomain.com/sale/index.aspx, но никто так и не увидел index.aspx).
Джошуа

38

Вы можете обратиться к официальному документу Роя Филдинга о REpresentational State Transfer (REST) о том, когда и почему . Первой платформой, о которой я знал, которая делала различие между ресурсом и файлом, был Ruby on Rails, представляющий концепцию URL для маршрутизации кода.

Основными концепциями REST, которые были трансформационными, были:

  • URL представляет ресурс
  • Этот ресурс может иметь несколько представлений
  • URL не должен ломаться, если приложение реструктурировано
  • Приложения должны охватывать безгражданство Интернета

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

  • Ссылки на ресурсы постоянно нарушаются по мере реорганизации сайтов
  • Ресурс и представление связаны между собой

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

  • Не все ресурсы равны по важности. Вот почему у вас все еще есть ресурсы, основанные на стилях, обслуживаемые напрямую (CSS, JavaScript / EcmaScript, изображения)
  • В REST, например, в HATEOAS , есть усовершенствования, которые лучше поддерживают одностраничные приложения.

когда вы говорите «представление», вы имеете в виду такие вещи, как JSON / HTML / TEXT / и т. д.? Я смутно знаком с REST, но я думаю, что даже с REST у вас должен быть какой-то триггер для изменения представления ответа ...
Деннис

@ Денис, да. HTTP имеет несколько заголовков, которые могут быть использованы для указания на нужную форму ( developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation ), а REST - это сильные стороны HTTP. Тем не менее, приложение нередко имеет собственный способ согласования желаемого контента.
Берин Лорич

5
CGI (1993), Servlets (1997) и JSP (1999) часто отделяли URL-адреса от файловой системы и предшествовали REST (2000). Однако этот ответ в основном верен при определении причин популярности шаблона проектирования: REST, Java Struts и Ruby on Rails оказывают огромное влияние на популярность разделения ресурсов и представлений в 21-м веке.
dcorking

1
Согласно статье Филдинга, «первое издание REST было разработано в период с октября 1994 года по август 1995 года»
Коннор

1
@dcorking, CGI в то время не отделял URL-адреса от файлов, он просто запускал файл вместо 9 раз из 10. Сервлеты могли бы быть наиболее близкими, но если вы говорите о концепции маршрутов и наличии спроектированного пространства URL-адресов , которая пришла с Rails и фреймворками
Берин Лорич

20

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

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

Затем наступил век подачи динамического контента. CGI-скрипты (и все, что произошло от них) создавали страницы на лету, опираясь на какую-то базу данных. GET параметры в URL стали обычным явлением, например en.wikipedia.org/w/index.php?title=Path_(computing) .

Однако удобнее иметь читаемый URL, состоящий только из сегментов пути. Таким образом, динамические приложения отображают простые пути (например, en.wikipedia.org/wiki/Path_(computing) ) в параметры, и эти сопоставления известны как «маршруты».

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


12

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

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

Одной из причин является стремление к более семантическим, динамичным маршрутам, как https://softwareengineering.stackexchange.com/questions/363517/how-and-why-did-modern-web-application-frameworks-evolve-to-decouple-url-routes. Очевидно, вам не нужен /var/www/questions/363517/how-and-why-did-modern-web-application-frameworks-evolve-to-decouple-url-routes.phpфайл. Вы использовали для создания правил переписывания URL-адресов в конфигурации веб-сервера для создания таких маршрутов. Теперь это просто изменение кода, что намного проще в эксплуатации.


Вам не нужно переписывать URL для этого примера.
Yay295

1
Он обрабатывается кодом, который распознает первую часть пути, и использует число / 363517 / для поиска вопроса в базе данных. Ничего общего с самим веб-сервером, а с приложением ...
Уилл Кроуфорд

11

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

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

Это не только вопрос PHP. В качестве доказательства здесь приведен соответствующий раздел руководства по защите Apache .


1
Почему отрицательный голос?
JimmyJames

8

Я не могу отвечать за отрасль, но могу сказать вам, почему я перешел от файловой системы URL = в начале 2000-х годов к виртуальным «маршрутам».

При работе с PHP старой школы, если у вас есть 1000 страниц PHP, у вас будет 1000 файлов PHP, представляющих эти страницы. Каждый дублирующий верхний / нижний колонтитул включает и, возможно, некоторую другую логику. Теперь скажем, вам нужно это изменить. Какой беспорядок у вас сейчас на руках! Вам либо нужно изменить все 1000 файлов, либо вы получите кучу очень уродливого кода в верхних и нижних колонтитулах для обработки всех случаев. При использовании виртуальных маршрутов логика верхнего / нижнего колонтитула, логика подключения к базе данных и другая инициализация включаются один раз , точка Намного лучше работать с

Другая причина состоит в том, чтобы избежать двусмысленности. По мере роста приложений верхние и нижние колонтитулы становятся все более сложными. У них обычно были свои собственные вложенные элементы, которые зависели от разных вещей. В файле PHP для «страницы» часто возникала неоднозначность относительно того, является ли переменная isset () или нет. Используя виртуальные маршруты и приложение, в котором все необходимое загружается при каждой загрузке страницы, у вас больше нет этой проблемы.

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


Можете ли вы сказать больше, почему вы получили очень уродливый код? Я вижу необходимость изменения 1000 файлов (при условии, что это обновление заголовков / колонтитулов), но что вы подразумеваете под беспорядочным уродливым кодом?
Деннис

Смотрите параграф, который я только что добавил. Но в основном, когда вы расширяете код заголовка / нижнего колонтитула / кода инициализации для обработки большего количества случаев, особенно если вы условно включаете другие файлы (это было плохой привычкой, но многие программисты PHP это делали), вы в конечном итоге получаете очень трудный для понимания код ,
GrandmasterB

5

Я не буду вдаваться в подробности того, почему это разделение выгодно. Основным аргументом является то, что он отделяет семантику (к чему вы фактически пытаетесь получить доступ) от базовой реализации.

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

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

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


1

RFC уже создали концепции с нуля, с URI (которые не привязывали семантику к локальной части), и URL-адреса в качестве особого случая, которые вводили семантику, похожую на путь, чтобы документы HTML могли использовать ссылки относительно документа базовый URL.

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

Если у вас есть веб-приложение с постоянными данными, структура затрат меняется: у вас всегда есть накладные расходы на запуск приложения, а интеграция с ним декодирования URL-адресов упрощает реализацию многих функций, снижая затраты.


1

Вначале URL-адреса сопоставлялись непосредственно с путями к файлам на сервере, потому что это легко, и в любом случае нет другого способа сделать это, не так ли? Если я попрошу /path/to/index.php, я начну /path/to/index.phpс корневого каталога веб-сайта (обычно не самого сервера, веб-сайт должен находиться в каталоге или подкаталоге ниже).

Затем, через пару лет, мы начали узнавать о переписывании, которое обслуживает другой ресурс, чем тот, о котором, по-видимому, просили. /request/path/to/index.phpможет на самом деле служить /response/path/to/index.php.

Другой трюк скрывается index.php. Если я попрошу, /index.php?foo=bar&baz=quxсервер может ответить, спрятавшись index.phpтак:, /?foo=bar&baz=quxвсе время фактически обслуживая в index.phpлюбом случае.

Следующим важным шагом является то, что мы научились перенаправлять все URL-адреса /index.php. Так что теперь /path/to/some/pageмолча перенаправлен на /index.php?path/to/some/page. Это немного сложно, потому что обычно каждый слеш представляет новый подкаталог, но в этом случае веб-сервер настроен на отправку пути в качестве параметра, а не на поиск в нем.

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

Он эффективно превращает ваш сайт с сотнями или тысячами приложений (если вы считаете каждый файл своим приложением) в одно, гораздо более сложное, но гораздо более согласованное приложение.

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

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


-1

Как давний вебдев, я думаю, что появление контроля истории без навигации ( history.pushState()) во времена HTML5 сделало это практичным. Перед этим вам пришлось перезагрузить страницу, чтобы обновить строку URL, если только вы не обновили фрагмент ( /path#fragment). Этот фрагмент был невидим для сервера (он не маршрутизируется), поэтому единственный способ обновить или добавить в закладки динамическую страницу - это JavaScript.

Это имеет серьезные последствия для SEO и привело к тому, что Google разработал редко используемую схему «hashbang», которая требовала сопоставления динамических хешей на стороне сервера с физическими URL-адресами. Это было громоздко и не универсально среди роботов, ведущих (ложную) аксиому: «пауки не могут сканировать контент ajax». Но преимущества контента ajax ощутимы: попробуйте, например, использовать карты Google без JS.

Решением был способ обновить строку URL значением, которое можно зеркально отразить на сервере (разрешив закладки и обновление без JS), БЕЗ перезагрузки страницы. Как только эта возможность стала доступна, разработчики могли «перемещаться» по сайту, просто обновляя «основной раздел контента», панель URL и хлебные крошки. Это означало, что весь JS + CSS не нуждался в повторном извлечении + анализе, что позволило НАМНОГО быстрее передавать страницу на страницу.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.