Request headers in Goliath middleware - ruby

I am writing own middleware for Goliath server.
How can I get request headers in "call" method?
Thanks!

"call" method always return [status_code, headers, body] tuple, see example below:
class AwesomeMiddleware
include Goliath::Rack::AsyncMiddleware
def call(env)
status, headers, response = super(env)
[status, headers, response]
end
end
Also checkout AsyncMiddleware and SimpleAroundwareFactory in Goliath repository.

Related

How to stub a HTTParty request inside a method for testing?

I have created a function that makes a HTTParty get request. It raises a custom error message that i need to test. I tried to stub the request using Webmock in the test but it is raising a <Net::OpenTimeout>. How can i stub the get request if the url is dynamically constructed?
def function(a , b)
# some logic , dynamic url constructed
response = HTTParty.get(url, headers: {"Content-Type" =>
"application/json"})
if response.code != 200
raise CustomError.new <<~EOF
Error while fetching job details.
Response code: #{response.code}
Response body: #{response.body}
EOF
end
JSON.parse(response.body)
for the test
def test_function
WebMock.stub_request(:get, url).with(:headers => {'Content-
Type'=>'application/json'}).to_return(:status => 500)
# HTTParty.stub(get: fake_response)
err = assert_raises CustumError do
c.function(a , b)
end
WebMock allows you to use "wildcard matching" so you can stub requests matching a regular expression:
WebMock.stub_request(:get, /example/).to_return(status: 500)

Mocking a post request with binary data in Sinatra

I have an endpoint in my Sinatra application that will be receiving binary data as part of the body. The other application sending it data will have a Faraday request that looks like this:
connection = Faraday.new(url: "https://example.com/post_data") do |conn|
conn.request :multipart
conn.adapter :net_http
conn.headers['Content-Type'] = 'octet/stream'
end
#response ||= connection.post do |req|
req.params = { :host => host,
:verification => "false"}
req.body = my_base64_encoded_binary
end
Then, in Sinatra, I will have an endpoint that receives those request parameters and binary data and passes it along to a model, like so:
post '/post_data' do
request.body.rewind
payload = request.body.read
raise Sinatra::NotFound unless payload and params[:host]
output = MyOutput.new(params, payload)
content_type 'application/json'
body output.data
end
When I try to test this endpoint using Rack::Test helpers, I end up in a weird situation. I can't seem to create the proper mock in order to test this endpoint properly. Based on some manual testing with PostMan, I'm pretty certain my endpoint works properly. It's just the test that's holding me up. Here is the spec:
it "should return a json response" do
post(url, :host => host, :verification => "false") do |req|
req.body = [my_binary]
req.content_type = "application/octet-stream"
end
expect(last_response.status).to eq(200)
expect(last_response.content_type).to eq("application/json")
end
And when I inspect what the incoming request looks like in the test, it does not contain a proper body. params is properly set to the host and verification settings I set, but the body is also being set to the params (inspected through payload = request.body.read) instead of the binary.
Is there a different way to set up the mock so that the binary properly is set to the body of the request, and the parameters are still set to the request parameters properly?
The answer is that the only way to post the body is where I was adding the params in the rack test helper. I needed to take the params and move them into the query string of the URL in the request, and then only add the binary as the body of the post request in the test helper.
let(:url) { "http://example.com/post_data?host=>#{host}&verification=#{verification}" }
it "should return a json response" do
post(url, my_binary)
expect(last_response.status).to eq(200)
expect(last_response.content_type).to eq("application/json")
end

How can I wrap every request with RestClient to use :verify_ssl => false?

I'm trying
RestClient.add_before_execution_proc do |req, params|
req(:verify_ssl => false)
end
It isn't working.
How can I wrap every request with RestClient to use :verify_ssl => false?
Use the params instead of req. Those params will be passed to RestClient.execute, which is the entry point for all requests.
RestClient.add_before_execution_proc do |req, params|
params[:verify_ssl] = false
end
You can also consider creating a simple class to encapsulate your needs and execute a get/post/... rest without verify_ssl
(check https://github.com/rest-client/rest-client/blob/master/lib/restclient/request.rb#L160)
I'd write my own helper wrapper for the RestClient calls rather than modifying global state, since global changes make it hard for someone reading your code to understand what's happening.
For example:
def insecure_restclient_get(url, headers={}, &block)
RestClient::Request.execute(verify_ssl: false, method: :get, url: url, headers: headers, &block)
end
def insecure_restclient_post(url, payload, headers={}, &block)
RestClient::Request.execute(verify_ssl: false, method: :post, url: url, payload: payload, headers: headers, &block)
end
Also note that if you're setting verify_ssl: false you might as well not be using https at all.
In response to #alb-i986's comment for #AlexandreAngelim's answer, I've written the follow monkey patch that wraps the constructor of RestClient::Request class instead so it would work with the latest RestClient:
module RestClient
class Request
orig_initialize = instance_method(:initialize)
define_method(:initialize) do |args|
args[:verify_ssl] = false
orig_initialize.bind(self).(args)
end
end
end

Output Raw HTTP Request without Sending in Ruby

I am trying to setup a POST request to a rest api using ruby. What I want to do is to output the raw HTTP request without actually sending the request. I have looked at HTTParty and Net:HTTP, but it seems the only way to output the request is only once you send the request. So basically I want a convenient way for creating an HTTP request string without actually having to send it.
The HTTParty.get and similar methods methods are helper functions that wraps a lot of the internal complexity; you should just peek inside the method to find that HTTParty.get to find that inside it it just makes a call to perform_request:
def get(path, options={}, &block)
perform_request Net::HTTP::Get, path, options, &block
end
and peeking into perform_request, we get that it just constructs a Request object and call perform on it:
def perform_request(http_method, path, options, &block) #:nodoc:
options = default_options.merge(options)
process_headers(options)
process_cookies(options)
Request.new(http_method, path, options).perform(&block)
end
You should take a look into the Request class.
Take a look at Typhoeus
request = Typhoeus::Request.new(
"www.example.com",
method: :post,
body: "this is a request body",
params: { field1: "a field" },
headers: { Accept: "text/html" }
)
It allows you to create the request and then you can run it or not with
request.run

Add api_key on every request with Rack middleware

I work with Devise token_authentication service and ActiveResource client. I wish set automatically :auth_token params in every requests !
I tried this, but this doesn't work...
class AuthApp
def initialize(app)
#app = app
end
def call(env)
status, headers, response = #app.call(env)
request = Rack::Request.new(env)
request.params[:auth_token] = 'jCxKPj8wJJdOnQJB8ERy'
[status, headers, response]
end
end
Any idea ?
If you have a recent copy of rack that includes this pull request, you can use Rack::Request#update_param:
request = Rack::Request.new(env)
request.update_param :auth_token, 'jCxKPj8wJJdOnQJB8ERy'
That will persist in the env that is passed among middlewares (and to Rails).

Resources