urlencode vs rawurlencode?

380

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?

Gary Willoughby
źródło
1
Naprawdę chciałbym zobaczyć kilka powodów, dla których wybieram jeden (drugi) (np. Problemy, które mogą wystąpić z jednym lub drugim), ja (i spodziewam się, że inni) będą w stanie po prostu wybrać jeden i używać go na zawsze z najmniej zamieszania, więc zacząłem nagrodę za to pytanie.
Kzqai,
29
@Tchalvak: Jeśli chcesz wybrać tylko jeden, wybierz 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.
Anomie

Odpowiedzi:

326

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 )

Zwraca ciąg, w którym wszystkie znaki niealfanumeryczne oprócz -_. ~ Zostały zastąpione znakiem procentu (%), po którym następują dwie cyfry szesnastkowe. Jest to kodowanie opisane w »RFC 3986 do ochrony literalnych znaków przed interpretacją jako specjalne ograniczniki adresów URL oraz do ochrony adresów URL przed zniekształcaniem przez media transmisyjne z konwersjami znaków (jak niektóre systemy poczty e-mail).

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 %20jak w rawurlencode) (patrz http://us2.php.net/manual/en/function.urlencode.php )

Zwraca ciąg znaków, w którym wszystkie znaki niealfanumeryczne oprócz -_. zostały zastąpione znakiem procentu (%), po którym następują dwie cyfry szesnastkowe i spacje zakodowane jako znaki plus (+). Jest zakodowany w taki sam sposób, jak zakodowane dane z formularza WWW, czyli w taki sam sposób, jak w przypadku media / application-x-www-form-urlencoded. Różni się to od kodowania »RFC 3986 (patrz rawurlencode ()) tym, że ze względów historycznych spacje są kodowane jako znaki plus (+).

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:

W ramach komponentu zapytania znaki są zastrzeżone.";", "/", "?", ":", "@",
"&", "=", "+", ",", and "$"

Jak widać, +jest to znak zastrzeżony w ciągu zapytania i dlatego musiałby zostać zakodowany zgodnie z RFC 3986 (jak w rawurlencode).

Jonathan Fingland
źródło
27
Więc co jest preferowane?
Gary Willoughby
79
rawurlencode. w tym przypadku wybierz standard. urlencode jest przechowywany tylko do użytku starszego
Jonathan Fingland
2
Świetne dzięki, tak myślałem, chciałem tylko drugiej opinii, zanim zacznę aktualizować dużo kodu.
Gary Willoughby
3
Myślę, że to rawurlencode, który nie koduje spacji jako znaków plus, ale jako% 20s
BigName
2
@Pindatjuh: Część, którą zacytowałeś Jedynym wyjątkiem są starsze systemy, które oczekują, że ciąg zapytania będzie zgodny ze stylem kodowania formularzy spacji zakodowanych jako + zamiast% 20 (w którym to przypadku potrzebujesz kodu urlencode) oznacza, że ​​podczas gdy rawurlencode jest odpowiedni dla większości sytuacji , niektóre systemy oczekują, że spacje będą kodowane jako znak + (znak plus). Dla takich systemów lepszym wyborem jest kod urlencode.
Jonathan Fingland
213

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 ()

PHP_FUNCTION(rawurlencode)
{
    char *in_str, *out_str;
    int in_str_len, out_str_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in_str,
                              &in_str_len) == FAILURE) {
        return;
    }

    out_str = php_raw_url_encode(in_str, in_str_len, &out_str_len);
    RETURN_STRINGL(out_str, out_str_len, 0);
}

UrlEncode ()

PHP_FUNCTION(urlencode)
{
    char *in_str, *out_str;
    int in_str_len, out_str_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in_str,
                              &in_str_len) == FAILURE) {
        return;
    }

    out_str = php_url_encode(in_str, in_str_len, &out_str_len);
    RETURN_STRINGL(out_str, out_str_len, 0);
}

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

PHPAPI char *php_raw_url_encode(char const *s, int len, int *new_length)
{
    register int x, y;
    unsigned char *str;

    str = (unsigned char *) safe_emalloc(3, len, 1);
    for (x = 0, y = 0; len--; x++, y++) {
        str[y] = (unsigned char) s[x];
#ifndef CHARSET_EBCDIC
        if ((str[y] < '0' && str[y] != '-' && str[y] != '.') ||
            (str[y] < 'A' && str[y] > '9') ||
            (str[y] > 'Z' && str[y] < 'a' && str[y] != '_') ||
            (str[y] > 'z' && str[y] != '~')) {
            str[y++] = '%';
            str[y++] = hexchars[(unsigned char) s[x] >> 4];
            str[y] = hexchars[(unsigned char) s[x] & 15];
#else /*CHARSET_EBCDIC*/
        if (!isalnum(str[y]) && strchr("_-.~", str[y]) != NULL) {
            str[y++] = '%';
            str[y++] = hexchars[os_toascii[(unsigned char) s[x]] >> 4];
            str[y] = hexchars[os_toascii[(unsigned char) s[x]] & 15];
#endif /*CHARSET_EBCDIC*/
        }
    }
    str[y] = '\0';
    if (new_length) {
        *new_length = y;
    }
    return ((char *) str);
}

I oczywiście php_url_encode:

PHPAPI char *php_url_encode(char const *s, int len, int *new_length)
{
    register unsigned char c;
    unsigned char *to, *start;
    unsigned char const *from, *end;

    from = (unsigned char *)s;
    end = (unsigned char *)s + len;
    start = to = (unsigned char *) safe_emalloc(3, len, 1);

    while (from < end) {
        c = *from++;

        if (c == ' ') {
            *to++ = '+';
#ifndef CHARSET_EBCDIC
        } else if ((c < '0' && c != '-' && c != '.') ||
                   (c < 'A' && c > '9') ||
                   (c > 'Z' && c < 'a' && c != '_') ||
                   (c > 'z')) {
            to[0] = '%';
            to[1] = hexchars[c >> 4];
            to[2] = hexchars[c & 15];
            to += 3;
#else /*CHARSET_EBCDIC*/
        } else if (!isalnum(c) && strchr("_-.", c) == NULL) {
            /* Allow only alphanumeric chars and '_', '-', '.'; escape the rest */
            to[0] = '%';
            to[1] = hexchars[os_toascii[c] >> 4];
            to[2] = hexchars[os_toascii[c] & 15];
            to += 3;
#endif /*CHARSET_EBCDIC*/
        } else {
            *to++ = c;
        }
    }
    *to = 0;
    if (new_length) {
        *new_length = to - start;
    }
    return (char *) start;
}

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 Lw 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:

/* rfc1738:

   ...The characters ";",
   "/", "?", ":", "@", "=" and "&" are the characters which may be
   reserved for special meaning within a scheme...

   ...Thus, only alphanumerics, the special characters "$-_.+!*'(),", and
   reserved characters used for their reserved purposes may be used
   unencoded within a URL...

   For added safety, we only leave -_. unencoded.
 */

static unsigned char hexchars[] = "0123456789ABCDEF";

Poza tym funkcje są naprawdę różne i wyjaśnię je w ASCII i EBCDIC.

Różnice w ASCII:

URLENCODE:

  • Oblicza długość początkową / końcową ciągu wejściowego, przydziela pamięć
  • Przechodzi przez pętlę while, stopniowo, aż dojdziemy do końca łańcucha
  • Łapie obecną postać
  • Jeśli znak jest równy ASCII Char 0x20 (tj. „Spacja”), dodaj +znak do ciągu wyjściowego.
  • Jeśli nie jest to spacja, a także nie jest alfanumeryczna ( isalnum(c)), a także nie jest i _, -lub .znak, wówczas wyprowadzamy %znak do pozycji tablicy 0, sprawdzamy tablicę do hexcharstablicy w celu wyszukania os_toasciitablicy ( tablica z Apache, która tłumaczy char na kod szesnastkowy) dla klucza c(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.
  • Jeśli skończy, to nie jest spacją, jest alfanumeryczny lub jeden z _-.znaków, wyświetla dokładnie to, czym jest.

KOD RAWURLEN:

  • Przydziela pamięć dla ciągu
  • Iteruje nad nim na podstawie długości podanej w wywołaniu funkcji (nie obliczonej w funkcji jak w przypadku URLENCODE).

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 xi ysprawdza wyjście po lenosiągnięciu 0 i zwiększa zarówno, jak xi y. Wiem, że nie jest to, czego można się spodziewać, ale to poprawny kod.

  • Przypisuje obecną postać do pasującej pozycji postaci w str.
  • Sprawdza, czy obecny znak jest alfanumeryczny, czy jest jednym z _-.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ąc y++zamiast to[1]tego, ponieważ ciągi są budowane na różne sposoby, ale i tak osiągają ten sam cel na końcu.
  • Kiedy pętla jest skończona, a długość zniknęła, w rzeczywistości kończy ciąg znaków, przypisując \0bajt.
  • Zwraca zakodowany ciąg.

Różnice:

  • UrlEncode sprawdza miejsce, przypisuje znak +, RawURLEncode nie.
  • UrlEncode nie przypisuje \0bajtu do ciągu, RawUrlEncode robi (może to być kwestia sporna)
  • Powtarzają się one różnie, można mieć skłonność do przepełnienia zniekształconymi łańcuchami, sugeruję to tylko i tak naprawdę nie badałem.

Zasadniczo iterują inaczej, jeden przypisuje znak + w przypadku ASCII 20.

Różnice w EBCDIC:

URLENCODE:

  • Taka sama konfiguracja iteracji jak w ASCII
  • Nadal tłumaczy znak „spacja” na znak + . Uwaga - myślę, że należy to skompilować w EBCDIC, czy skończy się to błędem? Czy ktoś może to edytować i potwierdzić?
  • Sprawdza, czy obecny jest znak znak wcześniej 0, z wyjątkiem bycia .lub -, lub mniejsza niż A, ale większa niż znak 9, lub większej niż Zmniej niż a a, 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:

  • Taka sama konfiguracja iteracji jak w ASCII
  • Ta sama kontrola, jak opisano w wersji EBCDIC URL Encode, z tym wyjątkiem, że jeśli jest większa niż z, wyklucza ~z kodowania URL.
  • To samo przypisanie, co ASCII RawUrlEncode
  • Nadal dołączam \0bajt do ciągu przed zwróceniem.

Wielkie podsumowanie

  • Oba używają tej samej tabeli odnośników hexchars
  • URIEncode nie kończy łańcucha z \ 0, raw robi.
  • Jeśli pracujesz w EBCDIC, sugeruję użycie RawUrlEncode, ponieważ zarządza tym, ~że UrlEncode nie ( jest to zgłaszany problem ). Warto zauważyć, że ASCII i EBCDIC 0x20 są spacjami.
  • Iterują inaczej, jeden może być szybszy, może być podatny na exploity oparte na pamięci lub łańcuchach.
  • URIEncode tworzy spację +, RawUrlEncode tworzy spację %20poprzez 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).

Incognito
źródło
W końcu nigdy nie musiałem się martwić podwójnym kodowaniem. Powinienem wiedzieć, co kodowałem, ponieważ to ja wykonuję kodowanie. Ponieważ dekoduję wszystko, co otrzymuję, w trybie zgodności, który wie, jak traktować + dla przestrzeni, równie dobrze nigdy nie spotkałem się z problemami, o których starasz się tutaj ostrzegać. Mogę zrozumieć patrzenie na źródło, jeśli nie wiemy, co coś robi, ale czego dokładnie się tutaj nauczyliśmy, że nie wiedzieliśmy po prostu wykonując obie funkcje. Wiem, że jestem stronniczy, ale nie mogę przestać myśleć, że poszło to za daleko. Wyrazy uznania dla wysiłku! =)
nickl-
2
+1, w tej części: „Wierzę, że% 20 będzie faktycznie kompatybilny wstecz, ponieważ zgodnie ze starym standardem% 20 działał, po prostu nie był preferowany”
Gras Double
3
Dobra odpowiedź, ale może trochę przesada?
rinogo,
38
echo rawurlencode('http://www.google.com/index.html?id=asd asd');

daje

http%3A%2F%2Fwww.google.com%2Findex.html%3Fid%3Dasd%20asd

podczas

echo urlencode('http://www.google.com/index.html?id=asd asd');

daje

http%3A%2F%2Fwww.google.com%2Findex.html%3Fid%3Dasd+asd

Różnica polega na tym, że asd%20asdvsasd+asd

kod urlencode różni się od RFC 1738 kodowaniem spacji jak +zamiast%20

drganie
źródło
28

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'a rawurlencode('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"natomiast decodeURI("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 .

Neven Boyanov
źródło
6
To zdecydowanie najlepsza odpowiedź, jaką widziałem. Zapewnia sugestię użycia na przykładzie z prawdziwego świata. Ponadto jest zwięzły.
dotancohen
To dobry przykład, chociaż wolę json_encodei JSON.parsedo tego celu.
Fabrício Matté
21

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 rawurlencodei urlencode:

echo "http://example.com"
    . "/category/" . rawurlencode("latest songs")
    . "/search?q=" . urlencode("lady gaga");

Wynik:

http://example.com/category/latest%20songs/search?q=lady+gaga

Co się stanie, jeśli kodujesz ścieżkę i przeszukujesz ciąg znaków w drugą stronę? Dla następującego przykładu:

http://example.com/category/latest+songs/search?q=lady%20gaga
  • Serwer będzie szukał katalogu latest+songszamiastlatest songs
  • Parametr ciągu zapytania qbędzie zawieraćlady gaga
Salman A.
źródło
2
„Parametr ciągu zapytania qbędzie zawierać lady gaga” Co jeszcze zawierałby w innym przypadku? qWydaje się, że parametr zapytania ma tę samą wartość przekazywaną do $_GETtablicy, niezależnie od użycia rawurlencodelub urlencodew PHP 5.2+. Chociaż urlencodekoduje w application/x-www-form-urlencodedformacie domyślnym dla żądań GET, więc idę z twoim podejściem. +1
Fabrício Matté
2
Chciałem wyjaśnić, że zarówno +i %20są dekodowane jako przestrzeń stosowany w ciągów zapytań.
Salman A,
5

Różnica polega na wartościach zwracanych, tj .:

urlencode () :

Zwraca ciąg znaków, w którym wszystkie znaki niealfanumeryczne oprócz -_. zostały zastąpione znakiem procentu (%), po którym następują dwie cyfry szesnastkowe i spacje zakodowane jako znaki plus (+). Jest zakodowany w taki sam sposób, jak zakodowane dane z formularza WWW, czyli w taki sam sposób, jak w przypadku media / application-x-www-form-urlencoded. Różni się to od kodowania »RFC 1738 (patrz rawurlencode ()) tym, że ze względów historycznych spacje są kodowane jako znaki plus (+).

rawurlencode () :

Zwraca ciąg znaków, w którym wszystkie znaki niealfanumeryczne oprócz -_. zostały zastąpione znakiem procentu (%), po którym następują dwie cyfry szesnastkowe. Jest to kodowanie opisane w »RFC 1738 do ochrony literalnych znaków przed interpretacją jako specjalne ograniczniki adresów URL oraz do ochrony adresów URL przed zniekształcaniem przez media transmisyjne z konwersjami znaków (jak niektóre systemy poczty elektronicznej).

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 .:

echo '<a href="ftp://user:', rawurlencode('foo @+%/'),
     '@ftp.example.com/x.txt">';
//Outputs <a href="ftp://user:foo%20%40%2B%25%[email protected]/x.txt">
karim79
źródło
2
OP pyta, jak się dowiedzieć, którego użyć i kiedy. Wiedza na temat tego, co każdy robi ze spacjami, nie pomaga OP podjąć decyzji, jeśli nie zna znaczenia różnych wartości zwracanych.
dotancohen
5

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?

Naprawdę chciałbym zobaczyć kilka powodów, dla których wybieram jeden nad drugim ... Chcę móc wybrać jeden i używać go na zawsze przy najmniejszym zamieszaniu.

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

Klienci POWINNI być tolerancyjni podczas analizowania wiersza stanu, a serwery tolerancyjni podczas analizowania wiersza żądania.

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ć rawurlencodedo tworzenia łańcuchów kodowanych RFC 1738 zgodnych ze standardami i stosować urldecodekompatybilność wsteczną i przyjmować wszystko, co możesz napotkać.

Teraz możesz mi uwierzyć na słowo, ale udowodnijmy, że będziemy ...

php > $url = <<<'EOD'
<<< > "Which, % of Alice's tasks saw $s @ earnings?"
<<< > EOD;
php > echo $url, PHP_EOL;
"Which, % of Alice's tasks saw $s @ earnings?"
php > echo urlencode($url), PHP_EOL;
%22Which%2C+%25+of+Alice%27s+tasks+saw+%24s+%40+earnings%3F%22
php > echo rawurlencode($url), PHP_EOL;
%22Which%2C%20%25%20of%20Alice%27s%20tasks%20saw%20%24s%20%40%20earnings%3F%22
php > echo rawurldecode(urlencode($url)), PHP_EOL;
"Which,+%+of+Alice's+tasks+saw+$s+@+earnings?"
php > // oops that's not right???
php > echo urldecode(rawurlencode($url)), PHP_EOL;
"Which, % of Alice's tasks saw $s @ earnings?"
php > // now that's more like it

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!

nikiel
źródło
4

urlencode : Różni się od kodowania »RFC 1738 (patrz rawurlencode ()) tym, że ze względów historycznych spacje są kodowane jako znaki plus (+).

Remus Rusanu
źródło
2

Spacje zakodowane jako %20vs.+

Największym powodem, dla którego widziałem rawurlencode()w większości przypadków, jest to, że urlencodekoduje spacje tekstowe jako +(znaki plus), gdzie rawurlencodekoduje je jako powszechnie postrzegane %20:

echo urlencode("red shirt");
// red+shirt

echo rawurlencode("red shirt");
// red%20shirt

W szczególności widziałem niektóre punkty końcowe interfejsu API, które akceptują zakodowane zapytania tekstowe, które spodziewają się zobaczyć %20spacji, 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ć.

Jake Wilson
źródło
1

Uważam, że urlencode jest dla parametrów zapytania, podczas gdy rawurlencode jest dla segmentów ścieżki. Wynika to głównie z %20segmentów ścieżki vs +parametrów zapytania. Zobacz tę odpowiedź, która mówi o spacjach: Kiedy zakodować spację na plus (+) lub% 20?

Jednak %20teraz 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 przez urldecode, co oznacza, że +i %20są 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 %20parametry zapytania, to urlencodejest 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.

CMCDragonkai
źródło
0

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

haysam elmasry
źródło