Jeśli chcę utworzyć adres URL przy użyciu zmiennej, mam dwie możliwości zakodowania ciągu. urlencode()
a rawurlencode()
.
Jakie dokładnie są różnice i które są preferowane?
php
urlencode
url-encoding
Gary Willoughby
źródło
źródło
rawurlencode
. Rzadko spotykasz system, który dusi się, gdy podane są spacje zakodowane jako%20
, natomiast systemy, które dławią się spacjami zakodowanymi jako,+
są bardziej powszechne.Odpowiedzi:
Będzie to zależeć od twojego celu. Jeśli współdziałanie z innymi systemami jest ważne, wydaje się, że właściwym rozwiązaniem jest kod surowy. Jedynym wyjątkiem są starsze systemy, które oczekują, że ciąg zapytania będzie zgodny ze stylem kodowania spacji kodowanych jako + zamiast% 20 (w takim przypadku potrzebujesz kodu urlencode).
rawurlencode jest zgodny z RFC 1738 przed PHP 5.3.0 i RFC 3986 później (patrz http://us2.php.net/manual/en/function.rawurlencode.php )
Uwaga na temat RFC 3986 vs 1738. rawurlencode przed php 5.3 kodował znak tyldy (
~
) zgodnie z RFC 1738. Jednak w PHP 5.3 Rawurlencode jest zgodny z RFC 3986, który nie wymaga kodowania znaków tyldy.urlencode koduje spacje jako znaki plus (nie tak
%20
jak w rawurlencode) (patrz http://us2.php.net/manual/en/function.urlencode.php )Odpowiada to definicji aplikacji / x-www-form-urlencoded w RFC 1866 .
Dodatkowe czytanie:
Możesz również zobaczyć dyskusję na stronie http://bytes.com/groups/php/5624-urlencode-vs-rawurlencode .
Ponadto, RFC 2396 jest wart obejrzenia. RFC 2396 definiuje poprawną składnię URI. Główną częścią, którą jesteśmy zainteresowani, jest komponent zapytania 3.4:
Jak widać,
+
jest to znak zastrzeżony w ciągu zapytania i dlatego musiałby zostać zakodowany zgodnie z RFC 3986 (jak w rawurlencode).źródło
Dowód znajduje się w kodzie źródłowym PHP.
Przeprowadzę cię przez szybki proces samodzielnego odkrywania tego rodzaju rzeczy w przyszłości, kiedy tylko chcesz. Bądźcie ze mną, będzie dużo kodu źródłowego C, który można przejrzeć (wyjaśniam). Jeśli chcesz odświeżyć trochę C, dobrym miejscem do rozpoczęcia jest nasza wiki SO .
Pobierz źródło (lub użyj http://lxr.php.net/, aby przeglądać je online), grepuj wszystkie pliki dla nazwy funkcji, znajdziesz coś takiego:
PHP 5.3.6 (najnowsza w chwili pisania) opisuje dwie funkcje w ich natywnego kodu C w pliku url.c .
RawUrlEncode ()
UrlEncode ()
Okej, więc co tu jest innego?
Oba w zasadzie wywołują odpowiednio dwie różne funkcje wewnętrzne: php_raw_url_encode i php_url_encode
Poszukaj tych funkcji!
Spójrzmy na php_raw_url_encode
I oczywiście php_url_encode:
Krótka wiedza zanim przejdę dalej, EBCDIC to kolejny zestaw znaków , podobny do ASCII, ale całkowity konkurent. PHP próbuje sobie z tym poradzić. Ale w zasadzie oznacza to, że bajt EBCDIC 0x4c nie jest bajtem
L
w ASCII, to w rzeczywistości jest<
. Jestem pewien, że widzisz tutaj zamieszanie.Obie te funkcje zarządzają EBCDIC, jeśli serwer go zdefiniował.
Obaj używają również tablicy znaków (typu łańcuchowego)
hexchars
, aby uzyskać pewne wartości, tablica jest opisana jako taka:Poza tym funkcje są naprawdę różne i wyjaśnię je w ASCII i EBCDIC.
Różnice w ASCII:
URLENCODE:
+
znak do ciągu wyjściowego.isalnum(c)
), a także nie jest i_
,-
lub.
znak, wówczas wyprowadzamy%
znak do pozycji tablicy 0, sprawdzamy tablicę dohexchars
tablicy w celu wyszukaniaos_toascii
tablicy ( tablica z Apache, która tłumaczy char na kod szesnastkowy) dla kluczac
(obecnego znaku), następnie bitowo przesuwamy w prawo o 4, przypisujemy tę wartość do znaku 1, a do pozycji 2 przypisujemy to samo wyszukiwanie, z wyjątkiem tego, że wykonujemy preformę logiczne i sprawdzić, czy wartość wynosi 15 (0xF), i zwróć 1 w tym przypadku, lub 0 w przeciwnym razie. Na końcu skończysz z czymś zakodowanym._-.
znaków, wyświetla dokładnie to, czym jest.KOD RAWURLEN:
Uwaga: Wielu programistów prawdopodobnie nigdy nie widziało powtarzania pętli for w ten sposób, jest to nieco hackerskie, a nie standardowa konwencja stosowana w większości pętli for, zwracaj uwagę, przypisuje
x
iy
sprawdza wyjście polen
osiągnięciu 0 i zwiększa zarówno, jakx
iy
. Wiem, że nie jest to, czego można się spodziewać, ale to poprawny kod.str
._-.
znaków, a jeśli nie jest, wykonujemy prawie takie samo przypisanie, jak w przypadku URLENCODE, w którym wykonuje on wyszukiwanie, jednak zwiększamy go inaczej, używający++
zamiastto[1]
tego, ponieważ ciągi są budowane na różne sposoby, ale i tak osiągają ten sam cel na końcu.\0
bajt.Różnice:
\0
bajtu do ciągu, RawUrlEncode robi (może to być kwestia sporna)Zasadniczo iterują inaczej, jeden przypisuje znak + w przypadku ASCII 20.
Różnice w EBCDIC:
URLENCODE:
0
, z wyjątkiem bycia.
lub-
, lub mniejsza niżA
, ale większa niż znak9
, lub większej niżZ
mniej niż aa
, ale nie_
. LUB większy niżz
(tak, EBCDIC jest trochę zepsuty do pracy). Jeśli pasuje do któregokolwiek z nich, wykonaj podobne wyszukiwanie jak w wersji ASCII (po prostu nie wymaga wyszukiwania w os_toascii).KOD RAWURLEN:
z
, wyklucza~
z kodowania URL.\0
bajt do ciągu przed zwróceniem.Wielkie podsumowanie
~
że UrlEncode nie ( jest to zgłaszany problem ). Warto zauważyć, że ASCII i EBCDIC 0x20 są spacjami.+
, RawUrlEncode tworzy spację%20
poprzez wyszukiwanie tablic.Oświadczenie: Nie dotykałem C od lat i nie patrzyłem na EBCDIC od naprawdę bardzo dawna. Jeśli gdzieś się mylę, daj mi znać.
Sugerowane wdrożenia
Opierając się na tym wszystkim, rawurlencode jest drogą do przejścia przez większość czasu. Jak widać w odpowiedzi Jonathana Finglanda, trzymaj się jej w większości przypadków. Zajmuje się nowoczesnym schematem komponentów URI, w którym jako urlencode robi się to w oldschoolowy sposób, gdzie + oznaczało „przestrzeń”.
Jeśli próbujesz przekonwertować stary format na nowy, upewnij się, że Twój kod nie wygłupia się i nie zamienia czegoś, co jest zdekodowanym znakiem + w spację przez przypadkowe podwójne kodowanie lub podobne scenariusze „ups” wokół tego problem spacja / 20% / +.
Jeśli pracujesz na starszym systemie ze starszym oprogramowaniem, które nie preferuje nowego formatu, trzymaj się kodu urlencode, jednak uważam, że% 20 faktycznie będzie kompatybilny wstecz, ponieważ w starym standardowym% 20 działało, po prostu preferowane. Daj mu szansę, jeśli masz ochotę się bawić, daj nam znać, jak Ci się udało.
Zasadniczo powinieneś trzymać się surowego, chyba że twój system EBCDIC naprawdę cię nienawidzi. Większość programistów nigdy nie natknie się na EBCDIC na żadnym systemie wyprodukowanym po 2000 roku, może nawet 1990 roku (to pcha, ale moim zdaniem nadal prawdopodobne).
źródło
daje
podczas
daje
Różnica polega na tym, że
asd%20asd
vsasd+asd
kod urlencode różni się od RFC 1738 kodowaniem spacji jak
+
zamiast%20
źródło
Jednym praktycznym powodem wyboru jednego spośród innych jest użycie wyniku w innym środowisku, na przykład JavaScript.
W PHP
urlencode('test 1')
zwraca,'test+1'
arawurlencode('test 1')
zwraca'test%201'
jako wynik.Ale jeśli trzeba „dekodowania” to w JavaScript używając decodeURI () funkcję wtedy
decodeURI("test+1")
dadzą Ci"test+1"
natomiastdecodeURI("test%201")
da wam"test 1"
jako wynik.Innymi słowy, spacja („”) zakodowana przez urlencode na plus („+”) w PHP nie zostanie poprawnie zdekodowana przez decodeURI w JavaScript.
W takich przypadkach należy użyć funkcji PHP typu rawurlencode .
źródło
json_encode
iJSON.parse
do tego celu.Uważam, że spacje muszą być zakodowane jako:
%20
gdy jest używany w składniku ścieżki URL+
w przypadku użycia w elemencie ciągu zapytania lub danych formularza URL (patrz 17.13.4 Typy treści formularza )Poniższy przykład pokazuje prawidłowe użycie
rawurlencode
iurlencode
:Wynik:
Co się stanie, jeśli kodujesz ścieżkę i przeszukujesz ciąg znaków w drugą stronę? Dla następującego przykładu:
latest+songs
zamiastlatest songs
q
będzie zawieraćlady gaga
źródło
q
będzie zawieraćlady gaga
” Co jeszcze zawierałby w innym przypadku?q
Wydaje się, że parametr zapytania ma tę samą wartość przekazywaną do$_GET
tablicy, niezależnie od użyciarawurlencode
luburlencode
w PHP 5.2+. Chociażurlencode
koduje wapplication/x-www-form-urlencoded
formacie domyślnym dla żądań GET, więc idę z twoim podejściem. +1+
i%20
są dekodowane jako przestrzeń stosowany w ciągów zapytań.Różnica polega na wartościach zwracanych, tj .:
urlencode () :
rawurlencode () :
Obie są bardzo podobne, ale ta ostatnia (rawurlencode) zastąpi spacje „%” i dwiema cyframi szesnastkowymi, co jest odpowiednie do kodowania haseł itp., Gdzie „+” nie jest np .:
źródło
1. Jakie dokładnie są różnice i
Jedyna różnica polega na sposobie traktowania spacji:
urlencode - w oparciu o starszą implementację konwertuje spacje na +
rawurlencode - na podstawie RFC 1738 tłumaczy spacje na% 20
Powodem tej różnicy jest to, że znak + jest zarezerwowany i ważny (niekodowany) w adresach URL.
2. który jest preferowany?
Szczerze mówiąc, mam prostą strategię, którą stosuję przy podejmowaniu tych decyzji, którymi podzielę się z wami w nadziei, że może to pomóc.
Myślę, że była to specyfikacja HTTP / 1.1 RFC 2616, która wymagała „ tolerancji aplikacji ”
W obliczu takich pytań najlepszą strategią jest zawsze konsumować jak najwięcej i produkować to, co jest zgodne ze standardami.
Tak więc radzę używać
rawurlencode
do tworzenia łańcuchów kodowanych RFC 1738 zgodnych ze standardami i stosowaćurldecode
kompatybilność wsteczną i przyjmować wszystko, co możesz napotkać.Teraz możesz mi uwierzyć na słowo, ale udowodnijmy, że będziemy ...
Wygląda na to, że PHP miał na myśli dokładnie to, chociaż nigdy nie spotkałem nikogo, kto odmówiłby jednego z dwóch formatów, nie mogę wymyślić lepszej strategii, która mogłaby zostać przyjęta jako strategia defacto, prawda?
nJoy!
źródło
źródło
Spacje zakodowane jako
%20
vs.+
Największym powodem, dla którego widziałem
rawurlencode()
w większości przypadków, jest to, żeurlencode
koduje spacje tekstowe jako+
(znaki plus), gdzierawurlencode
koduje je jako powszechnie postrzegane%20
:W szczególności widziałem niektóre punkty końcowe interfejsu API, które akceptują zakodowane zapytania tekstowe, które spodziewają się zobaczyć
%20
spacji, w wyniku czego nie powiodą się, jeśli zamiast niej zostanie użyty znak plus. Oczywiście będzie to różnić się w zależności od implementacji API, a przebieg może się różnić.źródło
Uważam, że urlencode jest dla parametrów zapytania, podczas gdy rawurlencode jest dla segmentów ścieżki. Wynika to głównie z
%20
segmentów ścieżki vs+
parametrów zapytania. Zobacz tę odpowiedź, która mówi o spacjach: Kiedy zakodować spację na plus (+) lub% 20?Jednak
%20
teraz działa również w parametrach zapytań, dlatego rawurlencode jest zawsze bezpieczniejszy. Jednak znak plus jest zwykle używany, gdy liczy się wygoda użytkownika w edycji i czytelność parametrów zapytania.Zauważ, że to oznacza,
rawurldecode
że nie dekoduje się+
w spacje ( http://au2.php.net/manual/en/function.rawurldecode.php ). To dlatego $ _GET jest zawsze automatycznie przekazywane przezurldecode
, co oznacza, że+
i%20
są dekodowane na obu przestrzeniach.Jeśli chcesz, aby kodowanie i dekodowanie były spójne między danymi wejściowymi i wyjściowymi, a wybrałeś zawsze używanie,
+
a nie%20
parametry zapytania, tourlencode
jest w porządku dla parametrów zapytania (klucz i wartość).Z tego wniosek:
Segmenty ścieżki - zawsze używaj kodu rawurlencode / rawurldecode
Parametry zapytania - do dekodowania zawsze używaj kodu urld (wykonywanego automatycznie), do kodowania, zarówno kod rawurlencode, jak i kod urlencode są w porządku, po prostu wybierz jeden, aby zachować spójność, szczególnie przy porównywaniu adresów URL.
źródło
simple * rawurlencode ścieżka - ścieżka jest częścią przed „?” - spacje muszą być zakodowane jako% 20 * urlencode ciąg zapytania - Ciąg zapytania jest częścią po „?” -przestrzenie są lepiej kodowane jako „+” = rawurlencode jest ogólnie bardziej kompatybilny
źródło