Skip to content

Commit

Permalink
Feature/add http basic support auth (q9f#151)
Browse files Browse the repository at this point in the history
* Adds support for basic http auth

* Adds support for basic http auth
  • Loading branch information
johnnybutler7 authored and arthur-cw committed Oct 31, 2022
1 parent fe54691 commit 57c3472
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 3 deletions.
2 changes: 2 additions & 0 deletions lib/eth/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Client
# @raise [ArgumentError] in case it cannot determine the client type.
def self.create(host)
return Client::Ipc.new host if host.end_with? ".ipc"
return Client::HttpBasic.new host if Regexp.new(":.*@.*:", Regexp::IGNORECASE).match host
return Client::Http.new host if host.start_with? "http"
raise ArgumentError, "Unable to detect client type!"
end
Expand Down Expand Up @@ -496,4 +497,5 @@ def marshal(params)

# Load the client/* libraries
require "eth/client/http"
require "eth/client/http_basic"
require "eth/client/ipc"
73 changes: 73 additions & 0 deletions lib/eth/client/http_basic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Copyright (c) 2016-2022 The Ruby-Eth Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require "net/http"

# Provides the {Eth} module.
module Eth

# Provides an HTTP/S-RPC Basic client.
class Client::HttpBasic < Client

# The host of the HTTP endpoint.
attr_reader :host

# The port of the HTTP endpoint.
attr_reader :port

# The full URI of the HTTP endpoint, including path.
attr_reader :uri

# Attribute indicator for SSL.
attr_reader :ssl

# Attribute for user.
attr_reader :user

# Constructor for the HTTP Client. Should not be used; use
# {Client.create} intead.
#
# @param host [String] an URI pointing to an HTTP RPC-API.
def initialize(host)
super
uri = URI.parse(host)
raise ArgumentError, "Unable to parse the HTTP-URI!" unless ["http", "https"].include? uri.scheme
@host = uri.host
@port = uri.port
@ssl = uri.scheme == "https"
@user = uri.user
@password = uri.password
@uri = URI("#{uri.scheme}://#{uri.user}:#{uri.password}@#{@host}:#{@port}#{uri.path}")
end

# Sends an RPC request to the connected HTTP client.
#
# @param payload [Hash] the RPC request parameters.
# @return [String] a JSON-encoded response.
def send(payload)
http = Net::HTTP.new(@host, @port)
http.use_ssl = @ssl
header = { "Content-Type" => "application/json" }
request = Net::HTTP::Post.new(@uri, header)
request.body = payload
response = http.request(request)
response.body
end
end

private

# Attribute for password.
attr_reader :password
end
27 changes: 24 additions & 3 deletions spec/eth/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
describe Client do
let(:geth_dev_ipc_path) { "/tmp/geth.ipc" }
let(:geth_dev_http_path) { "http://127.0.0.1:8545" }
let(:geth_dev_http_basic_auth_path) { "http://username:password@127.0.0.1:8545" }
subject(:geth_dev_ipc) { Client.create geth_dev_ipc_path }
subject(:geth_dev_http) { Client.create geth_dev_http_path }
subject(:geth_dev_http_basic) { Client.create geth_dev_http_basic_auth_path }

describe ".create .initialize" do
it "creates an http client" do
it "creates an ipc client" do
expect(geth_dev_ipc).to be
expect(geth_dev_ipc).to be_instance_of Client::Ipc
expect(geth_dev_ipc.path).to eq geth_dev_ipc_path
end

it "creates an ipc client" do
it "creates an http client" do
expect(geth_dev_http).to be
expect(geth_dev_http).to be_instance_of Client::Http
expect(geth_dev_http.host).to eq "127.0.0.1"
Expand All @@ -25,6 +27,17 @@
expect(geth_dev_http.ssl).to be_falsy
end

it "creates a http basic auth client" do
expect(geth_dev_http_basic).to be
expect(geth_dev_http_basic).to be_instance_of Client::HttpBasic
expect(geth_dev_http_basic.host).to eq "127.0.0.1"
expect(geth_dev_http_basic.port).to eq 8545
expect(geth_dev_http_basic.uri.to_s).to eq geth_dev_http_basic_auth_path
expect(geth_dev_http_basic.user).to eq "username"
expect(geth_dev_http_basic.instance_variable_get(:@password)).to eq "password"
expect(geth_dev_http_basic.ssl).to be_falsy
end

it "functions as geth development client" do
expect(geth_dev_ipc.id).to eq 0
expect(geth_dev_ipc.chain_id).to eq Chain::PRIVATE_GETH
Expand All @@ -34,14 +47,22 @@
expect(geth_dev_ipc.gas_limit).to eq Tx::DEFAULT_GAS_LIMIT
end

it "can query basic methods" do
it "http can query basic methods" do

# the default account is prefunded; this test fails if you manually drain the account to zero
expect(geth_dev_http.get_balance geth_dev_http.default_account).to be > 0
expect(geth_dev_http.get_nonce geth_dev_http.default_account).to be >= 0
expect(geth_dev_http.reset_id).to eq 0
end

it "http basic can query basic methods" do

# the default account is prefunded; this test fails if you manually drain the account to zero
expect(geth_dev_http_basic.get_balance geth_dev_http.default_account).to be > 0
expect(geth_dev_http_basic.get_nonce geth_dev_http.default_account).to be >= 0
expect(geth_dev_http_basic.reset_id).to eq 0
end

it "does not create dysfunctional clients" do
expect { Client.create "ftp://127.0.0.1:8545" }.to raise_error ArgumentError, "Unable to detect client type!"
expect { Client.create "/home/user/fun.txt" }.to raise_error ArgumentError, "Unable to detect client type!"
Expand Down

0 comments on commit 57c3472

Please sign in to comment.