Skip to content

Commit

Permalink
Add REST API client implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalie committed Sep 5, 2023
1 parent 0cf7bff commit 4885086
Show file tree
Hide file tree
Showing 23 changed files with 540 additions and 21 deletions.
2 changes: 2 additions & 0 deletions .rubocop.yml
Expand Up @@ -6,9 +6,11 @@ require:
- rubocop-minitest

AllCops:
NewCops: enable
TargetRubyVersion: 3.0
Exclude:
- '*.gemspec'
- 'Gemfile'
- 'Rakefile'
- 'vendor/**/*'

Expand Down
5 changes: 5 additions & 0 deletions README.md
Expand Up @@ -4,3 +4,8 @@ This is the Ruby client for [LuaDNS REST API](https://www.luadns.com/api.html).


[![Build Status](https://github.com/luadns/luadns-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/luadns/luadns-ruby/actions/workflows/ci.yml)


Usage:

```
4 changes: 2 additions & 2 deletions Rakefile
Expand Up @@ -3,13 +3,13 @@ require 'rake/testtask'
require 'rdoc/task'

desc 'Default: run tests.'
task :default => :test
task default: :test


desc 'Run luadns unit tests.'
Rake::TestTask.new do |t|
t.libs << 'test'
t.libs << 'lib'
t.test_files = Dir[ 'test/*_test.rb' ]
t.test_files = Dir[ 'test/**/*_test.rb' ]
t.verbose = true
end
13 changes: 12 additions & 1 deletion lib/luadns.rb
@@ -1,7 +1,18 @@
# frozen_string_literal: true

module Luadns
BASE_URL = 'https://api.luadns.com/v1'
BASE_URL = 'https://api.luadns.com/v1'
JSON_MIME = 'application/json'
USER_AGENT = "luadns-ruby/#{VERSION}".freeze
end

require 'httparty'
require_relative 'luadns/errors'
require_relative 'luadns/schema'
require_relative 'luadns/schema/base'
require_relative 'luadns/schema/user'
require_relative 'luadns/schema/zone'
require_relative 'luadns/schema/record'
require_relative 'luadns/response'
require_relative 'luadns/http_client'
require_relative 'luadns/client'
105 changes: 99 additions & 6 deletions lib/luadns/client.rb
@@ -1,13 +1,106 @@
module Luadns
class Client
attr_reader :base_url
attr_reader :username
attr_reader :password
@@options = {
format: :json,
headers: {
'Accept' => JSON_MIME,
'Content-Type' => JSON_MIME,
'User-Agent' => USER_AGENT
}
}

def initialize(username, password, base_url = Luadns::BASE_URL)
attr_reader :http_client

def initialize(username, password, base_url = BASE_URL)
@http_client = HttpClient.new(request_options(username, password))
@base_url = base_url
@username = username
@password = password
end

# Gets current user.
def me
http_client.get(endpoint_url('/users/me')) do |response|
JSON.parse(response.body, object_class: Schema::User)
end
end

# Lists all zones.
def list_zones
http_client.get(endpoint_url('/zones')) do |response|
JSON.parse(response.body, object_class: Schema::Zone)
end
end

# Creates a zone.
def create_zone(attrs)
http_client.post(endpoint_url('/zones'), attrs) do |response|
JSON.parse(response.body, object_class: Schema::Zone)
end
end

# Gets a zone.
def get_zone(zone_id)
http_client.get(endpoint_url("/zones/#{zone_id}")) do |response|
JSON.parse(response.body, object_class: Schema::Zone)
end
end

# Updates a zone.
def update_zone(zone_id, attrs)
http_client.put(endpoint_url("/zones/#{zone_id}"), attrs) do |response|
JSON.parse(response.body, object_class: Schema::Zone)
end
end

# Deletes a zone.
def delete_zone(zone_id)
http_client.delete(endpoint_url("/zones/#{zone_id}")) do |response|
JSON.parse(response.body, object_class: Schema::Zone)
end
end

# Lists all zone records.
def list_records(zone)
http_client.get(endpoint_url("/zones/#{zone.id}/records")) do |response|
JSON.parse(response.body, object_class: Schema::Record)
end
end

# Creates a zone record.
def create_record(zone, attrs)
http_client.post(endpoint_url("/zones/#{zone.id}/records"), attrs) do |response|
JSON.parse(response.body, object_class: Schema::Record)
end
end

# Gets a zone record.
def get_record(zone, record_id)
http_client.get(endpoint_url("/zones/#{zone.id}/records/#{record_id}")) do |response|
JSON.parse(response.body, object_class: Schema::Record)
end
end

# Updates a zone record.
def update_record(zone, record_id, attrs)
http_client.put(endpoint_url("/zones/#{zone.id}/records/#{record_id}"), attrs) do |response|
JSON.parse(response.body, object_class: Schema::Record)
end
end

# Deletes a zone record.
def delete_record(zone, record_id)
http_client.delete(endpoint_url("/zones/#{zone.id}/records/#{record_id}")) do |response|
JSON.parse(response.body, object_class: Schema::Record)
end
end

protected

def request_options(username, password)
@@options.merge({ basic_auth: { username: username, password: password } })
end

def endpoint_url(path)
"#{@base_url}#{path}"
end
end
end
45 changes: 44 additions & 1 deletion lib/luadns/errors.rb
@@ -1,3 +1,46 @@
module Luadns
# class LuadnsError < RuntimeError; end
class NotFoundError < StandardError; end

class RequestError < StandardError
attr_reader :message

def initialize(response)
@message = JSON.parse(response.body)['message']
end
end

class AuthFailedError < RequestError; end

class ValidationError < RequestError
attr_reader :message

def initialize(response)
body = JSON.parse(response.body)
@message = body.map do |t|
fields = t['fieldNames']
message = t['message']
"#{fields.join(', ')}: #{message}"
end.join('; ')
end
end

class TooManyRequestsError < StandardError
attr_reader :code
attr_reader :reset

def initialize(response)
@code = response.code
@reset = response.headers['X-Ratelimit-Reset'].to_i
end
end

class ServerError < StandardError
attr_reader :code
attr_reader :content_type

def initialize(response)
@code = response.code
@content_type = response.headers['Content-Type']
end
end
end
61 changes: 61 additions & 0 deletions lib/luadns/http_client.rb
@@ -0,0 +1,61 @@
module Luadns
class HttpClient
def initialize(options = {})
@options = options
end

# Make a HTTP GET request.
def get(url, options = {})
yield http_request(:get, url, nil, request_options(options))
end

# Make a HTTP POST request.
def post(url, data = nil, options = {})
yield http_request(:post, url, data, request_options(options))
end

# Make a HTTP PUT request.
def put(url, data = nil, options = {})
yield http_request(:put, url, data, request_options(options))
end

# Make a HTTP DELETE request.
def delete(url, options = {})
yield http_request(:delete, url, nil, request_options(options))
end

private

def http_request(method, url, data = nil, options = {})
request_type = options.dig(:headers, 'Content-Type')
options = options.merge(body: encode_body(data, request_type)) if data
response = HTTParty.send(method, url, options)
case response.code
when 200
raise ServerError, response unless response.headers['Content-Type'].start_with?(JSON_MIME)

response
when 400
raise ValidationError, response
when 401
raise AuthFailedError, response
when 403
raise RequestError, response
when 404
raise NotFoundError, response
when 429
raise TooManyRequestsError, response
else
raise ServerError, response
end
end

def encode_body(data, content_type)
content_type == JSON_MIME ? JSON.dump(data) : data
end

def request_options(options)
@options.merge(options)
end
end
end
6 changes: 6 additions & 0 deletions lib/luadns/response.rb
@@ -0,0 +1,6 @@
module Luadns
class Response
attr_reader :status_code
attr_reader :body
end
end
4 changes: 0 additions & 4 deletions lib/luadns/schema.rb
Expand Up @@ -2,7 +2,3 @@ module Luadns
module Schema
end
end

require_relative 'schema/user'
require_relative 'schema/zone'
require_relative 'schema/record'
15 changes: 15 additions & 0 deletions lib/luadns/schema/base.rb
@@ -0,0 +1,15 @@
module Luadns
module Schema
class Base
def initialize(options = {})
options.each do |name, value|
send("#{name}=", value)
end
end

def []=(name, value)
send("#{name}=", value) if respond_to?(name)
end
end
end
end
2 changes: 1 addition & 1 deletion lib/luadns/schema/record.rb
@@ -1,6 +1,6 @@
module Luadns
module Schema
class Record
class Record < Base
attr_accessor :id
attr_accessor :name
attr_accessor :type
Expand Down
2 changes: 1 addition & 1 deletion lib/luadns/schema/user.rb
@@ -1,6 +1,6 @@
module Luadns
module Schema
class User
class User < Base
attr_accessor :email
attr_accessor :name
attr_accessor :repo_uri
Expand Down
2 changes: 1 addition & 1 deletion lib/luadns/schema/zone.rb
@@ -1,6 +1,6 @@
module Luadns
module Schema
class Zone
class Zone < Base
attr_accessor :id
attr_accessor :name
attr_accessor :created_at
Expand Down
2 changes: 2 additions & 0 deletions lib/luadns/version.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module Luadns
VERSION = '0.1'
end

0 comments on commit 4885086

Please sign in to comment.