【问题标题】:In Rails, can an internal request be generated that behaves identically to an HTTP request?在 Rails 中,是否可以生成与 HTTP 请求行为相同的内部请求?
【发布时间】:2010-02-08 05:15:42
【问题描述】:

在我的 Rails 应用程序中,我想生成与“真正的”HTTP 请求行为相同的请求。

举一个有些人为的例子,假设我正在创建一个系统,可以批处理传入的 HTTP 请求以供以后处理。它的界面类似于:

  1. 通过通常的 CRUD 方法创建新的批处理资源(POST,接收新创建资源的位置)。
  2. 通过向批处理资源发送 URL、HTTP 方法和数据来更新批处理资源,这些数据将被添加到它应该稍后批量执行的请求集合中。
  3. “处理”批处理资源,其中它将遍历其请求集合(每个请求可能由 URL、HTTP 方法和一组数据表示),并以某种方式告诉 Rails 在就像他们正常的“非批量”请求一样。

在我看来,要使其正常运行,需要完成两项重要的工作:

首先,传入的请求需要以某种方式保存以备后用。这可能只是保存传入请求的各个方面的情况,例如路径、方法、数据、标头等,它们已经作为控制器内传入请求对象的一部分公开。如果有一种更“自动”的方式来处理这个问题会很好——可能更像是对象编组或序列化——但是记录单个参数的蛮力方法也应该可以工作。

其次,保存的请求需要能够在以后重新注入到 Rails 应用程序中,并经历与普通 HTTP 请求相同的过程:路由、控制器、视图等。我'我希望能够捕获字符串中的响应,就像 HTTP 客户端会看到的那样,我还希望使用 Rails 的内部机制来做到这一点,而不是简单地使用 HTTP 库来让应用程序真正实现对自己的新请求。

想法?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    存储参数的直接方式应该在控制器中序列化请求对象 - 这应该包含所有重要数据

    稍后调用请求,我会考虑使用 Dispatcher.dispatch 类方法,它需要 3 个参数:cgi 请求、会话选项(CgiRequest::DEFAULT_SESSION_OPTIONS 应该没问题)和输出写入的流到

    【讨论】:

    • 通过什么方法序列化请求对象? Marshal.dump(request) 不起作用:它抱怨“没有为类 Proc 定义 marshal_dump”,这是有道理的,因为请求对象的至少一个属性是 Proc。许多其他属性也是对实例化对象的引用,这使我相信即使封送处理产生了结果,以后的重构也不会产生有效的请求。我想任何其他典型的序列化方法(例如,to_yaml', to_json')都会遇到同样的问题。
    【解决方案2】:

    机架中间件

    在我最初提出这个问题后进行了大量调查后,我最终尝试并成功实施了使用机架中间件的解决方案。

    基本方法

    在中间件的`call'方法中:

    1. 检查我们是否将请求作为 交易对象,或者如果它是一个普通的请求。如果它是 普通,通过调用中间件正常进行 app.call(env),并返回状态、标头和响应。

    2. 除非这是一个事务提交,否则记录下“有趣”的部分 请求的 env 哈希,并将它们作为关联的“操作”保存到数据库中 使用此交易对象。

    3. 如果这是一个事务提交,则检索所有相关操作 对于本次交易。要么创建一个新的请求环境,要么克隆 现有的并用为操作保存的值填充它。还 制作原始请求环境的副本以供以后恢复,如果 控制通常是在提交后通过应用程序。

    4. 将构建的环境输入到对 app.call(env) 的调用中。重复 每个操作。

    5. 如果原始请求环境被保留,恢复它并制作一个 对 app.call(env) 的最终调用,从调用 `call' 中返回 中间件 来自此最终调用的状态、标头和响应 app.call(env).

    示例应用程序

    我已经实现了我在此处描述的方法的示例实现,我已在 GitHub 上提供了该示例实现。它还包含一个深入的示例,描述了从 API 角度来看实现的外观。请注意:它非常粗糙,完全没有文档记录(自述文件除外),并且很可能违反了 Rails 良好的编码实践。可以在这里获取:

    插件/宝石

    我还开始开发一个插件或 gem,它将为任何 Rails 应用程序提供这种接口。它正处于形成阶段(实际上它目前完全没有代码),并且它的工作可能会缓慢进行。在这里探索它的发展:

    另见

    【讨论】:

    • 另外值得注意的是,我没有完全探索 roman 建议的答案,它可能是我提出的方法的可行替代方案。
    • 您的示例和宝石的链接已损坏
    猜你喜欢
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 2019-07-29
    • 1970-01-01
    • 2019-10-18
    相关资源
    最近更新 更多