urlencode vs rawurlencode?

380

Wenn ich eine URL mit einer Variablen erstellen möchte, habe ich zwei Möglichkeiten, die Zeichenfolge zu codieren. urlencode()und rawurlencode().

Was genau sind die Unterschiede und welche werden bevorzugt?

Gary Willoughby
quelle
1
Ich würde wirklich gerne einige Gründe für die Auswahl eines über dem anderen sehen (z. B. Probleme, die bei dem einen oder anderen auftreten könnten). Ich (und ich erwarte andere) möchte in der Lage sein, einfach einen auszuwählen und ihn für immer mit dem zu verwenden Am wenigsten Aufhebens, also habe ich eine Prämie für diese Frage begonnen.
Kzqai
29
@Tchalvak: Wenn Sie nur eine auswählen möchten, wählen Sie rawurlencode. Sie werden selten auf ein System stoßen, das erstickt, wenn Leerzeichen codiert werden %20, während Systeme, die an Leerzeichen verschlüsselt +sind, häufiger als verschlüsselt sind.
Anomie

Antworten:

326

Es wird von Ihrem Zweck abhängen. Wenn die Interoperabilität mit anderen Systemen wichtig ist, scheint Rawurlencode der richtige Weg zu sein. Die einzige Ausnahme bilden Legacy-Systeme, bei denen erwartet wird, dass die Abfragezeichenfolge dem Formularcodierungsstil von Leerzeichen folgt, die als + anstelle von% 20 codiert sind (in diesem Fall benötigen Sie Urlencode).

rawurlencode folgt RFC 1738 vor PHP 5.3.0 und danach RFC 3986 (siehe http://us2.php.net/manual/en/function.rawurlencode.php )

Gibt eine Zeichenfolge zurück, in der alle nicht alphanumerischen Zeichen außer -_. ~ Durch ein Prozentzeichen (%) gefolgt von zwei hexadezimalen Ziffern ersetzt wurden. Dies ist die in »RFC 3986 beschriebene Codierung zum Schutz von Literalzeichen vor der Interpretation als spezielle URL-Trennzeichen und zum Schutz von URLs vor der Zerstörung durch Übertragungsmedien mit Zeichenkonvertierungen (wie bei einigen E-Mail-Systemen).

Hinweis zu RFC 3986 vs 1738. Rawurlencode vor PHP 5.3 codierte das Tilde-Zeichen ( ~) gemäß RFC 1738. Ab PHP 5.3 folgt Rawurlencode jedoch RFC 3986, für das keine Tilde-Zeichen codiert werden müssen.

urlencode codiert Leerzeichen als Pluszeichen (nicht wie %20im rawurlencode) (siehe http://us2.php.net/manual/en/function.urlencode.php )

Gibt eine Zeichenfolge zurück, in der alle nicht alphanumerischen Zeichen außer -_ enthalten sind. wurden durch ein Prozentzeichen (%) ersetzt, gefolgt von zwei hexadezimalen Ziffern und Leerzeichen, die als Pluszeichen (+) codiert sind. Es wird auf die gleiche Weise codiert, wie die aus einem WWW-Formular gesendeten Daten codiert werden, dh auf die gleiche Weise wie im Medientyp application / x-www-form-urlencoded. Dies unterscheidet sich von der »RFC 3986-Codierung (siehe rawurlencode ()) darin, dass Leerzeichen aus historischen Gründen als Pluszeichen (+) codiert werden.

Dies entspricht der Definition für application / x-www-form-urlencoded in RFC 1866 .

Zusätzliche Lektüre:

Möglicherweise möchten Sie die Diskussion auch unter http://bytes.com/groups/php/5624-urlencode-vs-rawurlencode sehen .

Auch RFC 2396 ist einen Blick wert. RFC 2396 definiert eine gültige URI-Syntax. Der Hauptteil, an dem wir interessiert sind, stammt aus 3.4 Query Component:

Innerhalb einer Abfragekomponente sind die Zeichen reserviert.";", "/", "?", ":", "@",
"&", "=", "+", ",", and "$"

Wie Sie sehen können, +ist das ein reserviertes Zeichen in der Abfragezeichenfolge und müsste daher gemäß RFC 3986 (wie in rawurlencode) codiert werden.

Jonathan Fingland
quelle
27
Was wird also bevorzugt?
Gary Willoughby
79
rawurlencode. Gehen Sie in diesem Fall mit dem Standard. Urlencode wird nur für Legacy-Zwecke aufbewahrt
Jonathan Fingland
2
Vielen Dank, das dachte ich mir, ich wollte nur eine zweite Meinung, bevor ich anfange, viel Code zu aktualisieren.
Gary Willoughby
3
Ich denke, es ist Rawurlencode, der Leerzeichen nicht als Pluszeichen, sondern als% 20s
codiert
2
@Pindatjuh: Der von Ihnen angegebene Teil Die einzige Ausnahme sind Legacy-Systeme, bei denen erwartet wird, dass die Abfragezeichenfolge dem Formularcodierungsstil von Leerzeichen folgt, die als + anstelle von% 20 codiert sind (in diesem Fall benötigen Sie Urlencode). Dies bedeutet, dass Rawurlencode für die meisten Situationen geeignet ist Einige Systeme erwarten, dass Leerzeichen als + (Pluszeichen) codiert werden. Für solche Systeme ist Urlencode die bessere Wahl.
Jonathan Fingland
213

Der Beweis ist im Quellcode von PHP.

Ich werde Sie durch einen kurzen Prozess führen, wie Sie diese Art von Dingen in Zukunft jederzeit selbst herausfinden können. Denken Sie daran, es wird eine Menge C-Quellcode geben, den Sie überfliegen können (ich erkläre es). Wenn Sie etwas C auffrischen möchten, ist unser SO-Wiki ein guter Anfang .

Laden Sie die Quelle herunter (oder verwenden Sie http://lxr.php.net/, um sie online zu durchsuchen), durchsuchen Sie alle Dateien nach dem Funktionsnamen. Sie finden Folgendes:

PHP 5.3.6 (letzter zum Zeitpunkt des Schreibens) beschreibt die beiden Funktionen in ihrem nativen C - Code in der Datei 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);
}

Okay, was ist hier anders?

Beide rufen im Wesentlichen zwei verschiedene interne Funktionen auf: php_raw_url_encode und php_url_encode

Suchen Sie also nach diesen Funktionen!

Schauen wir uns php_raw_url_encode an

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);
}

Und natürlich 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;
}

Ein schnell bisschen Wissen , bevor ich vorwärts zu bewegen, EBCDIC ist ein weiterer Zeichensatz , ähnlich wie ASCII, aber insgesamt Wettbewerber. PHP versucht mit beiden umzugehen. Aber im Grunde bedeutet dies, dass das Byte EBCDIC 0x4c Byte nicht das Lin ASCII ist, sondern tatsächlich ein <. Ich bin sicher, Sie sehen die Verwirrung hier.

Beide Funktionen verwalten EBCDIC, wenn der Webserver es definiert hat.

Außerdem verwenden beide ein Array von Zeichen (Think String Type) hexchars, um einige Werte abzurufen. Das Array wird als solches beschrieben:

/* 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";

Darüber hinaus sind die Funktionen sehr unterschiedlich und ich werde sie in ASCII und EBCDIC erklären.

Unterschiede in ASCII:

URLENCODE:

  • Berechnet eine Start- / Endlänge der Eingabezeichenfolge und weist Speicher zu
  • Geht durch eine while-Schleife und erhöht sich, bis das Ende der Zeichenfolge erreicht ist
  • Greift den gegenwärtigen Charakter
  • Wenn das Zeichen gleich ASCII Char 0x20 ist (dh ein "Leerzeichen"), fügen Sie +der Ausgabezeichenfolge ein Vorzeichen hinzu.
  • Wenn es nicht ein Raum, und es ist auch nicht alphanumerische Zeichen ( isalnum(c)), und auch nicht und _, -oder .Zeichen, dann wir, gibt ein %Zeichen Feldposition 0, tun einen Array Blick auf die oben hexcharsfür eine Referenz für die Array - os_toasciiAnordnung ( Ein Array von Apache, das char in Hex-Code übersetzt) ​​für den Schlüssel von c(das vorliegende Zeichen), verschieben wir dann bitweise um 4 nach rechts, weisen diesen Wert dem Zeichen 1 zu und zu Position 2 weisen wir die gleiche Suche zu, außer wir formen vor eine logische und um zu sehen, ob der Wert 15 (0xF) ist, und geben Sie in diesem Fall eine 1 oder eine 0 zurück. Am Ende erhalten Sie etwas Codiertes.
  • Wenn es am Ende kein Leerzeichen ist, es ist alphanumerisch oder eines der _-.Zeichen, gibt es genau das aus, was es ist.

RAWURLENCODE:

  • Ordnet Speicher für die Zeichenfolge zu
  • Iteriert darüber basierend auf der im Funktionsaufruf angegebenen Länge (nicht in der Funktion wie bei URLENCODE berechnet).

Hinweis: Viele Programmierer haben wahrscheinlich noch nie gesehen, dass eine for-Schleife auf diese Weise iteriert. Sie ist etwas hackig und nicht die Standardkonvention, die bei den meisten for-Schleifen verwendet wird. Achten Sie darauf, sie weist zu xund yprüft, ob sie bei lenErreichen von 0 beendet wird, und erhöht sowohl xals auch y. Ich weiß, es ist nicht das, was Sie erwarten würden, aber es ist gültiger Code.

  • Weist das aktuelle Zeichen einer übereinstimmenden Zeichenposition in zu str.
  • Es prüft , ob das vorliegende Zeichen alphanumerische oder eines der _-.Zeichen, und wenn dies nicht der Fall, haben wir fast die gleiche Belegung wie bei urlencode wo es Lookups Preforms jedoch erhöhen wir anders verwenden , y++anstatt to[1], ist dies , weil die Saiten werden auf unterschiedliche Weise gebaut, erreichen aber am Ende trotzdem das gleiche Ziel.
  • Wenn die Schleife fertig ist und die Länge weg ist, wird die Zeichenfolge tatsächlich beendet und das \0Byte zugewiesen.
  • Es gibt die codierte Zeichenfolge zurück.

Unterschiede:

  • UrlEncode sucht nach Leerzeichen, weist ein + -Zeichen zu, RawURLEncode nicht.
  • UrlEncode weist \0der Zeichenfolge kein Byte zu, RawUrlEncode jedoch (dies kann ein strittiger Punkt sein).
  • Sie iterieren unterschiedlich, man kann dazu neigen, mit fehlerhaften Zeichenfolgen überzulaufen. Ich schlage dies lediglich vor und habe es nicht wirklich untersucht.

Sie iterieren grundsätzlich anders, man weist bei ASCII 20 ein + -Zeichen zu.

Unterschiede in der EBCDIC:

URLENCODE:

  • Gleiches Iterationssetup wie bei ASCII
  • Das Leerzeichen wird immer noch in ein + -Zeichen übersetzt. Hinweis - Ich denke, dies muss in EBCDIC kompiliert werden, oder Sie werden mit einem Fehler enden? Kann jemand dies bearbeiten und bestätigen?
  • Es prüft , ob die vorliegende char , bevor ein Zeichen ist 0, mit Ausnahme eines Wesens .oder -, oder weniger als , Aaber größer als char 9, OR größer Zund kleiner als aeine , aber nicht _. ODER größer als z(ja, EBCDIC ist irgendwie durcheinander, um damit zu arbeiten). Wenn es mit einem dieser Elemente übereinstimmt, führen Sie eine ähnliche Suche wie in der ASCII-Version durch (es ist lediglich keine Suche in os_toascii erforderlich).

RAWURLENCODE:

  • Gleiches Iterationssetup wie bei ASCII
  • Dieselbe Prüfung wie in der EBCDIC-Version von URL Encode beschrieben, mit der Ausnahme, dass zsie ~von der URL-Codierung ausgeschlossen wird , wenn sie größer als ist .
  • Gleiche Zuordnung wie der ASCII RawUrlEncode
  • Hängt das \0Byte vor der Rückkehr immer noch an die Zeichenfolge an.

Große Zusammenfassung

  • Beide verwenden dieselbe Hexchars-Nachschlagetabelle
  • URIEncode beendet eine Zeichenfolge nicht mit \ 0, raw nicht.
  • Wenn Sie in EBCDIC arbeiten, würde ich die Verwendung von RawUrlEncode vorschlagen, da es das verwaltet ~, was UrlEncode nicht tut ( dies ist ein gemeldetes Problem ). Es ist erwähnenswert, dass ASCII und EBCDIC 0x20 beide Leerzeichen sind.
  • Sie iterieren unterschiedlich, man kann schneller sein, man kann anfällig für speicher- oder stringbasierte Exploits sein.
  • URIEncode macht ein Leerzeichen in +, RawUrlEncode macht ein Leerzeichen in %20über Array-Lookups.

Haftungsausschluss: Ich habe C seit Jahren nicht mehr berührt und mich EBCDIC schon lange nicht mehr angesehen. Wenn ich irgendwo falsch liege, lass es mich wissen.

Vorgeschlagene Implementierungen

Basierend auf all dem ist Rawurlencode die meiste Zeit der richtige Weg. Wie Sie in Jonathan Finglands Antwort sehen, bleiben Sie in den meisten Fällen dabei. Es befasst sich mit dem modernen Schema für URI-Komponenten, bei dem Urlencode die Dinge auf die alte Art und Weise erledigt, wobei + "Raum" bedeutet.

Wenn Sie versuchen, zwischen dem alten und dem neuen Format zu konvertieren, stellen Sie sicher, dass Ihr Code nicht fehlerhaft ist, und verwandeln Sie etwas, das ein dekodiertes + Zeichen ist, in ein Leerzeichen, indem Sie es versehentlich doppelt codieren, oder ähnliche "oops" -Szenarien Platz / 20% / + Ausgabe.

Wenn Sie auf einem älteren System mit älterer Software arbeiten, die das neue Format nicht bevorzugt, bleiben Sie bei Urlencode. Ich glaube jedoch, dass% 20 tatsächlich abwärtskompatibel ist, da% 20 unter dem alten Standard einfach nicht funktioniert hat bevorzugt. Probieren Sie es aus, wenn Sie zum Herumspielen bereit sind. Lassen Sie uns wissen, wie es für Sie funktioniert hat.

Grundsätzlich sollten Sie bei raw bleiben, es sei denn, Ihr EBCDIC-System hasst Sie wirklich. Die meisten Programmierer werden auf keinem System, das nach dem Jahr 2000, vielleicht sogar 1990, hergestellt wurde, auf EBCDIC stoßen (das ist drängend, aber meiner Meinung nach immer noch wahrscheinlich).

Inkognito
quelle
Ich musste mich nie um die doppelte Codierung kümmern, schließlich sollte ich wissen, was ich codiert habe, da ich die Codierung mache, die ich denken würde. Da ich alles, was ich erhalte, mit einem Kompatibilitätsmodus dekodiere, der weiß, wie man + für Speicherplatz behandelt, bin ich auch nie auf die Probleme gestoßen, vor denen Sie hier warnen möchten. Ich kann verstehen, wenn wir uns die Quelle ansehen, wenn wir nicht wissen, was etwas tut, aber was genau haben wir hier gelernt, das wir nicht schon durch einfaches Ausführen beider Funktionen gewusst haben. Ich weiß, dass ich voreingenommen bin, aber ich kann nicht anders, als zu glauben, dass dies weit über Bord gegangen ist. Ein großes Lob für die Mühe! =)
Nickl
2
+1, für diesen Teil: "Ich glaube,% 20 wird tatsächlich abwärtskompatibel sein, da unter dem alten Standard% 20 funktioniert hat, wurde einfach nicht bevorzugt"
Gras Double
3
Gute Antwort, aber vielleicht ein bisschen übertrieben?
Rinogo
38
echo rawurlencode('http://www.google.com/index.html?id=asd asd');

ergibt

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

während

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

ergibt

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

Der Unterschied ist der asd%20asdvsasd+asd

urlencode unterscheidet sich von RFC 1738 durch die Codierung von Leerzeichen +anstelle von%20

Jitter
quelle
28

Ein praktischer Grund, einen über den anderen zu wählen, besteht darin, das Ergebnis in einer anderen Umgebung zu verwenden, beispielsweise in JavaScript.

In PHP wird urlencode('test 1')zurückgegeben, 'test+1'während rawurlencode('test 1')zurückgegeben wird'test%201' als Ergebnis.

Wenn Sie dies jedoch in JavaScript mit der Funktion decodeURI () "dekodieren" decodeURI("test+1")müssen, erhalten Sie, "test+1"während decodeURI("test%201")Sie "test 1"das Ergebnis erhalten.

Mit anderen Worten, der von urlencode bis plus ("+") in PHP codierte Leerzeichen ("") wird von decodeURI in JavaScript nicht ordnungsgemäß decodiert .

In solchen Fällen sollte die Rawurlencode- PHP-Funktion verwendet werden.

Neven Boyanov
quelle
6
Dies ist bei weitem die beste Antwort, die ich gesehen habe. Es enthält einen Verwendungsvorschlag anhand eines Beispiels aus der Praxis. Darüber hinaus ist es prägnant.
Dotancohen
Es ist ein schönes Beispiel, obwohl ich es bevorzuge json_encodeund JSON.parsezu diesem Zweck.
Fabrício Matté
21

Ich glaube, Leerzeichen müssen wie folgt codiert werden:

Das folgende Beispiel zeigt die korrekte Verwendung von rawurlencodeund urlencode:

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

Ausgabe:

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

Was passiert, wenn Sie Pfad- und Abfragezeichenfolgenkomponenten umgekehrt codieren? Für das folgende Beispiel:

http://example.com/category/latest+songs/search?q=lady%20gaga
  • Der Webserver sucht latest+songsstattdessen nach dem Verzeichnislatest songs
  • Der Abfragezeichenfolgenparameter qenthältlady gaga
Salman A.
quelle
2
"Der Abfragezeichenfolgenparameter qenthält lady gaga" Was würde er sonst noch enthalten? Der Abfrageparameter qscheint $_GETunabhängig von der Verwendung denselben Wert an das Array übergeben zu habenrawurlencode oder urlencodein PHP 5.2+ übergeben zu haben. Obwohl, urlencodecodiert in dem application/x-www-form-urlencodedFormat , das standardmäßig für GET - Anfragen ist , damit ich mit dem Ansatz gehe. +1
Fabrício Matté
2
Ich wollte klarstellen, dass beide +und %20als Leerzeichen dekodiert werden, wenn sie in Abfragezeichenfolgen verwendet werden.
Salman A
5

Der Unterschied liegt in den Rückgabewerten, dh:

urlencode () :

Gibt eine Zeichenfolge zurück, in der alle nicht alphanumerischen Zeichen außer -_ enthalten sind. wurden durch ein Prozentzeichen (%) ersetzt, gefolgt von zwei hexadezimalen Ziffern und Leerzeichen, die als Pluszeichen (+) codiert sind. Es wird auf die gleiche Weise codiert, wie die aus einem WWW-Formular gesendeten Daten codiert werden, dh auf die gleiche Weise wie im Medientyp application / x-www-form-urlencoded. Dies unterscheidet sich von der »RFC 1738-Codierung (siehe rawurlencode ()) darin, dass Leerzeichen aus historischen Gründen als Pluszeichen (+) codiert werden.

rawurlencode () :

Gibt eine Zeichenfolge zurück, in der alle nicht alphanumerischen Zeichen außer -_ enthalten sind. wurden durch ein Prozentzeichen (%) gefolgt von zwei hexadezimalen Ziffern ersetzt. Dies ist die in »RFC 1738 beschriebene Codierung zum Schutz von Literalzeichen vor der Interpretation als spezielle URL-Trennzeichen und zum Schutz von URLs vor der Zerstörung durch Übertragungsmedien mit Zeichenkonvertierungen (wie bei einigen E-Mail-Systemen).

Die beiden sind sich sehr ähnlich, aber letztere (rawurlencode) ersetzen Leerzeichen durch ein '%' und zwei hexadezimale Ziffern, was zum Codieren von Passwörtern oder dergleichen geeignet ist, wobei ein '+' nicht z.

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
quelle
2
Das OP fragt, wie und wann zu verwenden ist. Zu wissen, was jeder mit Leerzeichen macht, hilft dem OP nicht, eine Entscheidung zu treffen, wenn er die Bedeutung der verschiedenen Rückgabewerte nicht kennt.
Dotancohen
5

1. Was genau sind die Unterschiede und

Der einzige Unterschied besteht in der Art und Weise, wie Räume behandelt werden:

urlencode - basierend auf der Legacy-Implementierung konvertiert Leerzeichen in +

rawurlencode - basierend auf RFC 1738 übersetzt Leerzeichen in% 20

Der Grund für den Unterschied ist, dass + in URLs reserviert und gültig (nicht codiert) ist.

2. welches ist bevorzugt?

Ich würde wirklich gerne einige Gründe dafür sehen, einen über den anderen zu wählen ... Ich möchte in der Lage sein, einfach einen auszuwählen und ihn mit dem geringsten Aufwand für immer zu verwenden.

Fairerweise habe ich eine einfache Strategie, die ich bei diesen Entscheidungen verfolge und die ich mit Ihnen teilen werde, in der Hoffnung, dass sie helfen kann.

Ich denke, es war die HTTP / 1.1-Spezifikation RFC 2616, die " tolerante Anwendungen " forderte.

Clients sollten tolerant beim Parsen der Statuszeile und Server tolerant beim Parsen der Anforderungszeile sein.

Bei solchen Fragen besteht die beste Strategie immer darin, so viel wie möglich zu konsumieren und Standards zu produzieren, die den Standards entsprechen.

Mein Rat ist daher rawurlencode, standardkonforme RFC 1738-codierte Zeichenfolgen urldecodezu erstellen und abwärtskompatibel zu sein und alles zu berücksichtigen, was Sie möglicherweise verbrauchen.

Jetzt könnten Sie einfach mein Wort dafür nehmen, aber lassen Sie uns beweisen, dass wir ...

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

Es scheint, dass PHP genau dies im Sinn hatte, obwohl ich noch nie auf jemanden gestoßen bin, der eines der beiden Formate ablehnt, kann ich mir keine bessere Strategie als Ihre Defacto-Strategie vorstellen, oder?

nJoy!

Nickl-
quelle
4

Urlencode : Dies unterscheidet sich von der »RFC 1738-Codierung (siehe rawurlencode ()) darin, dass Leerzeichen aus historischen Gründen als Pluszeichen (+) codiert werden.

Remus Rusanu
quelle
2

Leerzeichen codiert als %20vs.+

Der Hauptgrund, den ich rawurlencode()in den meisten Fällen gesehen habe, ist, dass urlencodeTexträume als +(Pluszeichen) rawurlencodecodiert werden, wobei sie als häufig gesehen codiert werden %20:

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

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

Ich habe speziell bestimmte API-Endpunkte gesehen, die codierte Textabfragen akzeptieren, die %20für ein Leerzeichen erwartet werden, und daher fehlschlagen, wenn stattdessen ein Pluszeichen verwendet wird. Offensichtlich wird dies zwischen API-Implementierungen unterschiedlich sein und Ihr Kilometerstand kann variieren.

Jake Wilson
quelle
1

Ich glaube, Urlencode ist für Abfrageparameter, während der Rawurlencode für die Pfadsegmente ist. Dies ist hauptsächlich auf %20Pfadsegmente +und Abfrageparameter zurückzuführen. Siehe diese Antwort, die über die Räume spricht: Wann muss das Leerzeichen in Plus (+) oder% 20 codiert werden?

Funktioniert %20jetzt jedoch auch in Abfrageparametern, weshalb rawurlencode immer sicherer ist. Das Pluszeichen wird jedoch häufig verwendet, wenn die Benutzererfahrung bei der Bearbeitung und Lesbarkeit von Abfrageparametern von Bedeutung ist.

Beachten Sie, dass dies bedeutet, rawurldecodedass nicht +in Leerzeichen dekodiert wird ( http://au2.php.net/manual/en/function.rawurldecode.php ). Aus diesem Grund wird $ _GET immer automatisch durchlaufen urldecode, was bedeutet, dass +und%20 beide in die Räume decodiert.

Wenn Sie möchten, dass die Codierung und Decodierung zwischen Ein- und Ausgängen konsistent ist und Sie ausgewählt haben, dass sie immer +und nicht %20für Abfrageparameter verwendet werden sollen, dannurlencode ist dies für Abfrageparameter (Schlüssel und Wert) in Ordnung.

Die Schlussfolgerung lautet:

Pfadsegmente - verwenden Sie immer rawurlencode / rawurldecode

Abfrageparameter - Verwenden Sie zum Decodieren immer den URL-Code (automatisch). Für die Codierung ist sowohl der Rawurlencode als auch der Urlencode in Ordnung. Wählen Sie einfach einen aus, um konsistent zu sein, insbesondere beim Vergleichen von URLs.

CMCDragonkai
quelle
0

simple * rawurlencode der Pfad - Pfad ist der Teil vor dem "?" - Leerzeichen müssen als% 20 * urlencode der Abfragezeichenfolge codiert werden. - Abfragezeichenfolge ist der Teil nach dem "?" -spaces sind besser codiert als "+" = rawurlencode ist im Allgemeinen kompatibler

Haysam Elmasry
quelle