简体   繁体   English

Rails JS链接在控制器上处理了两次

[英]Rails JS link being processed twice at controller

Seeing some strange behavior in an app I'm coding. 在我正在编写的应用中看到一些奇怪的行为。 I have an index page that shows a list of records. 我有一个显示记录列表的索引页。 If I create a new record, it is inserted into the DB and then the user is redirected to the index page which now shows the new record. 如果创建新记录,则将其插入数据库中,然后将用户重定向到现在显示新记录的索引页面。 Each record has some AJAX voting links. 每个记录都有一些AJAX投票链接。 When the user clicks a voting link on the new item, I see the request processed twice by the controller with two different IP addresses...also, I am storing a UUID in a permanent cookie for each user, and the second request from the second IP address shows a different UUID than the current user. 当用户单击新项目上的投票链接时,我看到具有两个不同IP地址的控制器对请求进行了两次处理...此外,我还将UUID存储在每个用户的永久Cookie中,第二个IP地址显示的UUID与当前用户不同。

I've only seen the problem at my friend's office, so I don't know if it is because of their messed up network or something (corporate network with proxies/firewalls/etc... which I'm told is poorly managed). 我只在朋友办公室看到了这个问题,所以我不知道这是因为他们的网络混乱了还是什么(代理服务器/防火墙/等的企业网络管理不善) 。 I think it's bizarre that it only happens on new records, and not when clicking a voting link (which uses the same exact code) on pre-existing records... 我认为这仅在新记录上发生,而不是在现有记录上单击投票链接(使用相同的精确代码)时才发生,这很奇怪...

Here's the log showing the controller response - note one response is processed as JS and the second as */* : 这是显示控制器响应的日志-请注意,一个响应as JS处理as JS第二个as */*

Started GET "/vote/14?vote_value=-1" for <company's external IP> at 2014-07-02 16:31:41 -0400
Processing by FoosController#voting as JS
  Parameters: {"vote_value"=>"-1", "foo_id"=>"14"}
  Foo Load (0.7ms)  SELECT "food".* FROM "food" WHERE "food"."id" = $1 ORDER BY created_at DESC LIMIT 1  [["id", "14"]]
   (0.3ms)  BEGIN
  SQL (0.8ms)  INSERT INTO "votes" ("created_at", "updated_at", "uuid", "value", "foo_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["created_at", Wed, 02 Jul 2014 20:31:41 UTC +00:00], ["updated_at", Wed, 02 Jul 2014 20:31:41 UTC +00:00], ["uuid", "61230391-311a-4358-9c4b-665d2a8bc8e9"], ["value", -1], ["foo_id", 14]]
   (2.0ms)  COMMIT
   (0.2ms)  BEGIN
   (0.3ms)  COMMIT
  Rendered foo/voting.js.erb (0.1ms)
Completed 200 OK in 14ms (Views: 2.2ms | ActiveRecord: 4.3ms)


Started GET "/vote/14?vote_value=-1" for <different unrecognized IP> at 2014-07-02 16:31:41 -0400
Processing by FoosController#voting as */*
  Parameters: {"vote_value"=>"-1", "foo_id"=>"14"}
  Foo Load (0.6ms)  SELECT "food".* FROM "food" WHERE "food"."id" = $1 ORDER BY created_at DESC LIMIT 1  [["id", "14"]]
   (0.3ms)  BEGIN
  SQL (0.7ms)  INSERT INTO "votes" ("created_at", "updated_at", "uuid", "value", "foo_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["created_at", Wed, 02 Jul 2014 20:31:41 UTC +00:00], ["updated_at", Wed, 02 Jul 2014 20:31:41 UTC +00:00], ["uuid", "b8a23470-9f9f-4a65-8577-7da7e31a6995"], ["value", -1], ["foo_id", 14]]
   (1.7ms)  COMMIT
   (0.1ms)  BEGIN
   (0.1ms)  COMMIT
  Rendered foo/voting.js.erb (0.2ms)
Completed 200 OK in 13ms (Views: 2.4ms | ActiveRecord: 3.5ms)

Here's the partial for the records that includes the AJAX links: 这是包含AJAX链接的部分记录:

<div class="foo" id="foo-<%= foo.id %>">
  <div class="voting">
    <span id="foo-<%= foo.id %>-score"><%= foo.score %></span>
    <div class="voting-links" id="foo-<%= foo.id %>-voting-links">
      <%= link_to 'UP', voting_path(foo.id, vote_value: 1), remote: true %> /
      <%= link_to 'DOWN', voting_path(foo.id, vote_value: -1), remote: true %>
    </div>
  </div>

  <div class="foo-content" id="foo-<%= foo.id %>-content">
     <%= foo.content %>
  </div>
</div>

Here's my controller action: 这是我的控制器动作:

def voting
    @foo = Foo.find(params[:foo_id])

    vote = @foo.votes.create(uuid: cookies[:user_uuid], value: params[:vote_value])

    @foo.save

    respond_to do |format|
      format.html { redirect_to root_path }
      format.js { render 'voting' }
    end
  end

And the response js.erb file: 以及响应js.erb文件:

score = $('#foo-' + <%= @foo.id %> + '-score');
score.html(<%= @foo.score %>);

Any ideas on how to troubleshoot this or make sure it is not an application issue and is a network issue at this particular site? 关于如何解决此问题或确保它不是应用程序问题以及此特定站点上的网络问题的任何想法? I haven't been able to reproduce in my office. 我无法在我的办公室中复制。 I used Firebug to check out the request being made from the browser, and it looks like only one request is being sent out. 我使用Firebug来检查从浏览器发出的请求,看来只有一个请求被发出。 Is this just an issue of a misconfigured gateway/router/firewall etc... reproducing the request somehow? 这仅仅是网关/路由器/防火墙等配置错误的问题吗?以某种方式重现请求? The fact that it is sending over two different UUIDs seems significant, but I can't imagine why it only happens with new entries. 它通过两个不同的UUID发送的事实似乎很重要,但我无法想象为什么它仅在新条目中发生。

Thanks! 谢谢!

If it comes from one single location then it is not coming from your code. 如果它来自一个位置,则它不是来自您的代码。 It could be a virus, a badly set-up caching proxy, a web-scanner bot, or anything else. 可能是病毒,设置错误的缓存代理,Web扫描程序机器人或其他任何东西。

Defending your code against double entry is a good thing to do, but seems pretty complex. 防止代码重复输入是一件好事,但看起来很复杂。 Example: You cannot rely on source IP because of load balancing proxies. 示例:由于负载平衡代理,您不能依赖源IP。

Anyhow there is something you can try (and I think you must do): 无论如何,您可以尝试一些操作(我认为您必须这样做):

1- You are using a GET request, and I see from your log that an INSERT is done in your database. 1-您正在使用GET请求,并且从您的日志中看到在数据库中已完成INSERT。 This goes against RESTfull solutions. 这与RESTfull解决方案背道而驰。 Only POST request should trigger INSERTs. 仅POST请求应触发INSERT。 You should change your code to reflect that, no matter how hard this is 无论这有多困难,您都应该更改代码以反映这一点

2- Once you have correctly set-up POST request for that action, you must enforce rails to protect against cross-script request by using csrf_meta_tags in your headers, and protect_from_forgery in your controllers. 2 -一旦你正确设置了该动作POST请求,你必须强制轨使用,以防止交叉脚本要求csrf_meta_tags在你的头,并protect_from_forgery在控制器中。

I do hope this would fix the situation and drop the second request. 我确实希望这能够解决问题并放弃第二个请求。 Just be sure that your test suite is fully covering your code before you start such modifications, because such a deep change may lead to unsuspected result specially with AJAX form or multipart forms. 在开始进行此类修改之前,只需确保测试套件完全覆盖了您的代码,因为如此深的更改可能会导致意外的结果,特别是对于AJAX表单或多部分表单。

It's complex and it may be long, but as I see your log now it seems your server is not protected. 它很复杂,可能很长,但是正如我现在看到的日志所示,您的服务器似乎不受保护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM