urlencode vs rawurlencode?


380

Nếu tôi muốn tạo một URL bằng một biến, tôi có hai lựa chọn để mã hóa chuỗi. urlencode()rawurlencode().

Chính xác thì sự khác biệt là gì và được ưa thích?


1
Tôi thực sự muốn thấy một số lý do để chọn cái này hơn cái kia (ví dụ như các vấn đề có thể gặp phải với cái này hoặc cái khác), tôi (và tôi mong đợi những người khác) muốn có thể chỉ chọn một và sử dụng nó mãi mãi với ít ồn ào nhất, vì vậy tôi đã bắt đầu trả tiền cho câu hỏi này.
Kzqai

29
@Tchalvak: Nếu bạn muốn chọn chỉ một, hãy chọn rawurlencode. Bạn sẽ hiếm khi chạy vào một hệ thống %20bị nghẹt thở khi được cung cấp các không gian được mã hóa dưới dạng , trong khi các hệ thống bị sặc trên các không gian được mã hóa là +phổ biến hơn.
Anomie

Câu trả lời:


326

Nó sẽ phụ thuộc vào mục đích của bạn. Nếu khả năng tương tác với các hệ thống khác là quan trọng thì có vẻ như rawurlencode là cách để đi. Một ngoại lệ là các hệ thống kế thừa dự kiến ​​chuỗi truy vấn tuân theo kiểu mã hóa biểu mẫu của khoảng trắng được mã hóa là + thay vì% 20 (trong trường hợp đó bạn cần urlencode).

rawurlencode theo RFC 1738 trước PHP 5.3.0 và RFC 3986 sau đó (xem http://us2.php.net/manual/en/feft.rawurlencode.php )

Trả về một chuỗi trong đó tất cả các ký tự không phải là chữ và số trừ -_. ~ Đã được thay thế bằng dấu phần trăm (%) theo sau là hai chữ số hex. Đây là mã hóa được mô tả trong »RFC 3986 để bảo vệ các ký tự bằng chữ không bị hiểu là các dấu phân cách URL đặc biệt và để bảo vệ các URL khỏi bị xáo trộn bởi phương tiện truyền tải với chuyển đổi ký tự (như một số hệ thống email).

Lưu ý về RFC 3986 so với 1738. rawurlencode trước php 5.3 đã mã hóa ký tự dấu ngã ( ~) theo RFC 1738. Tuy nhiên, kể từ PHP 5.3, tuy nhiên, rawurlencode theo RFC 3986 không yêu cầu mã hóa ký tự dấu ngã.

urlencode mã hóa các khoảng trắng dưới dạng dấu cộng (không %20được thực hiện trong rawurlencode) (xem http://us2.php.net/manual/en/feft.urlencode.php )

Trả về một chuỗi trong đó tất cả các ký tự không chữ và số trừ -_. đã được thay thế bằng dấu phần trăm (%) theo sau là hai chữ số hex và dấu cách được mã hóa thành dấu cộng (+). Nó được mã hóa giống như cách dữ liệu được đăng từ một hình thức WWW được mã hóa, giống như trong loại phương tiện ứng dụng / x-www-form-urlencoding. Điều này khác với mã hóa »RFC 3986 (xem rawurlencode ()) ở chỗ vì lý do lịch sử, không gian được mã hóa dưới dạng dấu cộng (+).

Điều này tương ứng với định nghĩa cho ứng dụng / x-www-form-urlencoding trong RFC 1866 .

Đọc thêm:

Bạn cũng có thể muốn xem cuộc thảo luận tại http://bytes.com/groups/php/5624-urlencode-vs-rawurlencode .

Ngoài ra, RFC 2396 là đáng xem. RFC 2396 định nghĩa cú pháp URI hợp lệ. Phần chính chúng tôi quan tâm là từ 3,4 Thành phần truy vấn:

Trong một thành phần truy vấn, các ký tự được bảo lưu.";", "/", "?", ":", "@",
"&", "=", "+", ",", and "$"

Như bạn có thể thấy, +ký tự dành riêng trong chuỗi truy vấn và do đó sẽ cần được mã hóa theo RFC 3986 (như trong rawurlencode).


27
Vì vậy, đó là preffered?
Gary Willoughby

79
rawurlencode. đi với tiêu chuẩn trong trường hợp này. urlencode chỉ được giữ lại để sử dụng kế thừa
Jonathan Fingerland

2
Cảm ơn rất nhiều, đó là những gì tôi nghĩ, tôi chỉ muốn có ý kiến ​​thứ hai trước khi bắt đầu cập nhật nhiều mã.
Gary Willoughby

3
Tôi nghĩ rằng đó là rawurlencode không mã hóa khoảng trắng dưới dạng dấu cộng mà là% 20s
BigName

2
@Pindatjuh: Phần bạn đã trích dẫn Một ngoại lệ là các hệ thống kế thừa mong muốn chuỗi truy vấn tuân theo kiểu mã hóa biểu mẫu của không gian được mã hóa là + thay vì% 20 (trong trường hợp đó bạn cần urlencode) có nghĩa là trong khi rawurlencode phù hợp với hầu hết tình huống , một số hệ thống mong muốn các không gian được mã hóa thành dấu + (dấu cộng). Đối với các hệ thống như vậy, urlencode là lựa chọn tốt hơn.
Jonathan Fingerland

213

Bằng chứng là trong mã nguồn của PHP.

Tôi sẽ đưa bạn qua một quá trình nhanh chóng để tự mình tìm ra loại điều này trong tương lai bất cứ lúc nào bạn muốn. Hãy kiên nhẫn với tôi, sẽ có rất nhiều mã nguồn C bạn có thể lướt qua (tôi giải thích nó). Nếu bạn muốn theo dõi một số C, một nơi tốt để bắt đầu là wiki SO của chúng tôi .

Tải xuống nguồn (hoặc sử dụng http://lxr.php.net/ để duyệt trực tuyến), grep tất cả các tệp cho tên hàm, bạn sẽ tìm thấy một cái gì đó như thế này:

PHP 5.3.6 (gần đây nhất tại thời điểm viết) mô tả hai hàm trong mã C gốc của chúng trong url.c tệp .

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

Được rồi, vậy có gì khác ở đây?

Cả hai về bản chất đều gọi hai hàm nội bộ khác nhau tương ứng: php_raw_url_encodephp_url_encode

Vì vậy, hãy tìm kiếm các chức năng!

Hãy xem 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);
}

Và tất nhiên, 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;
}

Một chút kiến ​​thức nhanh trước khi tôi tiến lên, EBCDIC là một bộ ký tự khác , tương tự ASCII, nhưng là một đối thủ cạnh tranh tổng thể. PHP cố gắng để đối phó với cả hai. Nhưng về cơ bản, điều này có nghĩa là byte EBCDIC 0x4c byte không phải là LASCII, nó thực sự là một <. Tôi chắc rằng bạn nhìn thấy sự nhầm lẫn ở đây.

Cả hai chức năng này đều quản lý EBCDIC nếu máy chủ web đã xác định nó.

Ngoài ra, cả hai đều sử dụng một mảng các ký tự (kiểu chuỗi suy nghĩ) hexcharsđể tìm kiếm một số giá trị, mảng được mô tả như sau:

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

Ngoài ra, các chức năng thực sự khác nhau và tôi sẽ giải thích chúng trong ASCII và EBCDIC.

Sự khác biệt trong ASCII:

URLENCODE:

  • Tính độ dài bắt đầu / kết thúc của chuỗi đầu vào, phân bổ bộ nhớ
  • Đi qua một vòng lặp while, tăng dần cho đến khi chúng ta đi đến cuối chuỗi
  • Lấy nhân vật hiện tại
  • Nếu ký tự bằng ASCII Char 0x20 (nghĩa là "khoảng trắng"), hãy thêm một +dấu hiệu vào chuỗi đầu ra.
  • Nếu nó không phải là một khoảng trắng và nó cũng không phải là chữ và số ( isalnum(c)), và cũng không phải và _, -hoặc .ký tự, thì chúng ta, xuất một %dấu hiệu đến vị trí mảng 0, thực hiện một mảng tìm đến hexcharsmảng để tìm kiếm os_toasciimảng ( tìm kiếm mảng) một mảng từ Apache dịch mã char thành mã hex) cho khóa của c(ký tự hiện tại), sau đó chúng ta dịch chuyển bit phải sang 4, gán giá trị đó cho ký tự 1 và đến vị trí 2, chúng ta gán cùng một tra cứu, ngoại trừ chúng ta tạo khuôn một logic và để xem nếu giá trị là 15 (0xF) và trả về 1 trong trường hợp đó hoặc 0 khác. Cuối cùng, bạn sẽ kết thúc với một cái gì đó được mã hóa.
  • Nếu kết thúc nó không phải là một khoảng trắng, đó là chữ và số hoặc một trong các _-.ký tự, nó xuất ra chính xác nó là gì.

RAWURLENCODE:

  • Phân bổ bộ nhớ cho chuỗi
  • Lặp lại trên nó dựa trên độ dài được cung cấp trong lệnh gọi hàm (không được tính trong hàm như với URLENCODE).

Lưu ý: Nhiều lập trình viên có thể chưa bao giờ thấy một vòng lặp lặp theo cách này, nó hơi hack và không phải là quy ước tiêu chuẩn được sử dụng với hầu hết các vòng lặp, chú ý, nó gán xy, kiểm tra thoát khi lenđạt 0, và tăng cả hai xy. Tôi biết, đó không phải là những gì bạn mong đợi, nhưng đó là mã hợp lệ.

  • Chỉ định ký tự hiện tại cho một vị trí ký tự phù hợp trong str.
  • Nó kiểm tra xem ký tự hiện tại có phải là chữ và số hay một trong các _-.ký tự không và nếu không, chúng tôi thực hiện gần như cùng một nhiệm vụ với URLENCODE, trong đó nó tạo ra các tra cứu, tuy nhiên, chúng tôi tăng khác nhau, sử dụng y++thay vì to[1], điều này là do các chuỗi đang được xây dựng theo những cách khác nhau, nhưng dù sao cũng đạt được cùng một mục tiêu.
  • Khi vòng lặp hoàn thành và độ dài hết, Nó thực sự chấm dứt chuỗi, gán \0byte.
  • Nó trả về chuỗi được mã hóa.

Sự khác biệt:

  • UrlEncode kiểm tra không gian, gán dấu +, RawURLEncode thì không.
  • UrlEncode không gán một \0byte cho chuỗi, RawUrlEncode thực hiện (đây có thể là điểm moot)
  • Chúng lặp đi lặp lại một cách khác nhau, một người có thể dễ bị tràn với các chuỗi không đúng định dạng, tôi chỉ đề xuất điều này và tôi chưa thực sự điều tra.

Về cơ bản, chúng lặp đi lặp lại khác nhau, người ta gán dấu + trong trường hợp ASCII 20.

Sự khác biệt trong EBCDIC:

URLENCODE:

  • Thiết lập lặp tương tự như với ASCII
  • Vẫn dịch ký tự "dấu cách" thành dấu + . Lưu ý-- Tôi nghĩ rằng điều này cần phải được biên dịch trong EBCDIC hoặc bạn sẽ gặp phải một lỗi? Ai đó có thể chỉnh sửa và xác nhận điều này?
  • Nó kiểm tra xem char hiện tại có phải là char trước hay không 0, ngoại trừ là một .hoặc -, OR nhỏ hơn Anhưng lớn hơn char 9, OR lớn hơn Zvà nhỏ hơn anhưng không phải là a _. HOẶC lớn hơn z(vâng, EBCDIC hơi rối khi làm việc với). Nếu nó phù hợp với bất kỳ thứ nào trong số đó, hãy thực hiện tra cứu tương tự như trong phiên bản ASCII (nó không yêu cầu tra cứu trong os_toascii).

RAWURLENCODE:

  • Thiết lập lặp tương tự như với ASCII
  • Kiểm tra tương tự như được mô tả trong phiên bản EBCDIC của Mã hóa URL, ngoại trừ nếu nó lớn hơn z, nó sẽ loại trừ ~khỏi mã hóa URL.
  • Nhiệm vụ tương tự như ASCII RawUrlEncode
  • Vẫn nối thêm \0byte vào chuỗi trước khi trả về.

Tóm tắt lớn

  • Cả hai đều sử dụng cùng một bảng tra cứu hexchars
  • URIEncode không chấm dứt một chuỗi với \ 0, raw không.
  • Nếu bạn đang làm việc trong EBCDIC, tôi khuyên bạn nên sử dụng RawUrlEncode, vì nó quản lý ~UrlEncode đó không ( đây là một vấn đề được báo cáo ). Điều đáng chú ý là ASCII và EBCDIC 0x20 đều là không gian.
  • Chúng lặp đi lặp lại khác nhau, một cái có thể nhanh hơn, một cái có thể dễ bị khai thác dựa trên bộ nhớ hoặc chuỗi.
  • URIEncode tạo khoảng trống vào +, RawUrlEncode tạo khoảng trống %20thông qua tra cứu mảng.

Tuyên bố miễn trừ trách nhiệm: Tôi đã không chạm vào C trong nhiều năm và tôi đã không nhìn vào EBCDIC trong một thời gian thực sự dài. Nếu tôi sai ở đâu đó, hãy cho tôi biết.

Đề xuất thực hiện

Dựa trên tất cả những điều này, rawurlencode là cách để đi hầu hết thời gian. Như bạn thấy trong câu trả lời của Jonathan Fingerland, hãy kiên trì với nó trong hầu hết các trường hợp. Nó liên quan đến sơ đồ hiện đại cho các thành phần URI, trong đó như urlencode thực hiện mọi thứ theo cách trường học cũ, trong đó + có nghĩa là "không gian".

Nếu bạn đang cố gắng chuyển đổi giữa định dạng cũ và định dạng mới, hãy chắc chắn rằng mã của bạn không bị hỏng và biến thứ gì đó được giải mã + thành không gian bằng cách vô tình mã hóa hai lần hoặc các tình huống "oops" tương tự xung quanh điều này dung lượng / 20% / + vấn đề.

Tuy nhiên, nếu bạn đang làm việc trên một hệ thống cũ hơn với phần mềm cũ không thích định dạng mới, hãy sử dụng urlencode, tuy nhiên, tôi tin rằng% 20 sẽ thực sự tương thích ngược, vì theo tiêu chuẩn cũ 20% hoạt động, chỉ là không hoạt động ưa thích. Cung cấp cho nó một shot nếu bạn đang chơi xung quanh, cho chúng tôi biết làm thế nào nó làm việc cho bạn.

Về cơ bản, bạn nên gắn bó với bản thô, trừ khi hệ thống EBCDIC của bạn thực sự ghét bạn. Hầu hết các lập trình viên sẽ không bao giờ chạy vào EBCDIC trên bất kỳ hệ thống nào được thực hiện sau năm 2000, thậm chí là năm 1990 (theo quan điểm của tôi, nhưng vẫn có khả năng).


Sau tất cả, tôi chưa bao giờ phải lo lắng về việc mã hóa gấp đôi. Tôi nên biết những gì tôi đã mã hóa vì tôi đang nghĩ mã hóa. Vì tôi giải mã mọi thứ tôi nhận được với chế độ tương thích, biết cách xử lý + cho không gian, tôi cũng không bao giờ gặp phải những vấn đề bạn cố gắng cảnh báo ở đây. Tôi có thể hiểu việc nhìn vào nguồn nếu chúng ta không biết điều gì làm, nhưng chính xác những gì chúng ta đã học ở đây mà chúng ta đã không biết chỉ đơn giản là thực hiện cả hai chức năng. Tôi biết tôi thiên vị nhưng tôi không thể không nghĩ rằng điều này đã đi quá mức. Kudos về những nỗ lực mặc dù! =)
nickl-

2
+1, đối với phần này: "Tôi tin rằng% 20 sẽ thực sự tương thích ngược, vì theo tiêu chuẩn cũ% 20 đã hoạt động, chỉ không được ưa thích"
Gras Double

3
Câu trả lời tốt, nhưng có thể hơi quá mức?
rinogo

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

sản lượng

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

trong khi

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

sản lượng

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

Sự khác biệt là asd%20asdvsasd+asd

urlencode khác với RFC 1738 bằng cách mã hóa không gian +thay vì%20


28

Một lý do thực tế để chọn một lý do khác là nếu bạn sẽ sử dụng kết quả này trong một môi trường khác, ví dụ như JavaScript.

Trong PHP urlencode('test 1')trả về 'test+1'trong khi rawurlencode('test 1')trả về 'test%201'như kết quả.

Nhưng nếu bạn cần "giải mã" điều này trong JavaScript bằng hàm decodeURI () thì decodeURI("test+1")sẽ cung cấp cho bạn "test+1"trong khi decodeURI("test%201")sẽ cung cấp cho bạn "test 1"kết quả.

Nói cách khác, không gian ("") được mã hóa bởi urlencode thành dấu cộng ("+") trong PHP sẽ không được giải mã chính xác bởi decodeURI trong JavaScript.

Trong các trường hợp như vậy, nên sử dụng hàm PHP rawurlencode .


6
Đây là câu trả lời tốt nhất mà tôi đã thấy. Nó cung cấp một gợi ý để sử dụng, trở lại bởi một ví dụ trong thế giới thực. Ngoài ra, nó là súc tích.
dotancohen

Đó là một ví dụ tốt đẹp, mặc dù tôi thích json_encodeJSON.parsecho mục đích đó.
Fabrício Matté

21

Tôi tin rằng không gian phải được mã hóa thành:

  • %20 khi được sử dụng bên trong thành phần đường dẫn URL
  • +khi được sử dụng bên trong thành phần chuỗi truy vấn URL hoặc dữ liệu biểu mẫu (xem 17.13.4 Loại nội dung biểu mẫu )

Ví dụ sau đây cho thấy việc sử dụng đúng rawurlencodeurlencode:

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

Đầu ra:

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

Điều gì xảy ra nếu bạn mã hóa các thành phần chuỗi đường dẫn và truy vấn theo cách khác? Ví dụ sau:

http://example.com/category/latest+songs/search?q=lady%20gaga
  • Máy chủ web sẽ tìm thư mục latest+songsthay vìlatest songs
  • Tham số chuỗi truy vấn qsẽ chứalady gaga

2
"Tham số chuỗi truy vấn qsẽ chứa lady gaga" Nó có chứa gì khác không? Tham số truy vấn qdường như có cùng giá trị được truyền cho $_GETmảng bất kể sử dụng rawurlencodehay urlencodetrong PHP 5.2+. Mặc dù, urlencodemã hóa ở application/x-www-form-urlencodedđịnh dạng mặc định cho các yêu cầu GET vì vậy tôi sẽ tiếp cận với cách tiếp cận của bạn. +1
Fabrício Matté

2
Tôi muốn làm rõ rằng cả hai +%20được giải mã là không gian khi được sử dụng trong chuỗi truy vấn.
Salman A

5

Sự khác biệt là trong các giá trị trả về, nghĩa là:

urlencode () :

Trả về một chuỗi trong đó tất cả các ký tự không chữ và số trừ -_. đã được thay thế bằng dấu phần trăm (%) theo sau là hai chữ số hex và dấu cách được mã hóa thành dấu cộng (+). Nó được mã hóa giống như cách dữ liệu được đăng từ một hình thức WWW được mã hóa, giống như trong loại phương tiện ứng dụng / x-www-form-urlencoding. Điều này khác với mã hóa »RFC 1738 (xem rawurlencode ()) ở chỗ vì lý do lịch sử, không gian được mã hóa dưới dạng dấu cộng (+).

rawurlencode () :

Trả về một chuỗi trong đó tất cả các ký tự không chữ và số trừ -_. đã được thay thế bằng dấu phần trăm (%) theo sau là hai chữ số hex. Đây là mã hóa được mô tả trong »RFC 1738 để bảo vệ các ký tự chữ không bị hiểu là các dấu phân cách URL đặc biệt và để bảo vệ các URL khỏi bị xáo trộn bởi phương tiện truyền tải với chuyển đổi ký tự (như một số hệ thống email).

Hai cái này rất giống nhau, nhưng cái sau (rawurlencode) sẽ thay thế khoảng trắng bằng '%' và hai chữ số hex, phù hợp để mã hóa mật khẩu hoặc như vậy, trong đó '+' không phải là:

echo '<a href="ftp://user:', rawurlencode('foo @+%/'),
     '@ftp.example.com/x.txt">';
//Outputs <a href="ftp://user:foo%20%40%2B%25%2F@ftp.example.com/x.txt">

2
OP hỏi làm thế nào để biết nên sử dụng cái nào và khi nào. Biết những gì từng làm với không gian sẽ không giúp OP đưa ra quyết định nếu anh ta không biết tầm quan trọng của các giá trị trả về khác nhau.
dotancohen

5

1. Chính xác thì sự khác biệt là gì và

Sự khác biệt duy nhất là trong cách xử lý không gian:

urlencode - dựa trên triển khai kế thừa chuyển đổi không gian thành +

rawurlencode - dựa trên RFC 1738 chuyển khoảng trắng thành% 20

Lý do cho sự khác biệt là vì + được bảo lưu và hợp lệ (không được mã hóa) trong các url.

2. cái nào được ưa thích?

Tôi thực sự muốn thấy một số lý do để chọn cái này hơn cái kia ... Tôi muốn có thể chỉ chọn một cái và sử dụng nó mãi mãi với ít phiền phức nhất.

Đủ công bằng, tôi có một chiến lược đơn giản mà tôi tuân theo khi đưa ra những quyết định mà tôi sẽ chia sẻ với bạn với hy vọng nó có thể giúp ích.

Tôi nghĩ rằng đó là RFC 2616 đặc tả HTTP / 1.1 được gọi là " Ứng dụng dung sai "

Khách hàng NÊN khoan dung trong việc phân tích dòng trạng thái và máy chủ dung sai khi phân tích dòng yêu cầu.

Khi phải đối mặt với những câu hỏi như thế này, chiến lược tốt nhất là luôn tiêu thụ càng nhiều càng tốt và tạo ra những gì tuân thủ tiêu chuẩn.

Vì vậy, lời khuyên của tôi là sử dụng rawurlencodeđể sản xuất các chuỗi được mã hóa RFC 1738 tuân thủ tiêu chuẩn và sử dụng urldecodeđể tương thích ngược và chứa bất cứ thứ gì bạn có thể gặp để tiêu thụ.

Bây giờ bạn có thể lấy từ của tôi cho nó nhưng hãy chứng minh rằng chúng ta sẽ ...

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

Dường như PHP có chính xác điều này trong đầu, mặc dù tôi chưa bao giờ bắt gặp bất kỳ ai từ chối một trong hai định dạng, tôi không thể nghĩ ra một chiến lược tốt hơn để áp dụng làm chiến lược defacto của bạn, bạn có thể không?

Xin chào!


4

urlencode : Điều này khác với mã hóa »RFC 1738 (xem rawurlencode ()) vì lý do lịch sử, không gian được mã hóa dưới dạng dấu cộng (+).


2

Không gian được mã hóa là %20vs.+

Lý do lớn nhất mà tôi thấy sử dụng rawurlencode()trong hầu hết các trường hợp là vì urlencodemã hóa không gian văn bản dưới dạng +(dấu cộng) trong đó rawurlencodemã hóa chúng như thường thấy %20:

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

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

Tôi đặc biệt đã thấy một số điểm cuối API nhất định chấp nhận các truy vấn văn bản được mã hóa mong muốn thấy %20một khoảng trắng và kết quả là, thất bại nếu sử dụng dấu cộng thay thế. Rõ ràng điều này sẽ khác nhau giữa các lần triển khai API và số dặm của bạn có thể khác nhau.


1

Tôi tin rằng urlencode dành cho các tham số truy vấn, trong khi rawurlencode dành cho các phân đoạn đường dẫn. Điều này chủ yếu là do %20các phân đoạn đường dẫn so +với các tham số truy vấn. Xem câu trả lời này nói về khoảng trắng: Khi nào mã hóa không gian thành dấu cộng (+) hoặc% 20?

Tuy nhiên %20bây giờ cũng hoạt động trong các tham số truy vấn, đó là lý do tại sao rawurlencode luôn an toàn hơn. Tuy nhiên, dấu cộng có xu hướng được sử dụng khi người dùng có kinh nghiệm chỉnh sửa và dễ đọc các tham số truy vấn.

Lưu ý rằng điều này có nghĩa là rawurldecodekhông giải mã +thành khoảng trắng ( http://au2.php.net/manual/en/feft.rawurldecode.php ). Đây là lý do tại sao $ _GET luôn tự động đi qua urldecode, mà phương tiện đó +%20đều được giải mã vào không gian.

Nếu bạn muốn mã hóa và giải mã thống nhất giữa đầu vào và đầu ra và bạn đã chọn luôn luôn sử dụng +và không sử dụng %20cho các tham số truy vấn, thì urlencodetốt cho các tham số truy vấn (khóa và giá trị).

Kết luận là:

Phân đoạn đường dẫn - luôn sử dụng rawurlencode / rawurldecode

Tham số truy vấn - để giải mã luôn sử dụng urldecode (được thực hiện tự động), để mã hóa, cả rawurlencode hoặc urlencode đều ổn, chỉ cần chọn một để thống nhất, đặc biệt là khi so sánh URL.


0

đơn giản * rawurlencode đường dẫn - đường dẫn là phần trước dấu "?" - khoảng trắng phải được mã hóa dưới dạng% 20 * urlencode chuỗi truy vấn - Chuỗi truy vấn là phần nằm sau dấu "?" -spaces được mã hóa tốt hơn vì "+" = rawurlencode thường tương thích hơn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.