Why can I not do a local Net::HTTP get request? - ruby-on-rails

So I have a controller action that renders json.. I can visit the url in the browser and see the json data, verifying that the route is working properly...
Yet, if I do:
uri = URI("#{request.protocol}#{request.host_with_port}/my_controller/action")
Net::HTTP.get(uri)
I get "Timeout::Error: Timeout::Error"
... ?

You're using a single-threaded HTTP server, i.e. Webrick. This means that it will only be able to serve one request at a time. You're attempting to make a request to the webserver from within the webserver itself. It won't be able to complete this action because of now hopefully obvious reasons.
Use a different web server, such as Thin, that would allow for this, or choose a different way to do this.

Related

Redirect http request to another address

I have a software that was developed in delphi and that makes a http get request to a specific url that I want to redirect to another url.
I have the source code but I can't recompile it because it wasn't developed by me, so it would take too much effort and time, and right now I can't afford it.
Anyway, back to my problem.
I tried using fiddler 2. It worked, but only for when I try accessing the url via browser. When my application sends the requests, it doesn't get redirected to the new url.
Does anyone have any other suggestion of what I can do?

Redirect a http post request with modified http header to another server

I'm using Ruby on Rails. Here is the requirement: the client (a native mobile app developed by me) will send a http post request to my Ruby code, my code will add some extra http headers (based on some business logic), then I need to "forward" or "redirect" this post request to another backend server (which has a REST service) and return its response back to the client.
I have been able to write a rack middleware to intercept the post request and add the extra headers. Originally I thought I could just use http redirect (status code: 307 for post request). But the problem is that the extra headers could NOT be submitted, which is the whole point of my code. So this isn't http redirect or forwarding per se, it's more like transforming a request.
I'm able to make a separate post request from my code using net http. This works. But I have to COPY data from the incoming request to my outgoing request (eg form data, http headers). This copying seems a bit tedious.
I would prefer some kind of simple "repackaging" (which is akin to http redirect or forwarding), that is I copy the whole incoming request to the outgoing request, slap on the extra headers and send it to the destination URL and be done with. I am not sure how to do this, and if doing it this way is even a good idea. For example, HTTP_USER_AGENT shows the OS, browser type of the client, when I'm making a new request, I probably don't need to send this on.
Alternatively, I can copy only the application specific data, because they're all the backend server (the destination of this "redirect") cares about. But I'm averse to hardcoding attributes in my code, causing close-coupling with the client (our native mobile app). Ideally I only copy application-specific data without hardcoding their attribute names. Is this possible? If so, how?
Any advice would be appreciated.
Thank you.
HTTP does not allow redirects for anything other than GET request.
(This is not technically correct but using HTTP 307 is kind of sketchy - see https://softwareengineering.stackexchange.com/questions/99894/why-doesnt-http-have-post-redirect)
If you need too send a POST request to another server for processing then using a proxy as you already seem to be doing is the correct solution.
Recreating the request in the proxy may seem tedious but it actually serves as a guarantee that you are calling the other servers "API" correctly.
While you can simply loop through the request headers:
uri = URI('http://www.example.com/todo.cgi')
req = Net::HTTP::Post.new(uri)
request.headers.each do |key, value|
req[key] = value
end
And pass the request form data:
req.set_form_data = request.request_parameters
You should ask yourself if it really is prudent to proxy everything.
See http://api.rubyonrails.org/classes/ActionDispatch/Request.html

How to get response headers and time using capybara-webkit

How to get response of seperate ajax requests in a web page using capybara-webkit?
Is there any particular method available to capture response time of each request?
Note:
Am using capybara with rspec.
For eg: i have 3 Ajax requests in a web page. I need to get separate response time of each request and the response time of entire web page.
Thanks,
Priya
Generally it's not possible since webserver is running in the different process but you could create a custom rack middle-ware and dump all responses to the separate log file. For the beginning you could implement technique described here: https://gist.github.com/2975611 and for dumping headers you could use some code snippets from http://rack.rubyforge.org/doc/Rack/ContentLength.html

http request (using net http or RestClient) inside my rails controller

I have problem creating http request inside my controller action. I used net/http and RestClient but I can't get it to work on my local server url i.e http://localhost:3000/engine/do_process, I always get requesttimeout however It works with other valid url.
Hope you can enlighten me on this one. I did some research but I can't find resources as to why I got this timeout problem.
Sample controller code:
require 'rest_client'
class LgController < ApplicationController
def get_lgjson
response = RestClient.get("http://localhost:3000/engine/do_process_lg")
#generated_json = response.to_str
end
end
I encountered this problem today, too, exactly in the same context: using the Ruby RestClient to make a HTTP request inside a controller. It worked earlier in a different project using OpenURI without problems. This was surprising because both http libraries, the RestClient and OpenURI for Ruby, use the same library Net::HTTP.
It is the URL that makes the difference. We can make a connection to an external URL in the controller, but not to localhost. The problem seems to be the duplicated connection to localhost. There is already a connection to localhost open, and we are trying to open a second one. This does not seem to work in a single-threaded web server like Thin for instance. A multi-threaded web server such as Puma could help.
I think this is because you use single-threaded web server. You have two opportunities to fix.
use passenger
define if it makes sense to make net/http to localhost.

How to invoke/simulate request to any url of application inside of application

How can I invoke a request to any url (controller/action) of my Rails3 application inside of application?
I've tried to use app object (Application) with get method, but it works only from console and not in the application.
For example: I have a controller that could handle all requests. It is not configured in routes.rb and this controller could parse the request.uri and return HTML in accordance of request. I need to get this html inside of application in other controller.
What you are asking for is the component feature that was officially removed from Rails in 2008 because it was slow and leads to bad design practices.
You can try to reproduce the feature, if you really need it. Or you can perform a new HTTP request internally (using a HTTP client) to the second location, get the response and then return the result.

Resources