อะไรคือความแตกต่างระหว่างURI.escape
และCGI.escape
กับสิ่งที่ฉันควรใช้
อะไรคือความแตกต่างระหว่างURI.escape
และCGI.escape
กับสิ่งที่ฉันควรใช้
คำตอบ:
มีความแตกต่างเล็ก ๆ แต่จุดสำคัญคือการที่URI.escape
ได้รับการเลิกใช้ในรูบี 1.9.2 ... เพื่อให้การใช้งานCGI::escape
หรือERB :: Util.url_encode
มีการอภิปรายยาวในทับทิมหลักสำหรับผู้ที่สนใจซึ่งยังกล่าวถึงWEBrick :: HTTPUtils.escapeและWEBrick :: HTTPUtils.escape_form
ERB::Util.url_encode
ที่เหมาะสม%20
สำหรับช่องว่าง
อะไรคือความแตกต่างระหว่างขวานกับดาบกับอันที่ฉันควรใช้ มันขึ้นอยู่กับสิ่งที่คุณต้องทำ
URI.escape
ควรจะเข้ารหัสสตริง (URL) ลงในจึงเรียกว่า " การเข้ารหัสร้อยละ "
CGI::escape
มาจากข้อมูลจำเพาะCGIซึ่งอธิบายถึงวิธีการเข้ารหัส / ถอดรหัสข้อมูลระหว่างเว็บเซิร์ฟเวอร์และแอปพลิเคชัน
ตอนนี้สมมติว่าคุณต้องหลบหนี URI ในแอปของคุณ มันเป็นกรณีการใช้งานที่เฉพาะเจาะจงมากขึ้น สำหรับสิ่งนั้นชุมชน Ruby ใช้มาURI.escape
นานหลายปี ปัญหาที่เกิดขึ้นURI.escape
คือมันไม่สามารถจัดการสเปค RFC-3896
URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog"
URI.escape
ถูกทำเครื่องหมายว่าล้าสมัย:
นอกจากนี้ URI.encode ปัจจุบันเป็น gsub ง่าย ๆ แต่ฉันคิดว่ามันควรแบ่ง URI เป็นส่วนประกอบแล้วหนีแต่ละองค์ประกอบและสุดท้ายเข้าร่วม
ดังนั้น URI.encode ปัจจุบันจึงถือว่าเป็นอันตรายและเลิกใช้แล้ว สิ่งนี้จะถูกลบออกหรือเปลี่ยนพฤติกรรมอย่างมาก
การเปลี่ยนในเวลานี้คืออะไร?
ดังที่ฉันได้กล่าวไว้ข้างต้น URI.encode ปัจจุบันผิดระดับสเป็ค ดังนั้นเราจะไม่ให้การเปลี่ยนที่แน่นอน การเปลี่ยนจะแตกต่างกันไปตามกรณีการใช้งาน
น่าเสียดายที่ไม่มีคำเพียงคำเดียวในเอกสารวิธีเดียวที่จะรู้เกี่ยวกับมันคือการตรวจสอบแหล่งที่มาหรือเรียกใช้สคริปต์ด้วยคำเตือนในระดับ verbose ( -wW2
) (หรือใช้ google-fu บางอย่าง)
บางคนเสนอให้ใช้CGI::Escape
สำหรับพารามิเตอร์การสืบค้นเนื่องจากคุณไม่สามารถหลีกเลี่ยง URI ทั้งหมด:
CGI::escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http%3A%2F%2Fgoogle.com%2Ffoo%3Fbar%3Dat%23anchor%26title%3DMy+Blog+%26+Your+Blog"
CGI::escape
ควรใช้สำหรับพารามิเตอร์การสืบค้นเท่านั้น แต่ผลลัพธ์จะตรงกับข้อมูลจำเพาะอีกครั้ง จริงๆแล้วกรณีใช้งานที่พบบ่อยที่สุดคือการหลีกเลี่ยงข้อมูลในแบบฟอร์มเช่นในขณะที่ส่งapplication/x-www-form-urlencoded
คำขอ POST
ยังกล่าวถึงWEBrick::HTTPUtils.escape
การปรับปรุงไม่มาก (อีกครั้งมันเป็นเพียงง่ายgsub
ซึ่งก็คือ IMO แม้ตัวเลือกที่แย่กว่าURI.escape
):
WEBrick::HTTPUtils.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog"
ที่ใกล้เคียงกับสเปคที่ดูเหมือนว่าจะเป็นแอดเดรสอัญมณี:
require 'addressable/uri'
Addressable::URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http://google.com/foo?bar=at#anchor&title=My%20Blog%20&%20Your%20Blog"
โปรดสังเกตว่าไม่เหมือนกับตัวเลือกก่อนหน้านี้ทั้งหมดแอดเดรสสามารถหลีกเลี่ยงได้#
และนี่เป็นพฤติกรรมที่คาดหวัง คุณต้องการเก็บ#
แฮชไว้ในพา ธ URI แต่ไม่ใช่ในเคียวรี URI
ปัญหาเดียวที่เหลือคือเราไม่ได้หลีกเลี่ยงพารามิเตอร์การสืบค้นอย่างถูกต้องซึ่งนำเราไปสู่ข้อสรุป: เราไม่ควรใช้วิธีการเดียวสำหรับ URI ทั้งหมดเนื่องจากยังไม่มีวิธีแก้ปัญหาที่สมบูรณ์แบบ (จนถึงตอนนี้) อย่างที่คุณเห็น&
ไม่ได้หลบหนีจาก "บล็อกของฉัน & บล็อกของคุณ" เราจำเป็นต้องใช้รูปแบบการหลบหนีที่แตกต่างกันสำหรับการค้นหาพารามิเตอร์ซึ่งผู้ใช้สามารถใส่อักขระที่แตกต่างที่มีความหมายพิเศษใน URL ป้อนการเข้ารหัส URL ควรใช้การเข้ารหัส URL สำหรับทุกค่าการสืบค้น "ที่น่าสงสัย" ซึ่งคล้ายกับที่ERB::Util.url_encode
ทำ:
ERB::Util.url_encode "My Blod & Your Blog"
# => "My%20Blod%20%26%20Your%20Blog""
มันเจ๋ง แต่เราต้องการ Addressable แล้ว:
uri = Addressable::URI.parse("http://www.go.com/foo")
# => #<Addressable::URI:0x186feb0 URI:http://www.go.com/foo>
uri.query_values = {title: "My Blog & Your Blog"}
uri.normalize.to_s
# => "http://www.go.com/foo?title=My%20Blog%20%26%20Your%20Blog"
สรุป:
URI.escape
หรือคล้ายกันCGI::escape
ถ้าคุณต้องการหลบหนีจากฟอร์มAddressable
เป็นหนึ่งในอัญมณีของคุณได้คุณสามารถแยกวิเคราะห์ URL เป็นครั้งแรกโดยป้อน rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse
Addressable:URL
นั้นคุณสามารถเรียกใช้วิธีการอินสแตนซ์ทั้งหมดบนมันบางทีหนึ่งในนั้นจะให้ผลลัพธ์ที่คุณต้องการ: rubydoc.info/gems/addressable/Addressable/URI
URI.escape ใช้พารามิเตอร์ตัวที่สองที่ช่วยให้คุณทำเครื่องหมายสิ่งที่ไม่ปลอดภัย ดู APIDock:
CGI::escape
เป็นสิ่งที่ดีสำหรับการหลบหนีส่วนข้อความเพื่อให้สามารถใช้ในพารามิเตอร์การค้นหา URL (สตริงหลังจาก '?') ตัวอย่างเช่นถ้าคุณต้องการมีพารามิเตอร์ที่มีอักขระสแลชใน url คุณ CGI :: escape สตริงนั้นก่อนแล้วจึงใส่เข้าไปใน url
อย่างไรก็ตามใน Rails คุณอาจไม่ได้ใช้งานโดยตรง โดยปกติแล้วคุณจะใช้hash.to_param
ซึ่งจะใช้CGI::escape
ภายใต้ประทุน
URI::escape
เป็นสิ่งที่ดีสำหรับการหลบหนี URL ซึ่งไม่ได้หลบหนีอย่างถูกต้อง ตัวอย่างเช่นบางเว็บไซต์แสดง URL ที่ไม่ถูกต้อง / ไม่ใช้ Escape ในแท็ก anchor หากโปรแกรมของคุณใช้ URL เหล่านี้เพื่อดึงทรัพยากรเพิ่มเติม OpenURI จะบ่นว่า URL นั้นไม่ถูกต้อง คุณต้องทำURI::escape
สิ่งเหล่านี้เพื่อให้เป็น URL ที่ถูกต้อง ดังนั้นจึงใช้เพื่อหลีกเลี่ยงสตริง URI ทั้งหมดเพื่อให้เหมาะสม ในคำพูดของฉัน URI :: unescape ทำให้ url สามารถอ่านได้โดยมนุษย์และ URI :: escape ทำให้ใช้ได้กับเบราว์เซอร์
นี่เป็นคำศัพท์ธรรมดาของผมและรู้สึกอิสระที่จะแก้ไขให้ถูกต้อง
ข้อแตกต่างคือ URI.escape ไม่ทำงาน ...
CGI.escape"/en/test?asd=qwe"
=> "%2Fen%2Ftest%3Fasd%3Dqwe"
URI.escape"/en/test?asd=qwe"
=> "/en/test?asd=qwe"
CGI.escape ใช้เพื่อหลีกเลี่ยงค่า URL ในสตริงการสืบค้น ตัวละครทั้งหมดที่ไม่ตกอยู่ใน ALPHA, DIGIT, '_', '-', '.' และ '' ชุดอักขระถูกหลีกหนี
แต่นั่นจะทำให้ URL ไม่ถูกต้องเนื่องจาก URL ต้องมี '/', ':', '?', '[', '&', '=', และ ';' อาจจะมากกว่านั้นที่ฉันไม่สามารถคิดถึงหัวของฉันได้
URI.escape ปล่อยให้อักขระ URL เหล่านั้นอยู่คนเดียวและพยายามค้นหาคีย์สตริงการสืบค้นและค่าที่จะหลบหนี อย่างไรก็ตามสิ่งนี้ไม่สามารถพึ่งพาได้จริง ๆ เนื่องจากค่าสามารถมีอักขระทุกชนิดที่ป้องกันการหลบหนีได้ง่าย โดยทั่วไปมันสายเกินไป แต่ถ้า URL สามารถขึ้นอยู่กับว่าง่าย (ไม่มี '&' s และ '=' s ฯลฯ ในค่า) ฟังก์ชั่นนี้อาจถูกใช้เพื่อหลบหนีบางทีตัวอักษรที่อ่านไม่ได้หรือผิดกฎหมาย
โดยทั่วไป - ใช้ CGI.escape บนคีย์และค่าของแต่ละบุคคลก่อนที่จะเข้าร่วมพวกเขาด้วย '&' และเพิ่มพวกเขาหลังจาก '?'
CGI.escape ไม่ทำงานกับ OpenProject API มันเข้ารหัส [], และไม่ใช่เครื่องหมาย + ฉันแฮ็คสิ่งนี้ด้วยกันซึ่งดูเหมือนจะใช้งานได้จนถึง API ของ OpenProject แต่ฉันแน่ใจว่ามันหายไป อาจเป็นไปได้ว่าไม่ดีเท่า URI.escape แต่จะไม่ทำให้เกิดข้อผิดพลาดที่ล้าสมัย
class XXX
def self.encode(path)
path, query = path.split("?", 2)
return path if query.nil?
query = CGI.escape(query).gsub("%3A", ":").gsub("%3D","=").gsub("%5B","[").gsub("%5D","]").gsub("%2C",",").gsub("+","%20")
return [path,query].join("?")
end
end
XXX.encode("http://test.com/some/path?query=[box: \"cart\"]")
URI.encode("http://test.com/some/path?query=[box: \"cart\"]")
เอาต์พุตทั้งสอง:
=> " http://test.com/some/path?query=urlbox:%20%22cart%22] "
=> " http://test.com/some/path?query=urlbox:%20 % 22cart% 22] "