应答3-重定向(redirect_to)

本文深入探讨了Rails框架中重定向的实现方式与应用场景,通过一个简单的博客应用示例,展示了如何正确使用重定向来改善用户体验并确保应用逻辑的正确执行。
一个HTTP redirect 被从服务端发送给客户端,以应答一个请求。它会说,“我不能处
理这个请求,但这儿有些人能处理”。Redirect 应答包括一个URL,它是客户端应该试着下
次发送同样的状态信息给这个redirect,而不管它是持久的(状态码301)还是临时的(状态码
307)。有时,当web 页面被重新改编时,redirect 会被使用;访问旧位置页面的客户端将被
引到页面的新位置。
Redirect 背后由web 浏览器进行处理。通常,你只知道重定向稍微有些延迟,并且你看
到的页面的URL 将被从你的请求修改。最后一点很重要—直到浏览器关注它,来自于服务端
的redirect 动作与最终你手工地输入目的URL 是一样的。
当写well-behaved Web 应用程序时,关掉redirect 是很重要的。
让我们看个简单的博客应用程序,它支持评论,我们的应用程序应该重新显示文章,新
的评论在尾部。下面是代码。
class BlogController
def display
@article = Article.find(params[:id])
end
def add_comment
@article = Article.find(params[:id])
comment = Comment.new(params[:comment])
@article.comments << comment
if @article.save
flash[:note] = "Thank you for your valuable comment"
else
flash[:note] = "We threw your worthless comment away"
end
# DON'T DO THIS
render(:action => 'display')
end
end
这儿很明显故意地在一个评论之后显示文章。要做到这点,开始在add_comment()方法
结束时调用render(:action=>’display’)。这会提交显示“视图”,显示最终用户更新的
文章。但从浏览器角度想想。它发送了一个尾部为blog/add_comment 的URL,并且取回了索
引列表。直到浏览器被连接,当前URL 的尾部还是blog/add_comment。这意味着如果用户点
击刷新(或许是想看看否有其它人的评论),add_commandt URL 将被再次发送给应用程序。用
户的目的是刷新显示,但应用程序看到了一个被添加到其它comment 上的请求。
在这些情况下,正确的方式是在index 列表中显示添加的评论,并将其重定向给浏览器
的display“动作”。我使用Rails 的redirect_to()方法来做。如果用户随后刷新浏览器,
它会简单地调用display“动作”,并不会添加其它的评论。
def add_comment
@article = Article.find(params[:id])
comment = Comment.new(params[:comment])
@article.comments << comment
if @article.save
flash[:note] = "Thank you for your valuable comment"
else
flash[:note] = "We threw your worthless comment away"
end
redirect_to(:action => 'display')
end
Rails 也有一个简单但强大的重定向机制。它可以重定向到给出的“控制器”(传递参数)
内的“动作”,或重定向到当前服务端的一个URL,或重定向到一个任意的URL,让我们依次
看看这三种形式。
1、redirect_to 重定向一个“动作”
redirect_to(options...) 基于选项哈希表内的值发关一个临时重定向给浏览器。目标
URL 使用url_for()生成,所以redirect_to()格式有Rails“路由器”代码在背后支持。可
查阅280 页16.3 节。
2、redirect_to 重定向到应用程序内的一个固定路径。
redirect_to(path) 重定向到给出的路径。用前导“/”开头的路径,相对于协议,主机,
当前请求的端口。这个方法不会URL 上完成任何的重写工作,所以它不应该被用于创建,期
望连接到应用程序内一个“动作”的路径。
def save
order = Order.new(params[:order])
if order.save
redirect_to :action => "display"
else
session[:error_count] ||= 0
session[:error_count] += 1
if session[:error_count] < 4
flash[:notice] = "Please try again"
else
# Give up -- user is clearly struggling
redirect_to("/help/order_entry.html")
end
end
end
3、redirect_to 重定向到一个有绝对路径的URL。
redirect_to(url) 重定向到一个给定的完整的URL,它必须用一个协议名字来开头(如
http://)。
def portal_link
link = Links.find(params[:id])
redirect_to(link.url)
end
缺省情况下,所有重定向都是临时性的(它们只影响到当前请求)。当重定向一个URL 时,
你或许是想得到永续的重定向。在这种情况下,设置“应答头”内的状态。
headers["Status"] = "301 Moved Permanently"
redirect_to("http://my.new.home")
因为重定向方法发送应答给浏览器,同样的规则也适用于提交方法—你可发一个请求。
ICMP(Internet Control Message Protocol)即互联网控制报文协议,是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。ICMP重定向是ICMP控制报文中的一种,在特定情况下,当路由器检测到一台机器使用的是非优化路由时,会向主机发送ICMP重定向报文,使主机走优化路由 [^2]。 #### 工作原理 当路由器接收到主机发送的数据报,发现该数据报的目标地址存在更优的下一跳路由器时,路由器会将数据报正常转发,并同时向源主机发送一个ICMP重定向报文。这个报文中包含了更优的下一跳路由器的IP地址。主机收到该ICMP重定向报文后,会更新自己的路由表,将去往该目标地址的下一跳路由器地址修改为报文中所指示的地址 [^3]。 #### 示例说明 假设主机PC要访问网络192.168.3.0/24,它将数据报发送给默认网关路由器R1。当路由器R1收到此ARP请求包后,它首先用ARP应答包回答主机PC的ARP请求(通知主机PC自己的E0接口的MAC地址),然后将此ICMP请求转发到路由器R2的E0接口(192.168.1.254),前提是路由器R1正确配置了到网络192.168.3.0/24的路由。此外,路由器R1还要发送一个ICMP重定向消息给主机PC,通知主机PC对于其请求的地址的网关是192.168.1.254 [^4]。 #### 作用 ICMP重定向的主要作用是优化网络中数据的传输路径。当主机的路由选择不是最优时,通过ICMP重定向机制,主机可以及时调整路由,从而减少数据传输的延迟和网络拥塞,提高网络的整体性能和效率 [^3]。 #### 潜在风险 ICMP重定向也存在一定的安全风险,可能会被攻击者利用进行ICMP重定向攻击。攻击者可以伪造ICMP重定向报文,诱使主机将数据报发送到恶意的下一跳地址,从而实现中间人攻击等目的。在许多情况下,禁用ICMP重定向是防止这类攻击的最简单且最有效的方式。大多数操作系统和路由器都允许管理员禁用ICMP重定向消息,这样即使攻击者尝试发送伪造的重定向消息,主机和路由器也不会处理它们 [^1][^3]。 ### 代码示例 以下是一个简单的Python示例,使用`scapy`库来模拟发送和接收ICMP重定向报文: ```python from scapy.all import * # 构造ICMP重定向报文 ip = IP(src="192.168.1.1", dst="192.168.1.100") icmp = ICMP(type=5, code=1) # type=5表示重定向,code=1表示主机重定向 icmp_gw = IP(src="192.168.1.254", dst="192.168.3.1") # 更优的下一跳地址 packet = ip/icmp/icmp_gw # 发送ICMP重定向报文 send(packet) # 接收ICMP重定向报文 def receive_icmp_redirect(): sniff(filter="icmp and icmp[0]=5", prn=lambda x: x.show(), count=1) receive_icmp_redirect() ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值