ส่วนย่อยของ URL และการเปลี่ยนเส้นทาง 302


137

เป็นที่ทราบกันดีว่าส่วนย่อย URL (ส่วนที่อยู่หลัง#) ไม่ได้ถูกส่งไปยังเซิร์ฟเวอร์

ฉันสงสัยว่าแฟรกเมนต์ทำงานอย่างไรเมื่อมีการเปลี่ยนเส้นทางเซิร์ฟเวอร์ (ผ่านสถานะ HTTP 302 และLocation:ส่วนหัว)

คำถามของฉันเป็นสองเท่าจริงๆ:

  1. หาก URL เดิมมีแฟรกเมนต์ ( /original.php#foo) และมีการเปลี่ยนเส้นทางไป/new.phpยังส่วนแฟรกเมนต์ของ URL เดิมจะหายไปหรือไม่ หรือบางครั้งมันถูกนำไปใช้กับ URL ใหม่?
    URL ใหม่จะ/new.php#fooอยู่ในกรณีนี้หรือไม่

  2. ไม่ว่า URL เดิมจะเป็นอย่างไรหากเซิร์ฟเวอร์เปลี่ยนเส้นทางไปยัง URL ใหม่ด้วยแฟรกเมนต์ ( /new.php#foo) แฟรกเมนต์จะได้รับ "เกียรติ" หรือไม่ หรือไม่เซิร์ฟเวอร์จริงๆมีธุรกิจไม่รบกวนการทำงานของชิ้นส่วนที่ทุกคน - และจะเบราว์เซอร์จึงไม่สนใจมันโดยเพียงแค่ไป/new.php??


1
คุณสามารถค้นหาข้อมูลจำเพาะได้จาก W3C: w3.org/TR/cuap#uriข้อ 4.1 ส่วนควรถูกเก็บรักษาไว้เมื่อเปลี่ยนเส้นทาง
Marcin

1
@Marcin: W3C TAG แนะนำที่แตกต่างกัน: lists.w3.org/Archives/Public/ietf-http-wg/2010OctDec/0504.html คำถามที่เกี่ยวข้อง: 302 Redirect ไปยัง URL สัมพัทธ์ถูกต้องหรือไม่ถูกต้อง?
hakre

คำตอบ:


136

อัปเดต 2557- มิ.ย. -27 :

RFC 7231, Hypertext Transfer Protocol (HTTP / 1.1): ความหมายและเนื้อหาได้รับการเผยแพร่เป็นมาตรฐานที่เสนอ จากChangelog :

ไวยากรณ์ของฟิลด์ส่วนหัวตำแหน่งถูกเปลี่ยนเพื่ออนุญาตให้มีการอ้างอิง URI ทั้งหมดรวมถึงการอ้างอิงและแฟรกเมนต์แบบสัมพัทธ์พร้อมกับคำชี้แจงบางประการเกี่ยวกับเวลาที่การใช้แฟรกเมนต์ไม่เหมาะสม (ข้อ 7.1.2)

ประเด็นสำคัญจากหัวข้อ 7.1.2 สถานที่ :

หากค่าตำแหน่งที่ระบุในการตอบสนอง 3xx (การเปลี่ยนเส้นทาง) ไม่มีคอมโพเนนต์แฟรกเมนต์เอเจนต์ผู้ใช้จะต้องประมวลผลการเปลี่ยนเส้นทางราวกับว่าค่าสืบทอดองค์ประกอบแฟรกเมนต์ของการอ้างอิง URI ที่ใช้ในการสร้างเป้าหมายคำขอ (เช่นการเปลี่ยนเส้นทางสืบทอด ส่วนอ้างอิงของต้นฉบับถ้ามี)

ตัวอย่างเช่นคำขอ GET ที่สร้างขึ้นสำหรับการอ้างอิง URI " http://www.example.org/~tim " อาจส่งผลให้มีการตอบกลับ 303 (ดูอื่น ๆ ) ที่มีฟิลด์ส่วนหัว:

Location: /People.html#tim

ซึ่งแนะนำให้ตัวแทนผู้ใช้เปลี่ยนเส้นทางไปที่ " http://www.example.org/People.html#tim "

ในทำนองเดียวกันคำขอ GET ที่สร้างขึ้นสำหรับการอ้างอิง URI " http://www.example.org/index.html#larry " อาจทำให้ได้รับการตอบกลับ 301 (ย้ายถาวร) ที่มีฟิลด์ส่วนหัว:

Location: http://www.example.net/index.html

ซึ่งแนะนำให้ตัวแทนผู้ใช้เปลี่ยนเส้นทางไปที่ " http://www.example.net/index.html#larry " โดยคงรักษาตัวระบุแฟรกเมนต์ดั้งเดิมไว้

สิ่งนี้ควรตอบคำถามของคุณได้อย่างชัดเจน

อัปเดต END

นี่คือการเปิด (ไม่ระบุ) ปัญหากับสเปค HTTP ปัจจุบัน ได้รับการแก้ไขใน 2 ประเด็นของคณะทำงาน IETF httpbis :

# 6 อนุญาตให้มีชิ้นส่วนในLocationส่วนหัว # 43 กล่าวว่า:

ฉันเพิ่งทดสอบสิ่งนี้กับเบราว์เซอร์ต่างๆ

  • Firefox และ Safari ใช้แฟรกเมนต์ในส่วนหัวของตำแหน่ง
  • Opera ใช้แฟรกเมนต์จาก URI ต้นทางเมื่อมีอยู่มิฉะนั้นแฟรกเมนต์จากตำแหน่งการเปลี่ยนเส้นทาง
  • IE (8) ละเว้นแฟรกเมนต์ในตำแหน่ง URI ดังนั้นจะใช้แฟรกเมนต์จาก URI ต้นทางเมื่อมี

ข้อเสนอ:

"หมายเหตุ: ลักษณะการทำงานเมื่อต้องรวมตัวระบุแฟรกเมนต์จาก URI ดั้งเดิมและการเปลี่ยนเส้นทางจะไม่ได้กำหนดเอเจนต์ผู้ใช้ปัจจุบันแตกต่างกันอย่างแท้จริงว่าส่วนใดมีความสำคัญมากกว่า

[... ]

ดูเหมือนว่า IE8 จะใช้ Fragment idenfitier จากLocation(พฤติกรรมที่ฉันเห็นอาจ จำกัด เฉพาะ localhost)

ดูเหมือนว่าเราจะมีพฤติกรรมที่สอดคล้องกันสำหรับ Safari / IE / Firefox / Chrome (เพิ่งทดสอบ) โดยที่ส่วนจากส่วนหัวตำแหน่งจะถูกใช้ไม่ว่า URI ดั้งเดิมจะเป็นอย่างไร

ดังนั้นผมจึงเปลี่ยนข้อเสนอของฉันในเอกสารว่าเป็นพฤติกรรมที่คาดหวัง

สิ่งนี้นำไปสู่การพิสูจน์ว่าเข้ากันได้กับเบราว์เซอร์ส่วนใหญ่และในอนาคต (เพราะในที่สุดปัญหานี้จะได้รับมาตรฐาน) คำตอบสำหรับคำถามของคุณ:

ตอบ:ส่วนย่อยจาก URL ดั้งเดิมจะถูกทิ้ง

B:ชิ้นส่วนจากLocationส่วนหัวได้รับเกียรติ


1
ฉันลืมกฎ "เขียนซ้ำ" บางส่วนที่ฉันตั้งไว้ในเซิร์ฟเวอร์ HTTP ซึ่งอาจนำไปใช้เป็นการเปลี่ยนเส้นทาง 301 ด้วยเหตุนี้ IE ยังคงสูญเสียตัวระบุแฟรกเมนต์เนื่องจากเมื่อคุณมีการเปลี่ยนเส้นทางหลายครั้งส่วนที่กำหนดโดยการเปลี่ยนเส้นทางครั้งแรกจะกลายเป็นส่วนหนึ่งของURI ต้นทางในวินาที
Eugene Yokota

โอเปร่า 12.12 ให้เกียรติชิ้นส่วนในส่วนหัวตำแหน่งเมื่อมีอยู่
แพะ

4
ในเวอร์ชันปัจจุบันของทั้ง Chrome และ Firefox: Aไม่เป็นความจริง ใน Firefox เวอร์ชันปัจจุบัน: Bไม่เป็นความจริง ในขณะนี้หากคุณต้องใช้แฮช (เช่นการใช้การกำหนดเส้นทางของ Backbone) ดูเหมือนว่าการเปลี่ยนเส้นทางโดยใช้จาวาสคริปต์เป็นทางเลือกเดียวที่แท้จริงของคุณ
a.real.human.being

บล็อกที่ยกมาดูเหมือนจะขัดแย้งในตัวเอง ขั้นแรกจะระบุว่า "IE (8) ละเว้นแฟรกเมนต์ในตำแหน่ง URI ดังนั้นจะใช้แฟรกเมนต์จาก URI ต้นทางเมื่อมี" จากนั้นจะระบุว่า "ดูเหมือนว่า IE8 จะใช้ตัวระบุแฟรกเมนต์จากตำแหน่ง" ครั้งแรกอ้างถึงสิ่งที่แตกต่างจากที่สองหรือไม่?
davidtbernal

B ไม่เป็นความจริงสำหรับ Chome 45.0.2454.85 B เป็นจริงสำหรับ Firefox 40.0.3
Jingguo Yao

44

Safari 5 และ IE9 และต่ำกว่าจะปล่อยส่วนของ URI ดั้งเดิมหากเกิดการเปลี่ยนเส้นทาง HTTP / 3xx หากส่วนหัว Location บนการตอบสนองระบุแฟรกเมนต์จะถูกใช้

IE10 +, Chrome 11+, Firefox 4+ และ Opera จะ "แนบ" ส่วนของ URI ดั้งเดิมทั้งหมดหลังจากทำตามการเปลี่ยนเส้นทาง 3xx

หน้าการทดสอบ: http://www.webdbg.com/test/redir/fragment/

ดูการอภิปรายเพิ่มเติมเกี่ยวกับปัญหานี้ได้ที่http://blogs.msdn.com/b/ieinternals/archive/2011/05/17/url-fragments-and-redirects-anchor-hash-missing.aspx


2
จริงๆแล้ว IE10 ยังคงทำงานแตกต่างจาก Firefox และ Chrome เวอร์ชันล่าสุด ดูเหมือนว่าจะเก็บส่วนย่อยจาก URL ต้นทางในกรณีของการเปลี่ยนเส้นทางแบบธรรมดา และหากการเปลี่ยนเส้นทางLocationมีส่วนย่อยก็จะเก็บไว้อย่างถูกต้อง แต่ถ้าการเปลี่ยนเส้นทางLocationด้วยแฟรกเมนต์ไปผ่านการเปลี่ยนเส้นทาง 3xx อื่นมันจะละเว้นแฟรกเมนต์จากการเปลี่ยนเส้นทางครั้งแรกอย่างลึกลับซึ่งไม่สอดคล้องกับพฤติกรรมก่อนหน้า 2 อย่าง Chrome และ Firefox เก็บรักษาไว้อย่างสม่ำเสมอ
odony

ฉันยืนยันว่าคุณถูกต้อง ดูลิงก์การทดสอบขั้นสุดท้ายในหน้านี้: webdbg.com/test/redir/fragment
EricLaw

11

เพียงเพื่อแจ้งให้คุณทราบคุณจะพบข้อมูลจำเพาะที่เหมาะสมที่นี่ โดย w3c กำหนดว่าควรปฏิบัติอย่างไร: http://www.w3.org/TR/cuap#uri - ข้อ 4.1 - ดูด้านล่าง:

เมื่อทรัพยากร (URI1) ถูกย้ายการเปลี่ยนเส้นทาง HTTP สามารถระบุตำแหน่งใหม่ (URI2)

หาก URI1 มีตัวระบุแฟรกเมนต์ #frag เป้าหมายใหม่ที่ตัวแทนผู้ใช้ควรพยายามเข้าถึงคือ URI2 # frag หาก URI2 มีตัวระบุแฟรกเมนต์อยู่แล้ว #frag จะต้องไม่ต่อท้ายและเป้าหมายใหม่คือ URI2

ผิด: เอเจนต์ผู้ใช้ปัจจุบันส่วนใหญ่ใช้การเปลี่ยนเส้นทาง HTTP แต่ไม่ผนวกตัวระบุแฟรกเมนต์เข้ากับ URI ใหม่ซึ่งโดยทั่วไปทำให้ผู้ใช้สับสนเพราะลงท้ายด้วยทรัพยากรที่ไม่ถูกต้อง

อ้างอิง:

การเปลี่ยนเส้นทาง HTTP อธิบายไว้ในส่วนที่ 10.3 ของข้อกำหนด HTTP / 1.1 [RFC2616] ลักษณะการทำงานที่ต้องการมีอธิบายโดยละเอียดใน "การจัดการตัวระบุส่วนย่อยใน URL ที่เปลี่ยนเส้นทาง" [RURL] คำว่า "Persistent Uniform Resource Locator (PURL)" กำหนด URL (กรณีพิเศษของ URI) ที่ชี้ไปยัง URL อื่นผ่านการเปลี่ยนเส้นทาง HTTP สำหรับข้อมูลเพิ่มเติมโปรดดูที่ "Persistent Uniform Resource Locators" [PURL] ตัวอย่าง:

สมมติว่าผู้ใช้ร้องขอทรัพยากรที่ http://www.w3.org/TR/WD-ruby/#changesและเซิร์ฟเวอร์เปลี่ยนเส้นทางตัวแทนของผู้ใช้เพื่อhttp://www.w3.org/TR/ruby/ ก่อนที่จะเรียกว่าหลัง URI เบราว์เซอร์ควรผนวก #changes ระบุชิ้นส่วนไป: http://www.w3.org/TR/ruby/#changes


0

กำลังโพสต์ปัญหาที่คล้ายกันกับวิธีแก้ปัญหาที่ฉันต้องเผชิญ

หวังว่าจะช่วยให้ผู้ที่มีข้อกำหนดคล้ายกันpreserving hash in IEสำหรับการเปลี่ยนเส้นทาง 302

การเพิ่มส่วนสำคัญของคำตอบแทนการเชื่อมโยงเพียงอย่างเดียว

เราใช้การSiteMinderพิสูจน์ตัวตนในแอปพลิเคชันของเรา

ฉันคิดว่าหลังจากการตรวจสอบที่ประสบความสำเร็จSiteMinderจะทำ302 redirectionกับผู้ใช้ร้องขอหน้าแอพลิเคชันโดยใช้แบบฟอร์มการเข้าสู่ระบบของตัวแปรที่ซ่อนอยู่value (ที่จะเก็บผู้ใช้ร้องขอ URL /myapp/- without hash fragmentเพราะมันจะไม่ถูกส่งไปยังเซิร์ฟเวอร์) redirectที่มีชื่อคล้ายกับ แบบฟอร์มตัวอย่างด้านล่าง

แบบฟอร์มเข้าสู่ระบบตัวอย่าง

เนื่องจากค่าredirectตัวแปรที่ซ่อนอยู่มีเฉพาะโดยไม่มีส่วนแฮชและเป็นการเปลี่ยนเส้นทาง 302 ส่วนแฮชจะถูกลบโดยอัตโนมัติโดย IE ก่อนที่จะมาถึงแอปพลิเคชันของเราและวิธีแก้ปัญหาใด ๆ ที่เราพยายามในรหัสแอปพลิเคชันของเราไม่ได้ผล/myapp/

IE การเปลี่ยนเส้นทางไป/myapp/เท่านั้นและจะมีการเชื่อมโยงไปถึงบนหน้าแรกของการเริ่มต้นของ https://ourapp.com/myapp/#/homeapp

เสียเวลาเกือบวันเพื่อคิดหาพฤติกรรมนี้

วิธีแก้ปัญหาคือ:

มีการเปลี่ยนแปลงรูปแบบการเข้าสู่ระบบตัวแปรที่ซ่อนอยู่ ( redirect) ค่าที่จะถือส่วนกัญชาโดยท้ายwindow.location.hashพร้อมกับค่าที่มีอยู่ คล้ายกับโค้ดด้านล่าง

$(function () {
  var $redirect = $('input[name="redirect"]');
  $redirect.val($redirect.val() + window.location.hash);
});

หลังจากการเปลี่ยนแปลงนี้redirectตัวแปรที่ซ่อนอยู่จะจัดเก็บค่า URL ที่ผู้ใช้ร้องขอเป็น/myapp/#/pending/requestsและSiteMinderกำลังเปลี่ยนเส้นทางไปยัง/myapp/#/pending/requestsใน IE

Chrome, Firefox and IEการแก้ปัญหาดังกล่าวข้างต้นทำงานได้ดีในทุกสามเบราว์เซอร์

ขอบคุณ @AlexFord สำหรับคำอธิบายโดยละเอียดและการแก้ปัญหานี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.