|
11 | 11 | Gem.find_files('recombee_api_client/api/*.rb').each { |path| require path } |
12 | 12 |
|
13 | 13 | module RecombeeApiClient |
| 14 | + ## |
| 15 | + # Client for sending requests to Recombee recommender system |
14 | 16 | class RecombeeClient |
15 | 17 | include HTTParty |
16 | 18 |
|
17 | | - def initialize(account, token, options = {}) |
| 19 | + ## |
| 20 | + # - +account+ -> Name of your account at Recombee |
| 21 | + # - +token+ -> Secret token obtained from Recombee for signing requests |
| 22 | + # - +protocol+ -> Default protocol for sending requests. Possible values: 'http', 'https'. |
| 23 | + def initialize(account, token, protocol = 'http', options = {}) |
18 | 24 | @account = account |
19 | 25 | @token = token |
| 26 | + @protocol = protocol |
20 | 27 | @base_uri = ENV['RAPI_URI'] if ENV.key? 'RAPI_URI' |
21 | 28 | @base_uri||= options[:base_uri] |
22 | | - @base_uri||= 'https://rapi.recombee.com' |
| 29 | + @base_uri||= 'rapi.recombee.com' |
23 | 30 | end |
24 | 31 |
|
| 32 | + ## |
| 33 | + # - +request+ -> ApiRequest to be sent to Recombee recommender |
25 | 34 | def send(request) |
26 | | - @request = request |
27 | | - uri = request.path |
28 | | - uri.slice! ('/{databaseId}/') |
29 | | - uri = URI.escape uri |
30 | 35 | timeout = request.timeout / 1000 |
| 36 | + uri = process_request_uri(request) |
| 37 | + uri = sign_url(uri) |
| 38 | + protocol = request.ensure_https ? 'https' : @protocol |
| 39 | + uri = protocol + '://' + @base_uri + uri |
31 | 40 | # puts uri |
32 | 41 | begin |
33 | 42 | case request.method |
34 | 43 | when :put |
35 | | - hmac_put(uri, timeout) |
| 44 | + put(request, uri, timeout) |
36 | 45 | when :get |
37 | | - hmac_get(uri, timeout) |
| 46 | + get(request, uri, timeout) |
38 | 47 | when :post |
39 | | - hmac_post(uri, timeout, request.body_parameters.to_json) |
| 48 | + post(request, uri, timeout) |
40 | 49 | when :delete |
41 | | - hmac_delete(uri, timeout) |
| 50 | + delete(request, uri, timeout) |
42 | 51 | end |
43 | 52 | rescue Timeout::Error |
44 | | - fail ApiTimeout.new(@request) |
| 53 | + fail ApiTimeout.new(request) |
45 | 54 | end |
46 | 55 | end |
47 | 56 |
|
48 | 57 | private |
49 | 58 |
|
50 | | - def hmac_put(uri, timeout, options = {}) |
51 | | - r = self.class.put(sign_url(uri), query: options, timeout: timeout) |
52 | | - check_errors r |
53 | | - r.body |
| 59 | + def put(request, uri, timeout) |
| 60 | + response = self.class.put(uri, timeout: timeout) |
| 61 | + check_errors(response, request) |
| 62 | + response.body |
54 | 63 | end |
55 | 64 |
|
56 | | - def hmac_get(uri, timeout, options = {}) |
57 | | - r = self.class.get(sign_url(uri), query: options, timeout: timeout) |
58 | | - check_errors r |
59 | | - JSON.parse(r.body) |
| 65 | + def get(request, uri, timeout) |
| 66 | + response = self.class.get(uri, timeout: timeout) |
| 67 | + check_errors(response, request) |
| 68 | + JSON.parse(response.body) |
60 | 69 | end |
61 | 70 |
|
62 | | - def hmac_post(uri, timeout, options = {}) |
63 | | - url = sign_url(uri) |
| 71 | + def post(request, uri, timeout) |
64 | 72 | # pass arguments in body |
65 | | - r = self.class.post(url, body: options, |
| 73 | + response = self.class.post(uri, body: request.body_parameters.to_json, |
66 | 74 | headers: { 'Content-Type' => 'application/json' }, |
67 | 75 | timeout: timeout) |
68 | | - check_errors r |
| 76 | + check_errors(response, request) |
69 | 77 | begin |
70 | | - return JSON.parse(r.body) |
| 78 | + return JSON.parse(response.body) |
71 | 79 | rescue JSON::ParserError |
72 | | - return r.body |
| 80 | + return response.body |
73 | 81 | end |
74 | 82 | end |
75 | 83 |
|
76 | | - def hmac_delete(uri, timeout, options = {}) |
77 | | - r = self.class.delete(sign_url(uri), query: options, timeout: timeout) |
78 | | - check_errors r |
79 | | - r.body |
| 84 | + def delete(request, uri, timeout) |
| 85 | + response = self.class.delete(uri, timeout: timeout) |
| 86 | + check_errors(response, request) |
| 87 | + response.body |
80 | 88 | end |
81 | 89 |
|
82 | | - def check_errors(response) |
| 90 | + def check_errors(response, request) |
83 | 91 | status_code = response.code |
84 | 92 | return if status_code == 200 || status_code == 201 |
85 | | - fail ResponseError.new(@request, status_code, response.body) |
| 93 | + fail ResponseError.new(request, status_code, response.body) |
| 94 | + end |
| 95 | + |
| 96 | + def process_request_uri(request) |
| 97 | + uri = request.path |
| 98 | + uri.slice! ('/{databaseId}/') |
| 99 | + uri = URI.escape uri |
| 100 | + uri |
86 | 101 | end |
87 | 102 |
|
88 | 103 | # Sign request with HMAC, request URI must be exacly the same |
89 | 104 | # We have 30s to complete request with this token |
90 | | - def sign_url(req) |
91 | | - uri = "/#{@account}/#{req}" |
| 105 | + def sign_url(req_part) |
| 106 | + uri = "/#{@account}/#{req_part}" |
92 | 107 | time = hmac_time(uri) |
93 | 108 | sign = hmac_sign(uri, time) |
94 | | - @base_uri + uri + time + "&hmac_sign=#{sign}" |
| 109 | + res = uri + time + "&hmac_sign=#{sign}" |
| 110 | + res |
95 | 111 | end |
96 | 112 |
|
97 | 113 | def hmac_time(uri) |
|
0 commit comments