Sinatra 应用程序作为机架中间件 TimeOut Rails 3

Posted

技术标签:

【中文标题】Sinatra 应用程序作为机架中间件 TimeOut Rails 3【英文标题】:Sinatra app as rack middleware TimesOut Rails 3 【发布时间】:2013-09-30 18:53:40 【问题描述】:

在 Rails 开发环境中,我尝试将 Sinatra 应用程序添加为中间件。 Sinatra 应用程序使用 geoip gem 处理用户的 IP 地址并返回带有城市的 json。

我可以通过在浏览器中直接访问示例 url 或在命令行中使用 curl http://local.fqdn.org/geoip/locate.json?ip=24.18.211.123 来查看返回的 json。但是,当我尝试从 Rails 控制器中使用 wget 调用 url 时,Rails 应用程序停止响应,经常使我的浏览器崩溃,并且我的 Rails 服务器不会使用 control+C 命令退出。

关于这里发生了什么的任何线索?为什么直接访问浏览器中的 url 会返回正确的响应,但我在控制器中的调用会导致超时?

sinatra-geoip.rb

require 'sinatra'
require 'geoip'
require 'json'

# http://localhost/geoip/locate.json?ip=24.18.211.123
#
# 
#     latitude: 47.684700012207
#     country_name: "United States"
#     area_code: 206
#     city: "Seattle"
#     region: "WA"
#     longitude: -122.384803771973
#     postal_code: "98117"
#     country_code3: "USA"
#     country_code: "US"
#     dma_code: 819
# 

class GeoIPServer < Sinatra::Base
    get '/geoip/locate.json' do
        c = GeoIP.new('/var/www/mywebsite.org/current/GeoLiteCity.dat').city(params[:ip])
        body c.to_h.to_json
    end
end

routes.rb

mount GeoIPServer => "/geoip"

config/environments/development.rb

Website::Application.configure do
    require "sinatra-geoip"
    config.middleware.use "GeoIPServer"

...
end

控制器

raw_geo_ip = Net::HTTP.get(URI.parse("http://#geoip_server/geoip/locate.json?ip=#request.ip"))
@geo_ip = JSON.parse(raw_geo_ip)

【问题讨论】:

【参考方案1】:

我们的解决方案很难找到。我们最终在 sinatra 源代码调用 forward 中找到了一个方法。

新的 sinatra-geoip.rb

class GeoIPServer < Sinatra::Base
    if defined?(::Rails)
        get '/properties.json' do
            env["geo_ip.lookup"] = geo_ip_lookup(request.ip)
            forward
        end
    end

    def geo_ip_lookup(ip = nil)
        ip = ip.nil? ? params[:ip] : ip
        result = GeoIP.new('/var/www/mywebsite.org/current/GeoLiteCity.dat').city(ip)
        result.to_h.to_json
    end
end

本质上,我们从文件中删除了/geoip/locate.json 路由并将其转换为一个简单的方法。我们需要在调用properties.json 时进行geoip 查找,因此添加了一个带有geoip 信息的新参数。然后我们在控制器中将新参数设置为等于@geo_ip 变量。

新的属性控制器

if Rails.env.development? or Rails.env.test?
    # Retrieves param set by sinatra-geoip middleware.
    @geo_ip = JSON.parse(env["geo_ip.lookup"] || "")
else
    # Production and staging code
end

相当模糊的问题和解决方案。希望它会帮助那里的人。 干杯。

【讨论】:

它帮助了我。感谢分享解决方案:)

以上是关于Sinatra 应用程序作为机架中间件 TimeOut Rails 3的主要内容,如果未能解决你的问题,请参考以下文章

机架会话在 Chrome 中丢失

Sinatra Route什么都不返回

在通用机架应用程序中获取中间件的有序列表?

如何在经典 sinatra 应用程序中配置omniauth 使用memcached 作为谷歌的后备存储?

什么是机架?我可以用它用 Ruby 构建 Web 应用程序吗?

您如何在 Sinatra 中选择您的 HTTP 服务器?