Can I catch and check the proxy request in tests - ruby-on-rails

I have the code:
def rest_endpoint
RestClient::Resource.new(url, { proxy: #action.proxy_service }.compact_blank)
end
It is necessary to test that sometimes the request is executed through a proxy server.
test 'use GET request via proxy' do
url = 'https://some.url'
proxy = 'https://test.example.co.internal:1313'
expected_proxy_request = stub_request(:any, proxy)
RestClient::Resource.new(url, proxy: proxy).get
assert_requested expected_proxy_request
end
It's failing. Is there a way to test accessing a proxy service using stub_request without paying attention to the instance of the RestClient::Resource class?

Related

Envoy Lua Filter - How to make HTTP request?

I would like to make http request from my lua filter to an external server.
According to Envoy documentation, http call can be done using request_handle:httpCall:
function envoy_on_request(request_handle)
-- Make an HTTP call to an upstream host with the following headers, body, and timeout.
local headers, body = request_handle:httpCall(
"lua_cluster",
{
[":method"] = "POST",
[":path"] = "/",
[":authority"] = "lua_cluster"
},
"hello world",
5000)
I have created a cluster called lua_cluster in my envoy.yaml file as needed, but the request doesn't reach my server and I'm getting 400 response.
Possible solution??
When changing the authority header from [":authority"] = "lua_cluster" to [":authority"] = "<cluster's url hostname>", the request arrived to the server and I got 200 response from the server. Can someone explain this? Is it a valid thing to do?

Rails 4: how to make request from outside of Rails app during integration test?

I have an application that needs 2-way communication to external daemon (bitcoind). There is functionality in bitcoind that allows to call my application whenever new block or transaction of interest occurs ('--walletnotify' and '--blocknotify'). For that I'm using CURL to request "http://myapp/walletnotify" and so on:
walletnotify = /usr/bin/curl --max-time 60 http://myapp/walletnotify/%s
I'm trying to create integration tests for this callback behavior. Unfortunately when running integration tests, I'm receiving errors on daemon side, as it is not able to perform requests to "http://myapp/walletnotify" - obviously Rails server cannot be reached (or the connection is interrupted?). Of course tests fail as appropriate actions are not called.
My question is: how to properly test such scenario? Is there any way to allow for direct external requests to application during integration tests? Is there a way to make sure that Rails server is running during integration tests? Or maybe I should listen to such requests inside integration test and then proxy them to application?
Update 2018-06-03: I'm using minitest. The test that I'm trying to run is here:
https://github.com/cryptogopher/token_voting/blob/master/test/integration/token_votes_notify_test.rb
After calling
#rpc.generate(101)
bitcoind daemon in regtest mode should generate 101 blocks and call 'blocknotify' callbacks. The problem is it cannot send HTTP request to application during test.
Ok, I resolved this one.
Looks like 'minitest' does not start application server no matter which driver you choose. Still you can start your own HTTP server to listen for notifications from external sources and forward them to tested application.
For this to work you need:
require 'webrick'
Setup HTTP server (logging disabled to avoid clutter):
server = WEBrick::HTTPServer.new(
Port: 3000,
Logger: WEBrick::Log.new("/dev/null"),
AccessLog: []
)
Specify how to handle incoming HTTP requests. In my case there will be only GET requests, but it is important to forward them with original headers:
server.mount_proc '/' do |req, resp|
headers = {}
req.header.each { |k,v| v.each { |a| headers[k] = a } }
resp = get req.path, {}, headers
end
Start HTTP server in separate thread (it is blocking the thread where it is running):
#t = Thread.new {
server.start
}
Minitest.after_run do
#t.kill
#t.join
end
Timeout.timeout(5) do
sleep 0.1 until server.status == :Running
end

Advice on how to set up a connection between nancy service and server

I am working on a project whereby we have sites (developed with ruby on rails) hosted on an Ubuntu server using tomcat. We want these sites to make HTTP calls to a service developed using Nancy. We have this working locally whereby the service is hosted on a machine that we can call within our network. We cannot however get it working when live. Here is an example call:
def get_call(routePath)
started_at = Time.now
enc_url = URI.encode("#{settings.service_endpoint}#{routePath}")
uri = URI.parse(enc_url)
http = Net::HTTP.new(uri.host, uri.port)
req = Net::HTTP::Get.new(uri.request_uri)
resp = http.request(req)
logger.bench 'SERVICE - GET', started_at, routePath
return resp if response_ok?(resp)
end
When working locally the settings are as follows:
settings.service_endpoint = http://10.10.10.27:7820
routePath = /Customers
When we upload it to the server we use the following:
settings.service_endpoint = http://127.0.0.1:24099
routePath = /Customers
We currently get the following error:
SocketError at /register
initialize: name or service not know
with the following line being highlighted:
resp = http.request(req)
Are we completely wrong with the IP being called. Should it be 127.0.0.1, localhost. 10.10.10.27 or something entirely different? The strange thing is we can do a GET call via telnet in our Ubuntu server (telnet 127.0.0.1 24099) so that must mean the server can make the calls but the site hosted on the server cannot. Do we need to include a HTTP proxy (have read some reference to that but dont really know if its needed).
Apologies if its obvious but we have never tried anything like this before so its all very perplexing. Any further information required just let me know.
We changed the service_endpoint to localhost and it worked. Not sure if this is because it didnt like "http://" or some other reason. Any explanation as to why this is the case would be much appreciated, just so we know. Thanks!

How to use $remote_addr with rails and nginx secure_link

I have a rails application that makes calls to another server via net::http to retrieve documents.
I have set up Nginx with secure_link.
The nginx config has
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri$remote_addr mySecretCode";
On the client side (which is in fact my rails server) I have to create the secure url something like:
time = (Time.now + 5.minute).to_i
hmac = Digest::MD5.base64digest("#{time}/#{file_path}#{IP_ADDRESS} mySecretCode").tr("+/","-_").gsub("==",'')
return "#{DOCUMENT_BASE_URL}/#{file_path}?md5=#{hmac}&expires=#{time}"
What I want to know is the best way to get the value above for IP_ADDRESS
There are multiple answers in SO on how to get the ip address but alot of them do not seem as reliable as actually making a request to a web service that returns the ip address of the request as this is what the nginx secure link will see (we don't want some sort of localhost address).
I put the following method on my staging server:
def get_client_ip
data=Hash.new
begin
data[:ip_address]=request.ip
data[:error]=nil
rescue Exception =>ex
data[:error]=ex.message
end
render :json=>data
end
I then called the method from the requesting server:
response = Net::HTTP.get_response(URI("myserver.com/web_service/get_client_ip"))
if response.class==Net::HTTPOK
response_hash=JSON.parse response.body
ip=response_hash["ip_address"] unless response_hash[:error]
else
#deal with error
end
After getting the ip address successfully I just cached it and did not keep on calling the web service method.

Https call giving exception

My code is like
encodestring = "test#gmail.com:test"
enc = Base64.encode64(encodestring)
auth = "Basic #{enc}"
https = Net::HTTP.new('localhost', 443)
https.use_ssl = true
path = '/user/test'
query_string = "#{auth}"
https.verify_mode = OpenSSL::SSL::VERIFY_NONE # don't display warnings
resp = https.post(path,query_string)
here test is a method inside user_controller.rb file.If i am making simple http request its working fine but while making https request it is giving exception "SocketError (initialize: name or service not known)".Please help me to make it a valid https call. thanks in advance.
The examples I've seen have taken a host name as the first argument to HTTP.new, rather than a URL. Try this:
https = Net::HTTP.new('localhost', 443)
It's not clear whether you actually want to connect to port 443 or 3001 - you obviously can't connect to both. If you want 3001, replace the 443 above.

Resources