เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ · URL ตัวเข้ารหัสและตัวถอดรหัส
ทำไม + กลายเป็นช่องว่างเมื่อคุณถอดรหัสสตริงการสืบค้น และเมื่อไม่เป็นเช่นนั้น
· มันทำงานอย่างไร
การเข้ารหัส URL javascript นักพัฒนาเวิร์กโฟลว์
การที่ + หมายถึงช่องว่างนั้นขึ้นอยู่กับตัวถอดรหัสที่คุณเรียกใช้ โพสต์นี้จะอธิบายวิธีที่ decodeURIComponent, URLSearchParams และเฟรมเวิร์กเซิร์ฟเวอร์แต่ละการปฏิบัติ + และวิธีหลีกเลี่ยงการเปลี่ยนข้อดีที่แท้จริงให้เป็นช่องว่าง
ทำไม + กลายเป็นช่องว่างเมื่อคุณถอดรหัสสตริงการสืบค้น และเมื่อไม่เป็นเช่นนั้น
การส่งแบบฟอร์ม HTML ใช้รูปแบบ application/x-www-form-urlencoded โดยที่ช่องว่างจะกลายเป็นเครื่องหมายบวก เซิร์ฟเวอร์ที่ได้รับ name=Alice+Smith จะแทนที่แต่ละเครื่องหมายบวกด้วยช่องว่างก่อนที่จะแตกค่า เมื่อเครื่องหมายบวกจริงอยู่ในข้อมูล เช่น ในการคำนวณ 5+3 จะมาถึงเซิร์ฟเวอร์เป็น 5 3 หลังจากขั้นตอนการถอดรหัสแบบฟอร์ม การเปลี่ยนแปลงที่มองไม่เห็นนี้เป็นรากฐานของความสับสน
การถอดรหัส JavaScript จะให้ผลลัพธ์ที่แตกต่างกัน ขึ้นอยู่กับฟังก์ชันที่คุณใช้ URLSearchParams ถือว่าเครื่องหมายบวกเป็นช่องว่าง ซึ่งตรงกับพฤติกรรมของเซิร์ฟเวอร์ แต่ decodeURIComponent ทิ้งไว้โดยไม่ถูกแตะต้องและปฏิบัติต่อมันอย่างแท้จริง ความไม่สมดุลระหว่างฟังก์ชันนี้คือสาเหตุที่อินพุตเดียวกันถอดรหัสต่างกัน นักพัฒนาคาดหวังว่าตัวถอดรหัสทั้งสองจะให้ผลลัพธ์ที่เหมือนกันและพบว่าไม่ได้เป็นเช่นนั้น
การเข้ารหัสสองตัวที่มีลักษณะเหมือนกัน — RFC 3986 การเข้ารหัสเปอร์เซ็นต์เทียบกับแอปพลิเคชัน/x-www-form-urlencoded
มาตรฐานการเข้ารหัสสองมาตรฐานมีลักษณะคล้ายกันแต่ทำงานต่างกัน RFC 3986 กำหนดการเข้ารหัสเปอร์เซ็นต์: อักขระใดๆ จะกลายเป็น %HH พื้นที่กลายเป็น %20 มาตรฐาน application/x-www-form-urlencoded เพิ่มชวเลข: ช่องว่างสามารถบวกได้ ใช้งานได้ทั้งในบริบทของแบบฟอร์ม แต่เครื่องหมายบวกเป็นทางเลือกและเฉพาะเจาะจงกับมาตรฐานนั้น เป็นโดเมนที่แตกต่างกันและมีลักษณะคล้ายกัน
การเรียก decodeURIComponent ใช้การถอดรหัส RFC 3986 เท่านั้น อ่านว่า %20 เป็นช่องว่าง และบวกเป็นเครื่องหมายบวก URLSearchParams ใช้กฎการถอดรหัสแบบฟอร์ม โดยเปอร์เซ็นต์การหลบหนีจะกลายเป็นอักขระ และเครื่องหมายบวกจะกลายเป็นช่องว่าง ฟังก์ชันทั้งสองแก้ปัญหาเดียวกันในโดเมนที่ต่างกัน การผสมพวกมันจะทำให้ค่าบวกที่แท้จริงหายไป หรือช่องว่างกลายเป็นค่าบวกและไม่สามารถแปลงได้
decodeURIComponent ออก + เพียงอย่างเดียว; URLSearchParams เปลี่ยนให้เป็นช่องว่าง — เปรียบเทียบพฤติกรรม JavaScript สองรายการ
พฤติกรรมของเซิร์ฟเวอร์แตกต่างกันไป ซึ่งทำให้เกิดปัญหา Rails หรือ Django จะใช้กฎของแบบฟอร์มโดยอัตโนมัติ: บวกกลายเป็นช่องว่าง แต่การแยกและถอดรหัสสตริงการสืบค้นดิบด้วยตนเองด้วยตัวถอดรหัส URL จะทำให้บวกเหมือนเดิม ค่าเดียวกันที่ประมวลผลโดยเฟรมเวิร์กที่ต่างกันจะให้ผลลัพธ์ที่แตกต่างกัน รหัสเซิร์ฟเวอร์มักจะจัดการสิ่งนี้โดยปริยาย โดยซ่อนปัญหาไว้จนกว่าคุณจะเขียนตัวถอดรหัสแบบกำหนดเอง
ตัวอย่าง: ช่องหมายเลขโทรศัพท์จะเก็บ +1-555-0100 โดยมีเครื่องหมายบวกเป็นรหัสประเทศ แบบฟอร์ม HTML เข้ารหัสเป็น %2B1-555-0100 เพราะ JavaScript เข้ารหัสบวกเป็น %2B เซิร์ฟเวอร์ได้รับสิ่งนี้ หากใช้การถอดรหัสแบบฟอร์ม %2B จะกลายเป็นบวกและค่านั้นถูกต้อง หากพร็อกซีตัดการเข้ารหัส การเรียก decodeURIComponent กับผลลัพธ์จะสร้าง +1-555-0100 แต่ละชั้นจะถอดรหัสหนึ่งครั้ง
สิ่งที่เซิร์ฟเวอร์ทำ — ลักษณะการทำงานของเฟรมเวิร์กทั่วไปในสตริงการสืบค้นและเนื้อหาคำขอ ซึ่งอธิบายไว้ในเงื่อนไขทั่วไป
JavaScript สามารถเข้ารหัสค่าโดยใช้ encodeURIComponent เมื่อให้ a+b จะได้ a%2Bb เมื่อสตริงที่เข้ารหัสนั้นไปถึงเซิร์ฟเวอร์หรือตัวถอดรหัสที่รับรู้ฟอร์ม %2B จะถอดรหัสเป็นบวกและผลลัพธ์ถูกต้อง หากคุณเข้ารหัสโดยใช้กฎของแบบฟอร์มแทน การเว้นวรรคจะกลายเป็นเครื่องหมายบวก และเครื่องหมายบวกจริงจะกลายเป็น %2B ไม่ว่าจะด้วยวิธีใด การเข้ารหัสจะสร้าง%2Bb การตีความขึ้นอยู่กับกฎการถอดรหัสที่ใช้
ทดสอบการเดินทางไปกลับ: เริ่มต้นด้วย a+b เข้ารหัสด้วย encodeURIComponent เพื่อรับ%2Bb ถอดรหัส a%2Bb ด้วย decodeURIComponent และกู้คืน a+b ส่ง a+b ไปยัง URLSearchParams: ถือว่าบวกเป็นช่องว่าง ทำให้เกิด a b ส่ง%2Bb ไปที่ URLSearchParams เพื่อรับ a+b กลับ อินพุตเดียวกันที่ถอดรหัสได้สองวิธีจะสร้างเอาต์พุตที่แตกต่างกัน ขึ้นอยู่กับตัวถอดรหัสที่คุณใช้
ตัวอย่างการทำงาน: 'a+b' และ 'a%2Bb' ผ่านตัวถอดรหัสทั้งสอง - ผลลัพธ์สี่รายการในตาราง
ข้อผิดพลาดทั่วไปจะตามมาโดยตรง นักพัฒนาถอดรหัสด้วย decodeURIComponent และสงสัยว่าเหตุใดข้อมูลในแบบฟอร์มขาเข้าจึงมีเครื่องหมายบวกจริง พวกเขาควรใช้ URLSearchParams ในทางกลับกัน บางคนใช้ URLSearchParams เมื่อควรใช้ decodeURIComponent และทุกตัวอักษรบวกจะหายไป การเข้ารหัสสองครั้งจะสร้าง %252B ซึ่งต้องใช้คู่ตัวเข้ารหัส-ตัวถอดรหัสที่ตรงกันจึงจะถอดรหัสได้อย่างถูกต้อง
ข้อผิดพลาดอีกประการหนึ่งคือการสร้างสตริงการสืบค้นด้วยตนเองเป็น ?q=value โดยไม่มีการเข้ารหัส เครื่องหมายและหรือเท่ากับใดๆ ในค่าจะสร้างพารามิเตอร์ใหม่โดยไม่แจ้งให้ทราบ เบราว์เซอร์ไม่ได้คาดเดาการต่อข้อมูลเป็นครั้งที่สอง มันปฏิบัติต่อผลลัพธ์ตามรูปแบบที่ถูกต้อง การเข้ารหัสโดยเจตนาด้วย encodeURIComponent เท่านั้นที่จะป้องกันสิ่งนี้ URL ตัวเข้ารหัสและตัวถอดรหัสแสดงทั้งสามฟังก์ชัน โดยเผยให้เห็นว่าแต่ละฟังก์ชันสร้างอะไร
ข้อผิดพลาดทั่วไป — ถอดรหัสสองครั้ง หรือเข้ารหัสช่องว่างเป็น + ในส่วนของเส้นทาง
กฎการเข้ารหัสแบบฟอร์มเรียกว่า application/x-www-form-urlencoded เนื่องจากกฎนี้อธิบายส่วนหัวเนื้อหาประเภทเนื้อหาคำขอ HTTP แบบฟอร์ม HTML ที่ไม่มีการอัปโหลดไฟล์จะส่งเนื้อหาในรูปแบบนี้ สตริงการสืบค้นใน URL ก็ใช้แบบแผนนี้เช่นกัน แม้ว่าในทางเทคนิคแล้วสตริงดังกล่าวจะไม่มีมาตรฐานการเข้ารหัสอย่างเป็นทางการก็ตาม ข้อกำหนด URL ถือว่าแบบสอบถามเป็นแบบทึบ บวกความหมายไม่ได้รับคำสั่ง แต่ในเว็บแอปพลิเคชัน บวกมักจะหมายถึงพื้นที่
เพื่อรับประกันการทำงานที่ถูกต้อง ให้เข้ารหัสอย่างจงใจและถอดรหัสด้วยฟังก์ชันที่ตรงกัน หากคุณเข้ารหัสด้วย encodeURIComponent ให้ถอดรหัสด้วย decodeURIComponent หากอ่านข้อมูลแบบฟอร์ม HTML หรือขอเนื้อหาในรูปแบบแบบฟอร์ม ให้ใช้ URLSearchParams อย่าคาดเดาจากรูปลักษณ์ภายนอก สตริงเช่น a+b นั้นไม่ชัดเจน ตัวถอดรหัสไม่สามารถใช้แทนกันได้
สิ่งนี้ไม่ครอบคลุมถึง - ข้อมูลแบบฟอร์มหลายส่วนและเนื้อหาคำขอ JSON
ข้อมูลแบบฟอร์มหลายส่วน เนื้อหาคำขอ JSON และมาตรฐานอื่นๆ มีกฎการเข้ารหัสแยกต่างหาก JSON ไม่ใช้เครื่องหมายบวกสำหรับช่องว่างหรือการเข้ารหัสเปอร์เซ็นต์ มันใช้การหลบหนีแบบ Unicode Multipart ใช้ขอบเขตที่แตกต่างกัน บทความนี้ครอบคลุมถึงสตริงแบบสอบถามและเนื้อความที่เข้ารหัสแบบฟอร์มเท่านั้น เนื่องจากเป็นที่ที่ความคลุมเครือบวกปรากฏขึ้น ตรวจสอบส่วนหัว Content-Type และ RFC ที่กำหนดเสมอ
เข้ารหัสเครื่องหมายบวกตามตัวอักษรเป็น %2B ทุกครั้งเมื่ออยู่ในค่าคิวรี URL ตัวเข้ารหัสและตัวถอดรหัสแสดงให้เห็นว่า Plus ได้รับการปกป้องอย่างไรในฐานะ %2B ในโหมดส่วนประกอบ โดยแยกจากช่องว่างซึ่งกลายเป็น %20 ส่ง a+b และ a%2Bb ผ่านแต่ละโหมด จากนั้นตรวจสอบผลลัพธ์ การเปรียบเทียบนั้นแสดงให้เห็นว่าเหตุใดอินพุตเดียวกันจึงถอดรหัสต่างกัน ความแตกต่างคือพฤติกรรมที่ถูกต้องของสองมาตรฐานที่แตกต่างกัน
ประเด็นสำคัญ: เข้ารหัสเครื่องหมายบวกเป็น %2B เสมอ — วิธีที่ตัวเข้ารหัสและตัวถอดรหัส URL แสดงลักษณะของค่าเป็นค่าการค้นหาที่เข้ารหัสเปอร์เซ็นต์อย่างไร
ประเด็นสำคัญ: เครื่องหมายบวกในสตริงแบบสอบถามคือรูปแบบการเข้ารหัสชวเลขสำหรับช่องว่าง ไม่ใช่เครื่องหมายบวกตามตัวอักษร เว้นแต่ว่าจะมาจากการเข้ารหัสที่ป้องกันเป็น %2B ตัวถอดรหัสผิดจะสูญเสียการป้องกันนั้น URLSearchParams ปลอดภัยที่สุดใน JavaScript สมัยใหม่; มันจัดการการเข้ารหัสแบบฟอร์มและให้การเข้าถึงพารามิเตอร์ที่มีชื่อ สำหรับสตริงดิบ encodeURIComponent จะปกป้องทุกสิ่ง decodeURIComponent ตีความ %20 และเปอร์เซ็นต์ แต่ถือว่าบวกตามตัวอักษร
ทดสอบสิ่งนี้: สร้าง ?x=a+b ด้วยมือและวางลงใน URL ตัวเข้ารหัสและตัวถอดรหัส ตรวจสอบและดู URLSearchParams แยกออกเป็นพารามิเตอร์ x ด้วยค่า a b วาง ?x=a%2Bb และดูค่า a+b ใช้ encodeURIComponent เพื่อสร้าง URL และเปรียบเทียบ การยืนยันด้วยภาพนั้นทำให้กฎมีความกระจ่างขึ้น: กฎของแบบฟอร์มใช้เครื่องหมายบวก การเข้ารหัสเปอร์เซ็นต์ใช้ %20 การผสมกฎเหล่านี้เป็นสาเหตุว่าทำไมเครื่องหมายบวกจึงหายไปในอวกาศ