Class: DoiExtractor::IpumsClient

Inherits:
Object
  • Object
show all
Defined in:
lib/doi_extractor/ipums_client.rb

Constant Summary collapse

DEFAULT_READ_TIMEOUT =
120

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, username, password) ⇒ IpumsClient

Returns a new instance of IpumsClient.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/doi_extractor/ipums_client.rb', line 8

def initialize(uri, username, password)
  case uri
    when String
      @uri = URI(uri)
    when URI
      @uri = uri
    else
      raise 'Invalid uri'
  end

  raise("Invalid uri: #{uri}") unless @uri.is_a?(URI::HTTP)

  @username = username
  @password = password
end

Instance Attribute Details

#passwordObject (readonly)

Returns the value of attribute password.



6
7
8
# File 'lib/doi_extractor/ipums_client.rb', line 6

def password
  @password
end

#uriObject (readonly)

Returns the value of attribute uri.



6
7
8
# File 'lib/doi_extractor/ipums_client.rb', line 6

def uri
  @uri
end

#usernameObject (readonly)

Returns the value of attribute username.



6
7
8
# File 'lib/doi_extractor/ipums_client.rb', line 6

def username
  @username
end

Instance Method Details

#build_request(method, request_uri, params) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/doi_extractor/ipums_client.rb', line 118

def build_request(method, request_uri, params)
  case method.to_s.downcase
    when 'get'
      case params
        when Hash
          request_uri.query = URI.encode_www_form(params)
        when String
          request_uri.query = params
        when nil
          # Do nothing
        else
          raise ApiError, "Invalid GET params: #{params}"
      end
      Net::HTTP::Get.new(request_uri.request_uri)
    when 'post'
      r = Net::HTTP::Post.new(request_uri.request_uri)
      case params
        when Hash
          r.set_content_type('application/json')
          r.body = JSON.generate(params)
        when String
          r.set_content_type('application/json')
          r.body = params
        when nil
          # Do nothing
        else
          raise ApiError, "Invalid POST params: #{params}"
      end
      r
    else
      raise ApiError, "HTTP method #{method} not implemented"
  end
end

#cancel_doi_extract(id) ⇒ Object



44
45
46
47
# File 'lib/doi_extractor/ipums_client.rb', line 44

def cancel_doi_extract(id)
  res = post("api/extracts/v1/extract_request_groups/#{id}/cancel")
  parse_body(res)
end

#combine_uri_paths(*parts) ⇒ Object



114
115
116
# File 'lib/doi_extractor/ipums_client.rb', line 114

def combine_uri_paths(*parts)
  parts.compact.map(&:to_s).map(&:strip).map { |p| p.sub(/^\/+/, '').sub(/\/+$/, '') }.join('/')
end

#create_doi_extract(doi_version, year, email) ⇒ Object



24
25
26
27
# File 'lib/doi_extractor/ipums_client.rb', line 24

def create_doi_extract(doi_version, year, email)
  res = post('api/extracts/v1/extract_request_groups', {type: 'doi', year: year, doi_version: doi_version, email: email}, 600)
  parse_body(res)
end

#download_extract_file(file_path, extract_request_id, extension) ⇒ Object



54
55
56
57
58
59
# File 'lib/doi_extractor/ipums_client.rb', line 54

def download_extract_file(file_path, extract_request_id, extension)
  path = "api/extracts/v1/extract_requests/#{extract_request_id}/file/#{extension}"
  File.open(file_path, 'w') do |f|
    perform_request('get', path, nil, f, 600)
  end
end

#get(path, params = nil) ⇒ Object



61
62
63
64
65
# File 'lib/doi_extractor/ipums_client.rb', line 61

def get(path, params = nil)
  io = StringIO.new
  perform_request('get', path, params, io)
  io.string
end

#get_doi_extract(id) ⇒ Object



39
40
41
42
# File 'lib/doi_extractor/ipums_client.rb', line 39

def get_doi_extract(id)
  res = get("api/extracts/v1/extract_request_groups/#{id}")
  parse_body(res)
end

#parse_body(body) ⇒ Object



152
153
154
155
156
157
158
# File 'lib/doi_extractor/ipums_client.rb', line 152

def parse_body(body)
  if body && body != ''
    JSON.parse(body, object_class: OpenStruct)
  else
    nil
  end
end

#perform_request(method, path, params, response_io, read_timeout = DEFAULT_READ_TIMEOUT, redirect_limit = 5) ⇒ Object

Raises:



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/doi_extractor/ipums_client.rb', line 73

def perform_request(method, path, params, response_io, read_timeout = DEFAULT_READ_TIMEOUT, redirect_limit = 5)
  raise ApiError, 'too many HTTP redirects' if redirect_limit == 0

  request_uri = self.uri.dup
  request_uri.path = '/' + combine_uri_paths(request_uri.path, path)

  Net::HTTP.start(uri.host, uri.port, {use_ssl: uri.scheme == 'https'}) do |http|
    # in seconds
    http.read_timeout = read_timeout
    request = build_request(method, request_uri, params)

    request.basic_auth(username, password)
    request.add_field('Accept', 'application/json')

    redirect_location = nil

    http.request(request) do |response|
      case response
        when Net::HTTPSuccess
          response.read_body do |chunk|
            response_io.write chunk
          end
        when Net::HTTPRedirection
          redirect_location = response['location']
        when Net::HTTPUnprocessableEntity
          body = response.body
          body = body && body != '' ? JSON.parse(body) : nil
          msg = body.map { |k, v| "#{k}: #{v}" }.join(', ')
          raise ApiError, "API Server returned an error:  #{msg}"
        else
          raise ApiError, "Invalid API Server Response from [#{method.to_s.upcase} #{path}]: #{response.code} - #{response.message}"
      end
    end

    if redirect_location
      perform_request('get', redirect_location, nil, response_io, read_timeout, redirect_limit - 1)
    end

  end
end

#post(path, params = nil, read_timeout = DEFAULT_READ_TIMEOUT) ⇒ Object



67
68
69
70
71
# File 'lib/doi_extractor/ipums_client.rb', line 67

def post(path, params = nil, read_timeout = DEFAULT_READ_TIMEOUT)
  io = StringIO.new
  perform_request('post', path, params, io, read_timeout)
  io.string
end

#recent_doi_extractsObject



34
35
36
37
# File 'lib/doi_extractor/ipums_client.rb', line 34

def recent_doi_extracts
  res = get('api/extracts/v1/extract_request_groups/recent', {type: 'doi'})
  parse_body(res)
end

#submit_doi_extract(id) ⇒ Object



29
30
31
32
# File 'lib/doi_extractor/ipums_client.rb', line 29

def submit_doi_extract(id)
  res = post("api/extracts/v1/extract_request_groups/#{id}/submit")
  parse_body(res)
end

#submit_extract(id) ⇒ Object



49
50
51
52
# File 'lib/doi_extractor/ipums_client.rb', line 49

def submit_extract(id)
  res = post("api/extracts/v1/extract_requests/#{id}/submit")
  parse_body(res)
end