2013-09-30 2 views
1

В среде разработки Rails я пытаюсь добавить приложение Sinatra в качестве промежуточного программного обеспечения. Приложение Sinatra использует geoip gem, который обрабатывает IP-адрес пользователя и возвращает json с их городом.Приложение Sinatra как промежуточное ПО стойки TimesOut Rails 3

Я могу просмотреть возвращенный json, перейдя непосредственно к примеру url в браузере или используя curl в командной строке, http://local.fqdn.org/geoip/locate.json?ip=24.18.211.123. Однако, когда я пытаюсь вызвать url с wget из контроллера Rails, приложение Rails перестает отвечать на часто возникающие ошибки моего браузера, а мой сервер rails не выйдет с помощью команды control + C.

Любой ключ к тому, что здесь происходит? Почему бы сразу перейти к URL-адресу в браузере, вернуть правильный ответ, но мой вызов в контроллере приводит к выходу Time Out?

Синатра-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" 

конфигурации/среда/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.

новый Синатра-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, поэтому новый параметр был добавлен с информацией геоинформации. Затем мы устанавливаем новый параметр, равный @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 

Вместо неясными проблемы и решения. Надеюсь, это поможет кому-то там. Cheers.

+0

Это помогло мне. Спасибо, что поделились решением :) –