Concurrent Net::HTTP.get to same domain - ruby-on-rails

As part of my Ruby on Rails application, I need to perform several (a few dozen) web requests to a foreign web server -- all on the same domain. I am aware of the two requests per domain throttle on Windows and know how to adjust that, but this application is running on CentOS and I was not expecting to run into this same issue, but I seem to be.
Does this same-domain-throttling exist on *nix? If so, how can I adjust it?

I think its not a OS issue but a Protocol issue.
Http 1.1 allows only 2 simulataneous requests to a hostname.
Note: http://one.yourdomain.com, http://two.yourdomain.com are considered different hostnames
HTH

I think it works better with other libraries like Typhoeus : Typhoeus or, if you're usning EventMachine : EM-Http-Request they both allow multi-request and you should be able to send more than 2 to the same domain (at least it does with Ubuntu)

Related

Rails rewriting link from Blogger

I use rack-reverse-proxy to setup my Blogger.com to a subdomain of my Ruby on Rails app: pulpoludo.com/blog
It's work, but I have an issue with the link of Blogger which returns to blog.pulpoludo.com (where my Blogger blog is host).
I would like to rewrite this link. But I don't know-how. Can you help me?
(I have found someone who does this in PHP: https://matt-stannard.blogspot.com/2013/02/blogger-in-subdirectory-of-my-domain.html
But I would like to do the same thing with Rails and a gem maybe)
Indeed, you cannot use rack-reverse-proxy because it does not allow you to change the response (you need to rewrite the page you retrieve using a regular expression replacement, as in the example you link to.
Also, you should probably avoid using rack-reverse-proxy in production, as it will keep your ruby processes busy waiting for the backend responses, that might fail or be slow. And:
It is not meant for production systems
You should instead proxy from your front HTTP acceptor (nginx or other). For nginx you can see a very thorough response, using a combination of proxy_pass and sub_filter, at https://stackoverflow.com/a/32543398/384417.
edit: If it's not possible to use nginx or another reverse proxy, you can still do it in ruby.
rack-reverse-proxy supports transformers, you can build one yourself, and register it so it's run on the response. This (closed) issue will help, it is exactly what you need: https://github.com/waterlink/rack-reverse-proxy/issues/65. The caveat (as always when changing responses) is that you have to update the Content-Length response header to match the updated size of the body.

Using routing with faye::WebSocket in ruby

I am experimenting with websockets in my ruby on Rails server. I am trying faye-websocket as described in here.
Initial tests look promising (I am using a python client and I am able to connect to the websocket) but I have a newbie question that keeps bugging me. Including my websockets library as a middleware in ruby seems to capture ALL requests from my client that are websocket connections. In such case, how do I differentiate (and reply differently) to client calls with different routing (e.g. calls to http://myserver.com/apple and http://myserver.com/pear being both websockets)?
EDIT
I found that the env variable contains the field "REQUEST_PATH" which has the information of the routing requested by the client. I can use that variable to return the appropriate answer to each one of the different client calls. Is there any more "elegant" way to do it?

Rails caching not working on server

In my application, I have used caching. This is the code, I have used. In after_filter, I called the method which include this one line code.
Rails.cache.write("properties", #properties.to_xml)
I try to get this in another action in before_filter like
#hotels = Rails.cache.fetch("properties")
this all working fine in development machine. But in server it returns null value. the application run in same development mode in server. Can you please anyone suggest me the right way. Thanks in advance.
It sounds like you haven't configured a backend for the store, so it will use ActiveSupport::Cache::MemoryStore
From the documentation:
If you're running multiple Ruby on Rails server processes (which is the case if you're using mongrel_cluster or Phusion Passenger), then this means that Rails server process instances won't be able to share cache data with each other.
This works in development since you are likely using a single server instance, so the cache is only stored in one process. For production you need to configure an alternative shared store. I'd recommend running a memcached instance, and installing and using the Dalli Gem as per the README.

Rails 3.1 - Firing an specific event with the EventMachine

I would like to use the plugin em-eventsource ( https://github.com/AF83/em-eventsource ) for server-sent events in a Rails 3.1-project. My problem is, that there is only explained how to listen on events and receive messages, but not how to fire a specific event up and send the message. I would like to produce the event in an Active Record-Observer. Am I right when I think that I have to defer a operation with EventMachine to produce this event, or how can I solve this?
And yes, it has to be Ruby on Rails. If I don't get this to work with EventMachine, I would try to bypass the whole ruby-part with node.js.
Actually I worked on this library a little with the maintainer. I think you mixed the client part with the server one. em-eventsource is a client library which you can use to consume a ServerSentEvent API, it's not meant to fire SSE.
On the server side, it quite doesn't matter whether you are using Rails or any other stack (nodejs, php…) as long as the server you are running on supports streaming. The default web server shipped with Rails does not (Webrick) but there are many others which do: Thin, Puma, Goliath…
In order to fire SSE in Rails, you would have to use both a streaming-capable server among those cited, and abide by the SSE specification. It mostly falls down to, first, responding with the proper Content-type header ("text/event-stream") so that the client (browser) knows it should hang-on, and then start streaming on the socket. That latter part is the one not easily possible as of today in Rails 3 (yet not impossible!); Rails 4 actually now supports streaming in an easy way, with a clean and simple internal API, so it's definitely coming.
In the mean time, you'd either:
mess with Rack's API in Rails (using EventMachine I guess, there are some examples in the wild)
or have it smart and make use of the streaming feature provided by Sinatra, built on top of Rack (see https://gist.github.com/1476463 for an example of Sinatra app which can be mounted in a Rails one!)
or you could use an external service such as Pusher
or leverage a entirely different stack…
A good overview: http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/
Maybe I'm wrong, but if IIRC Rails can't support long pooling. Rails block whole server (or thread if you have more than one running inside server) for each request and can't reuse them unless whole response was send. That's why you should setup reverse proxy (like nginx) in front of Rails application if you suspect there could be many concurrent connections - to proxy slow client requests and send them to Rails when whole request is received. It's just how Rack works, there's not much you can do about this probably.

How to get the HTTP_HOST from Rails?

I need to set some server specific variables in a rails application that will run on at least two different servers. What is the best way to get the request's HTTP_HOST value in order to know what is the current server and set these variables accordingly?
I'm using Apache 2 with Passenger.
Think you're looking for request.env["SERVER_ADDR"].
Are the 2 servers involved in load balancing? If so, you won't want to grab the host from the request, because it'll be the same in both cases. You'll want to grab it in some generic ruby call. It's been a while since I've done Ruby, but probably something like (untested - rough idea):
Resolv::Hosts.getNames(Resolv::Hosts.getAddress('localhost'))

Resources