Jak i dlaczego ewoluowały współczesne ramy aplikacji internetowych, aby oddzielić trasy adresów URL od systemu plików?

67

W porównaniu do około 10 lat temu zauważyłem zmianę na frameworki wykorzystujące styl routingu, który oddziela ścieżkę URL od systemu plików. Zwykle odbywa się to za pomocą wzorca kontrolera frontowego.

Mianowicie, kiedy wcześniej ścieżka URL była mapowana bezpośrednio do systemu plików, a zatem odzwierciedlała dokładne pliki i foldery na dysku, obecnie rzeczywiste ścieżki URL są programowane tak, aby były kierowane do określonych klas poprzez konfigurację i jako takie nie odzwierciedlają już pliku folder systemowy i struktura plików.

Pytanie

Jak i dlaczego stało się to powszechne? W jaki sposób i dlaczego zdecydowano, że „lepiej” do tego stopnia, że ​​po raz pierwszy powszechnie stosowane podejście bezpośrednie do pliku zostało skutecznie porzucone?

Inne odpowiedzi

Podobna odpowiedź dotyczy nieco trasy i niektórych zalet i wad: w przypadku frameworków PHP, dlaczego używana jest koncepcja „trasy”?

Ale nie dotyczy to historycznych aspektów zmian, ani tego, jak i dlaczego ta zmiana stopniowo następowała, w przypadku, gdy wszelkie nowe projekty w dzisiejszych czasach w zasadzie używają tego nowego stylu stylu routingu, a bezpośrednie przesyłanie do pliku jest przestarzałe lub zaniechane.

Ponadto większość wspomnianych zalet i wad nie wydaje się na tyle znacząca, aby uzasadniać taką globalną zmianę. Jedyną korzyścią, jaką widzę, powodując tę ​​zmianę, może być ukrywanie systemu plików / folderów przed użytkownikiem końcowym, a także brak ?param=value&param2=value, co sprawia, że ​​adresy URL wyglądają na odrobinę czystsze. Ale czy to był jedyny powód zmiany? A jeśli tak, to dlaczego były te powody to?

Przykłady:

Najbardziej znam frameworki PHP i wiele popularnych współczesnych frameworków korzysta z tego podejścia odsprzęgania routingu. Aby działało, skonfiguruj przepisywanie adresów URL w Apache lub podobnym serwerze WWW, w którym funkcje aplikacji internetowych zwykle nie są już uruchamiane przez ścieżkę adresu URL bezpośrednio do pliku.

Zend Expressive

https://docs.zendframework.com/zend-expressive/features/router/aura/
https://docs.zendframework.com/zend-expressive/features/router/fast-route/
https: //docs.zendframework. com / zend-expressive / features / router / 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

Dennis
źródło
14
czy naprawdę była taka zmiana? a może większość języków / ram nigdy nie używała bezpośredniego mapowania systemu plików? może to po prostu PHP dogania resztę rozsądku? twoje obserwacje są moim zdaniem błędne, więc nie ma dobrej odpowiedzi. również wspomniane „shift” występowało tylko w świecie PHP. ale moim zdaniem to zbyt szerokie pytanie ...
rsm
2
@rsm Miałem podobną pierwszą reakcję, ale po dalszych przemyśleniach jest to naprawdę coś, co zostało zrobione w wielu językach i platformach, co prowadzi do tego, że jest to naprawdę częste źródło luk w zabezpieczeniach.
JimmyJames
6
@rsm, może to być bardziej widoczne we frameworku PHP, ale żeby użyć innego sposobu - w pewnym momencie, zanim jakikolwiek framework naprawdę się przyłapie, czy to ASP, .NET, PHP, JSP itp., sieć najczęściej używana jest bezpośrednio - podejście do pliku. Dlaczego wszystkie te ramy opracowano tak, aby stosować podejście niezwiązane z wielkością produkcji? Technicznie podejście bezpośrednie do pliku jest nadal wykonalne i jestem pewien, że nowoczesne ramy mogą z niego korzystać. Czy mogą? Może nie mogą, a może istnieją dobre powody, dlaczego tego nie robią? Jakie byłyby te powody ...? Nie oferują nawet sposobu ani wtyczki do wykonania tego, po prostu całkowicie wyeliminowali bezpośrednie przesyłanie plików.
Dennis
2
Czy to nie (częściowo) dotyczy także przeglądania adresu URL ( lokalizatora , jak znaleźć zasób) jako identyfikatora URI (i identyfikatora )?
Hagen von Eitzen
2
Powiązane czytanie z historii starożytnej: Cool URIs Don't Change - Tim Berners-Lee, 1998
Michael Hampton

Odpowiedzi:

72

W najbardziej podstawowej formie strona internetowa obsługuje pliki statyczne. Mapowanie ścieżki adresu URL do ścieżki pliku jest najbardziej oczywistym wyborem; w zasadzie jest to witryna FTP tylko do odczytu.

Następnie ludzie chcieli zmienić zawartość strony za pomocą skryptów. Najprostszym sposobem jest osadzenie języka skryptowego na stronie i uruchomienie go przez tłumacza. Ponownie, biorąc pod uwagę już istniejącą ścieżkę -> routing ścieżek plików, było to dość proste.

Ale tak naprawdę teraz uruchamiasz ten plik jako argument dla interpretera. Musisz określić, kiedy żądanie dotyczy pliku statycznego, a kiedy dotyczy czegoś, co musisz zinterpretować.

Gdy zaczniesz używać bardziej zaawansowanych języków kompilowanych, jesteś jeszcze bardziej rozwiedziony z lokalizacją pliku.

Ponadto serwer sieciowy już buforuje pliki statyczne i wykonuje różnego rodzaju optymalizacje, co oznacza, że ​​uderzenie w system plików jest raczej wyjątkiem niż regułą. W tym momencie stara ścieżka do systemu plików linków jest bardziej przeszkodą niż pomocą.

Ale myślę, że prawdziwa zmiana morza nastąpiła, gdy użytkownicy chcieli pozbyć się rozszerzenia pliku ze ścieżki. Pobieranie myPage.asp lub myPage.php było czymś, co myliło „normalnych” ludzi i zakłócało SEO.

Ponieważ użytkownik widzi ścieżkę, stała się ona częścią interfejsu użytkownika sieci i jako taka musi być całkowicie wolna od jakichkolwiek ograniczeń technicznych. Zgubiliśmy „www” i praktycznie wszystko jest „.com”. Wiele adresów URL wskazuje tę samą stronę.

Jeśli zarabiam więcej z mydomain.com/sale vs www.mydomain.co.uk/products/sale.aspx, nie chcę, aby jakiekolwiek ograniczenia techniczne stanęły mi na drodze.

Ewan
źródło
7
Zawsze myślałem, że chęć ukrywania rozszerzeń plików była po części „zabezpieczeniem przez zaciemnienie” - co utrudnia stwierdzenie, jaką technologię zastosowano w witrynie, aby ułatwić celowanie w określone załączone / znane exploity niektórych serwerów i technicy w tym czasie
Caius Jard
20
@CaiusJard to część tego, ale inna część to agnostycyzm technologiczny - po zastąpieniu file.html na naszych ścieżkach nie chcieliśmy utknąć z innym przełącznikiem później (na przykład file.phtml do file.php, a nawet do plik.asp). Ale skoro rozdzielamy adres URL i ścieżkę systemu plików (wykorzystując routing lub cokolwiek innego), aby uzyskać dostęp do zasobów zbudowanych z rekordów bazy danych i / lub innych źródeł, dlaczego w ogóle ma rozszerzenie adresu URL?
HorusKol
39
@HorusKol Technologia agnostycyzm to nie tylko konieczność zmiany wszystkich plików na twojej ścieżce. Możliwość zmiany technologii zaplecza bez przerywania pracy i zakładek klienta oraz bez niszczenia SEO może być ogromna .
Shane
7
Co ciekawe, nigdy nie zaleca się posiadania rozszerzeń nazw plików w identyfikatorze URI, więc powinny były zostać wcześniej odłączone od systemu plików. Najwcześniejsze wzmianki na ten temat pochodzą z 1998 r. , Która faktycznie wyprzedza większość zmian opisanych w tej odpowiedzi.
Konrad Rudolph
8
W dawnych czasach mojadomena.com/sprzedaż nadal działała; przekierował do / sale / i ładował się dobrze (twoja strona to mydomain.com/sale/index.aspx, ale nikt nigdy nie widział index.aspx).
Joshua
39

Możesz zajrzeć na białym papierze Roy Fielding na reprezentacyjne State Transfer (REST) jak do kiedy i dlaczego . Pierwszą strukturą, o której wiedziałem, że rozróżniałem zasób od pliku, była Ruby on Rails - wprowadzająca koncepcję URL do routingu kodu.

Główne koncepcje REST, które były transformacyjne, to:

  • Adres URL reprezentuje zasób
  • Ten zasób może mieć wiele reprezentacji
  • Adres URL nie powinien ulec uszkodzeniu, jeśli aplikacja zostanie zrestrukturyzowana
  • Aplikacje powinny uwzględniać bezpaństwowość sieci

Główną wadą posiadania plików obsługiwanych bezpośrednio przez adres URL jest to, że występują następujące problemy:

  • Łącza do zasobów są stale przerywane w trakcie reorganizacji stron internetowych
  • Zasoby i reprezentacja są ze sobą powiązane

Myślę, że ważne jest również zapewnienie odpowiedniej równowagi:

  • Nie wszystkie zasoby mają takie same znaczenie. Dlatego nadal masz bezpośrednio obsługiwane zasoby oparte na stylu (CSS, JavaScript / EcmaScript, obrazy)
  • Istnieją udoskonalenia REST, takie jak HATEOAS, które lepiej obsługują aplikacje jednostronicowe.
Berin Loritsch
źródło
kiedy mówisz o reprezentacji, masz na myśli takie rzeczy jak JSON / HTML / TEXT / etc? Jestem niejasno obeznany z REST, ale wyobrażam sobie, że nawet z REST musisz mieć jakiś wyzwalacz, aby zmienić reprezentację odpowiedzi ...
Dennis
@Dennis, tak. HTTP ma wiele nagłówków, których można użyć do wskazania pożądanej formy ( developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation ), a REST polegał na wykorzystaniu mocnych stron HTTP. Jednak często zdarza się, że aplikacja ma zastrzeżony sposób negocjowania pożądanej zawartości.
Berin Loritsch,
5
CGI (1993), Servlety (1997) i JSP (1999) często oddzielały adresy URL od systemu plików i wcześniejsze REST (2000). Jednak ta odpowiedź jest w zasadzie poprawna w identyfikacji przyczyn popularności wzorca projektowego: REST, Java Struts i Ruby on Rails mają ogromny wpływ na popularność oddzielania zasobów od reprezentacji w XXI wieku.
dcorking
1
Według artykułu Fieldinga „Pierwsza edycja REST została opracowana między październikiem 1994 r. A sierpniem 1995 r.”
Connor
1
@corking, CGI w tym czasie nie oddzielał adresów URL od plików, po prostu uruchomił plik zamiast 9 razy na 10. Serwlety mogą być najbliższym dopasowaniem, ale jeśli mówisz o koncepcji tras i posiadaniu zaprojektowanej przestrzeni URL , który był dostarczany z Railsami i podobnymi strukturami.
Berin Loritsch,
20

Nie sądzę, że jest to artefakt współczesnych ram aplikacji internetowych, w większości jest to artefakt dynamicznej obsługi stron.

W dawnych czasach istniały głównie statyczne strony internetowe, na których oprogramowanie obsługiwało poszczególne pliki z systemu plików według ich ścieżki. Zrobili to głównie dlatego, że mapowanie ścieżek URL 1: 1 do ścieżek systemu plików (z jednym katalogiem wyznaczonym jako katalog główny) było oczywistym wyborem, chociaż przepisywanie adresów URL (np. W celu przekierowań po przeniesieniu plików) było również powszechne.

Potem przyszedł czas na dostarczanie dynamicznych treści. Skrypty CGI (i wszystko, co z nich wyewoluowało) tworzyły strony w locie, wspierane przez jakąś bazę danych. Parametry GET w adresie URL stały się powszechne, na przykład en.wikipedia.org/w/index.php?title=Path_(computing) .

Jednak jest bardziej przyjazny dla użytkownika , aby mieć czytelny adres URL, na które składają się tylko z segmentów ścieżki. Tak więc aplikacje dynamiczne zamapowały proste ścieżki (na przykład en.wikipedia.org/wiki/Path_(computing) ) na parametry, a te mapowania są znane jako „trasy”.

Być może to podejście wydaje się bardziej aktualne, ponieważ zyskało popularność, gdy znaczenie użyteczności zostało szerzej rozpoznane, a także stało się częścią SEO. Jest to prawdopodobnie powód, dla którego został on wbudowany bezpośrednio w duże frameworki internetowe.

Bergi
źródło
12

Jednym z powodów jest to, że ładowanie pliku z dysku przy każdym żądaniu jest powolne, więc serwery internetowe zaczęły tworzyć sposoby buforowania plików w pamięci, a jeśli chcesz mimo to spróbować zachować je w pamięci, dlaczego ma to znaczenie, gdzie było dysk?

Jednym z powodów jest to, że wiele frameworków internetowych jest napisanych w skompilowanych językach, więc nie masz nawet struktury plików na dysku, tylko jarplik lub cokolwiek innego. Języki interpretowane zapożyczały pomysły, które lubiły od skompilowanych.

Jednym z powodów jest pragnienie bardziej semantycznych, dynamicznych tras https://softwareengineering.stackexchange.com/questions/363517/how-and-why-did-modern-web-application-frameworks-evolve-to-decouple-url-routes. Oczywiście nie chcesz /var/www/questions/363517/how-and-why-did-modern-web-application-frameworks-evolve-to-decouple-url-routes.phppliku. Kiedyś tworzyłeś reguły przepisywania adresów URL w konfiguracji serwera WWW, aby tworzyć takie trasy. Teraz jest to tylko zmiana kodu, która jest znacznie prostsza operacyjnie.

Karl Bielefeldt
źródło
W tym przykładzie nie potrzebujesz przepisywania adresów URL.
Yay295,
1
Jest obsługiwany przez kod, który rozpoznaje pierwszą część ścieżki i używa numeru / 363517 /, aby wyszukać pytanie w bazie danych. Nie ma nic wspólnego z samym serwerem WWW, ale aplikacja ...
Will Crawford,
11

Jednym z głównych powodów jest prawdopodobne, że takie podejście mapowania identyfikatorów URI do ścieżek plików doprowadziło do dużej liczby przypadkowych uwolnień danych za pośrednictwem funkcji File Path Traversal

Kiedy mapujesz ścieżkę do systemu plików, oznacza to, że następnie musisz sprawdzić, czy każda ścieżka, którą otrzymujesz jako żądanie, jest mapowana na pliki, które powinny być dostępne dla klientów. Prostym podejściem do zagwarantowania, że ​​tak się nie dzieje, jest wyeliminowanie przezroczystego mapowania i robienie tego bardziej wyraźnie.

To nie dotyczy tylko PHP. Dowodem na to jest odpowiednia część przewodnika o hartowaniu Apache .

JimmyJames
źródło
1
Dlaczego głosowanie negatywne?
JimmyJames
8

Nie mogę odpowiedzieć na pytania branży, ale mogę powiedzieć, dlaczego na początku 2000 roku zrezygnowałem z systemu plików URL = w kierunku wirtualnych „tras”.

Pracując z „oldschoolowym” PHP, jeśli masz 1000 stron PHP, miałbyś 1000 plików PHP reprezentujących te strony. Każdy powielający się nagłówek / stopka zawiera i ewentualnie inną logikę. Powiedzmy teraz, że musisz to zmienić. Jaki bałagan masz teraz na rękach! Musisz zmienić wszystkie 1000 plików lub skończyć z mieszanką bardzo brzydkiego kodu w nagłówku / stopce, aby obsłużyć wszystkie przypadki. Przy użyciu tras wirtualnych logika nagłówka / stopki, logika połączenia z bazą danych i inna inicjalizacja są uwzględniane raz , kropka. O wiele lepiej pracować.

Innym powodem jest unikanie dwuznaczności. Wraz z rozwojem aplikacji, dołączane nagłówki / stopki stają się coraz bardziej złożone. Zazwyczaj zagnieżdżali własne, które zależały od różnych rzeczy. W pliku PHP „strony” często napotykasz dwuznaczność, czy zmienna isset (), czy nie. Korzystając z wirtualnych tras i aplikacji, w której wszystko, czego potrzebujesz, ładuje się przy każdym ładowaniu strony, nie masz już tego problemu.

Wreszcie (choć istnieją inne powody, ale to ostatnia lista, którą wymienię), wiele z tych 1000 stron reprezentuje kod, który zostałby zduplikowany. Tak więc po przekształceniu w odpowiedni zestaw klas i szablonów kod jest znacznie uproszczony i możesz zrobić wszystko, co chcesz, bez posiadania tych 1000 plików.

Grandmaster B.
źródło
czy możesz powiedzieć więcej, dlaczego skończyłbyś z bardzo brzydkim kodem? Widzę potrzebę zmiany 1000 plików (zakładając, że to aktualizacja nagłówka / stopki obejmuje), ale co masz na myśli mówiąc, że jest to brzydki kod?
Dennis
Zobacz akapit, który właśnie dodałem. Ale w zasadzie, gdy rozszerzasz kod nagłówka / stopki / inicjalizacji, aby obsłużyć większą liczbę przypadków, szczególnie jeśli warunkowo dołączasz inne pliki (to był zły nawyk, ale zrobiło to wielu programistów PHP), kończysz się bardzo trudnym do naśladowania kodem .
GrandmasterB
5

Nie będę szczegółowo omawiał, dlaczego ten podział jest korzystny. Głównym argumentem jest to, że oddziela semantykę (do czego tak naprawdę próbujesz uzyskać dostęp) od podstawowej implementacji.

Biorąc pod uwagę, że korzyści przewyższają koszty jako takie - co byłoby osobnym pytaniem - nietrudno zrozumieć, dlaczego zostało to stopniowo przyjęte. Nie sądzę, żeby było to jedno wydarzenie, chociaż z pewnością byłbym otwarty na naukę w tym zakresie.

Przynajmniej z mojego doświadczenia, początkowo było to często wykonywane przez konfigurację Apache - i prawdopodobnie również inne serwery WWW to obsługiwały. Jednak koncepcyjnie nie ma żadnego dobrego powodu, dla którego miałby to być serwer. W końcu trasy są specyficzne dla rzeczywistej aplikacji, więc warto je tam zdefiniować.

Zmieniło się to globalnie, ale jak zauważyłeś, stopniowo. Przyczyna tego jest prawie na pewno bardzo prosta: dobre pomysły rozprzestrzeniają się w czasie. Dlatego też nie jest zaskoczeniem, że zmiana nastąpiła na całym świecie. To nie tak, że wszyscy się spotkali i postanowili to zrobić w ten sposób. Zamiast tego każdy projekt dostosowywał to podejście, gdy uważał, że będzie to korzystne (a projekty, które go nie wspierały, ostatecznie zniknęły).

podwójnie
źródło
1

RFC już zbudowały koncepcje od podstaw, z identyfikatorami URI (które nie dołączały żadnej semantyki do części lokalnej) i adresami URL jako szczególny przypadek, który wprowadził semantykę podobną do ścieżki, aby umożliwić dokumentom HTML korzystanie z łączy w stosunku do dokumentu podstawowy adres URL.

Oczywistą implementacją jest odwzorowanie lokalnej części adresu URL bezpośrednio na system plików, więc zrobiły to proste konfiguracje - bez względu na to, czy używasz dedykowanej relacyjnej bazy danych do wyszukiwania dokumentu, czy korzystasz z wysoce zoptymalizowanego, niskiego obciążenia klucza -wartość sklepu, który już masz, nie ma znaczenia na zewnątrz, ale z pewnością wpływa na strukturę kosztów obsługi dokumentów.

Jeśli masz aplikację internetową z trwałymi danymi, struktura kosztów zmienia się: zawsze masz narzut związany z uruchomieniem aplikacji, a zintegrowanie z nią dekodowania adresów URL ułatwia wdrożenie wielu funkcji, co zmniejsza koszty.

Simon Richter
źródło
1

Na początku adresy URL są mapowane bezpośrednio na ścieżki plików na serwerze, ponieważ jest to łatwe, a poza tym nie ma innego sposobu, prawda? Jeśli poproszę /path/to/index.php, zacznę /path/to/index.phpod katalogu głównego witryny (zwykle nie z samego serwera, strona internetowa powinna znajdować się w katalogu lub podkatalogu dalej).

Następnie po kilku latach zaczęliśmy uczyć się o przepisywaniu, które służy innym zasobom niż ten, o który najwyraźniej został poproszony. /request/path/to/index.phpmoże faktycznie służyć /response/path/to/index.php.

Kolejną sztuczką jest ukrywanie się index.php. Jeśli poproszę /index.php?foo=bar&baz=quxserwer może odpowiedzieć, ukrywając się w ten index.phpsposób /?foo=bar&baz=qux:, index.phpmimo wszystko faktycznie służy .

Kolejnym ważnym krokiem jest nauczenie się przekierowywania wszystkich adresów URL /index.php. Teraz /path/to/some/pagejest po cichu przekierowywany na /index.php?path/to/some/page. Jest to nieco trudne, ponieważ zwykle każdy ukośnik reprezentuje nowy podkatalog, ale w tym przypadku serwer WWW jest skonfigurowany do wysyłania ścieżki jako parametru, zamiast w nią zaglądać.

Teraz, kiedy to mamy, potrzebujemy zupełnie innego sposobu myślenia o tym, jak zorganizowana jest strona internetowa. Wcześniej była to luźna kolekcja różnych stron. Teraz wszystko jest kierowane przez jedną stronę wejściową. To znacznie komplikuje witrynę, ale zapewnia możliwości, które wcześniej nie były dostępne, takie jak uwierzytelnianie użytkowników w całej witrynie, jednolite stosowanie nagłówków, stopek i stylów itp.

Skutecznie zamienia sto lub tysiąc stron internetowych aplikacji (jeśli uważasz każdy plik za własną aplikację) w jedną, znacznie bardziej skomplikowaną, ale o wiele bardziej spójną aplikację.

To ogromny skok, ponieważ nie można już stwierdzić, jaki kod zostanie wykonany, po prostu patrząc na adres URL. Teraz musisz dokładnie zrozumieć, w jaki sposób konkretna struktura tłumaczy ścieżki URL na ścieżki kodu i chociaż istnieją podobieństwa między strukturami, większość jest na tyle inna, że ​​potrzebujesz pewnej znajomości, aby móc pracować z kodem.

Krótko mówiąc, była to stopniowa ewolucja odkryć, a nie nagły skok, a każdy programista musiał przejść tę samą podróż odkrywania. Krzywa uczenia się jest dość stroma, chyba że naprawdę szybko zrozumiesz abstrakcyjne pojęcia.

CJ Dennis
źródło
-1

Jako webdev dawna, myślę, że z nadejściem nawigacji mniej kontroli historii ( history.pushState()) wokół momencie HTML5 wykonane to praktyczne. Wcześniej trzeba było ponownie załadować stronę, aby zaktualizować pasek adresu URL, chyba że zaktualizowano tylko fragment ( /path#fragment). Ten fragment był niewidoczny dla serwera (nie jest routowany), więc jedynym sposobem odświeżenia lub dodania do zakładek strony dynamicznej był JavaScript.

Ma to poważne konsekwencje dla SEO i doprowadziło google do opracowania rzadko używanego schematu „hashbang”, który wymagał mapowania dynamicznych skrótów po stronie serwera na fizyczne adresy URL. Było to nieporęczne i nie uniwersalne wśród robotów, prowadząc (fałszywy) aksjomat: „pająki nie mogą czołgać się do treści ajax”. Ale korzyści płynące z zawartości ajax są namacalne: spróbuj na przykład użyć Google Maps bez JS.

Rozwiązaniem był sposób aktualizacji paska adresu URL o wartość, która może być dublowana na serwerze (umożliwiając odświeżanie zakładek i JS), BEZ ponownego ładowania strony. Po udostępnieniu tej możliwości programiści mogli „nawigować” po witrynie, po prostu aktualizując „główną sekcję treści”, pasek adresu URL i bułkę tartą. Oznaczało to, że wszystkie pliki JS + CSS nie wymagały odświeżania + analizowania, umożliwiając DUŻO szybsze przesyłanie strony do strony.

dandavis
źródło