wovnrb 3.11.0 → 3.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,183 +1,186 @@
1
- require 'addressable'
2
- require 'digest'
3
- require 'json'
4
- require 'zlib'
5
-
6
- module Wovnrb
7
- class ApiTranslator
8
- def initialize(store, headers, uuid)
9
- @store = store
10
- @headers = headers
11
- @uuid = uuid
12
- end
13
-
14
- def translate(body)
15
- connection = prepare_connection
16
- request = prepare_request(body)
17
-
18
- begin
19
- response = connection.request(request)
20
- rescue => e
21
- WovnLogger.error("\"#{e.message}\" error occurred when contacting WOVNio translation API")
22
- return body
23
- end
24
-
25
- case response
26
- when Net::HTTPSuccess
27
- begin
28
- raw_response_body = @store.dev_mode? ? response.body : Zlib::GzipReader.new(StringIO.new(response.body)).read
29
- rescue Zlib::GzipFile::Error
30
- raw_response_body = response.body
31
- end
32
-
33
- begin
34
- JSON.parse(raw_response_body)['body'] || body
35
- rescue JSON::JSONError
36
- body
37
- end
38
- else
39
- WovnLogger.error("HTML-swapper call failed. Received \"#{response.message}\" from WOVNio translation API.")
40
- body
41
- end
42
- end
43
-
44
- private
45
-
46
- def prepare_connection
47
- connection = Net::HTTP.new(api_uri.host, api_uri.port)
48
-
49
- connection.open_timeout = api_timeout
50
- connection.read_timeout = api_timeout
51
-
52
- connection
53
- end
54
-
55
- def prepare_request(body)
56
- if @store.compress_api_requests?
57
- gzip_request(body)
58
- else
59
- json_request(body)
60
- end
61
- end
62
-
63
- def gzip_request(html_body)
64
- api_params = build_api_params(html_body)
65
- compressed_body = compress_request_data(api_params.to_json)
66
- request = Net::HTTP::Post.new(request_path(html_body), {
67
- 'Accept-Encoding' => 'gzip',
68
- 'Content-Type' => 'application/json',
69
- 'Content-Encoding' => 'gzip',
70
- 'Content-Length' => compressed_body.bytesize.to_s,
71
- 'X-Request-Id' => @uuid
72
- })
73
- request.body = compressed_body
74
-
75
- request
76
- end
77
-
78
- def json_request(html_body)
79
- api_params = build_api_params(html_body)
80
- request = Net::HTTP::Post.new(request_path(html_body), {
81
- 'Accept-Encoding' => 'gzip',
82
- 'Content-Type' => 'application/json',
83
- 'X-Request-Id' => @uuid
84
- })
85
- request.body = api_params.to_json
86
-
87
- request
88
- end
89
-
90
- def request_path(body)
91
- "#{api_uri.path}/translation?cache_key=#{cache_key(body)}"
92
- end
93
-
94
- def cache_key(body)
95
- cache_key_components = {
96
- 'token' => token,
97
- 'settings_hash' => settings_hash,
98
- 'body_hash' => Digest::MD5.hexdigest(body),
99
- 'path' => page_pathname,
100
- 'lang' => lang_code,
101
- 'version' => "wovnrb_#{VERSION}"
102
- }.map { |k, v| "#{k}=#{v}" }.join('&')
103
-
104
- CGI.escape("(#{cache_key_components})")
105
- end
106
-
107
- def build_api_params(body)
108
- result = {
109
- 'url' => page_url,
110
- 'token' => token,
111
- 'lang_code' => lang_code,
112
- 'url_pattern' => url_pattern,
113
- 'lang_param_name' => lang_param_name,
114
- 'translate_canonical_tag' => translate_canonical_tag,
115
- 'insert_hreflangs' => insert_hreflangs,
116
- 'product' => 'WOVN.rb',
117
- 'version' => VERSION,
118
- 'body' => body
119
- }
120
-
121
- result['custom_lang_aliases'] = JSON.dump(custom_lang_aliases) unless custom_lang_aliases.empty?
122
- result['custom_domain_langs'] = JSON.dump(custom_domain_langs) unless custom_domain_langs.empty?
123
-
124
- result
125
- end
126
-
127
- def compress_request_data(data_hash)
128
- ActiveSupport::Gzip.compress(data_hash)
129
- end
130
-
131
- def api_uri
132
- Addressable::URI.parse("#{@store.settings['api_url']}/v0")
133
- end
134
-
135
- def api_timeout
136
- @headers.search_engine_bot? ? @store.settings['api_timeout_search_engine_bots'] : @store.settings['api_timeout_seconds']
137
- end
138
-
139
- def settings_hash
140
- Digest::MD5.hexdigest(JSON.dump(@store.settings))
141
- end
142
-
143
- def token
144
- @store.settings['project_token']
145
- end
146
-
147
- def lang_code
148
- @headers.lang_code
149
- end
150
-
151
- def url_pattern
152
- @store.settings['url_pattern']
153
- end
154
-
155
- def lang_param_name
156
- @store.settings['lang_param_name']
157
- end
158
-
159
- def custom_lang_aliases
160
- @store.settings['custom_lang_aliases']
161
- end
162
-
163
- def translate_canonical_tag
164
- @store.settings['translate_canonical_tag']
165
- end
166
-
167
- def insert_hreflangs
168
- @store.settings['insert_hreflangs']
169
- end
170
-
171
- def custom_domain_langs
172
- @store.custom_domain_langs.to_html_swapper_hash
173
- end
174
-
175
- def page_url
176
- "#{@headers.protocol}://#{@headers.url}"
177
- end
178
-
179
- def page_pathname
180
- @headers.pathname_with_trailing_slash_if_present
181
- end
182
- end
183
- end
1
+ require 'addressable'
2
+ require 'digest'
3
+ require 'json'
4
+ require 'zlib'
5
+
6
+ module Wovnrb
7
+ class ApiTranslator
8
+ def initialize(store, headers, uuid, response_status_code)
9
+ @store = store
10
+ @headers = headers
11
+ @uuid = uuid
12
+ @response_status_code = response_status_code
13
+ end
14
+
15
+ def translate(body)
16
+ connection = prepare_connection
17
+ request = prepare_request(body)
18
+
19
+ begin
20
+ response = connection.request(request)
21
+ rescue => e
22
+ WovnLogger.error("\"#{e.message}\" error occurred when contacting WOVNio translation API")
23
+ return body
24
+ end
25
+
26
+ case response
27
+ when Net::HTTPSuccess
28
+ begin
29
+ raw_response_body = @store.dev_mode? ? response.body : Zlib::GzipReader.new(StringIO.new(response.body)).read
30
+ rescue Zlib::GzipFile::Error
31
+ raw_response_body = response.body
32
+ end
33
+
34
+ begin
35
+ JSON.parse(raw_response_body)['body'] || body
36
+ rescue JSON::JSONError
37
+ body
38
+ end
39
+ else
40
+ WovnLogger.error("HTML-swapper call failed. Received \"#{response.message}\" from WOVNio translation API.")
41
+ body
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def prepare_connection
48
+ connection = Net::HTTP.new(api_uri.host, api_uri.port)
49
+
50
+ connection.open_timeout = api_timeout
51
+ connection.read_timeout = api_timeout
52
+
53
+ connection
54
+ end
55
+
56
+ def prepare_request(body)
57
+ if @store.compress_api_requests?
58
+ gzip_request(body)
59
+ else
60
+ json_request(body)
61
+ end
62
+ end
63
+
64
+ def gzip_request(html_body)
65
+ api_params = build_api_params(html_body)
66
+ compressed_body = compress_request_data(api_params.to_json)
67
+ request = Net::HTTP::Post.new(request_path(html_body), {
68
+ 'Accept-Encoding' => 'gzip',
69
+ 'Content-Type' => 'application/json',
70
+ 'Content-Encoding' => 'gzip',
71
+ 'Content-Length' => compressed_body.bytesize.to_s,
72
+ 'X-Request-Id' => @uuid
73
+ })
74
+ request.body = compressed_body
75
+
76
+ request
77
+ end
78
+
79
+ def json_request(html_body)
80
+ api_params = build_api_params(html_body)
81
+ request = Net::HTTP::Post.new(request_path(html_body), {
82
+ 'Accept-Encoding' => 'gzip',
83
+ 'Content-Type' => 'application/json',
84
+ 'X-Request-Id' => @uuid
85
+ })
86
+ request.body = api_params.to_json
87
+
88
+ request
89
+ end
90
+
91
+ def request_path(body)
92
+ "#{api_uri.path}/translation?cache_key=#{cache_key(body)}"
93
+ end
94
+
95
+ def cache_key(body)
96
+ cache_key_components = {
97
+ 'token' => token,
98
+ 'settings_hash' => settings_hash,
99
+ 'body_hash' => Digest::MD5.hexdigest(body),
100
+ 'path' => page_pathname,
101
+ 'lang' => lang_code,
102
+ 'version' => "wovnrb_#{VERSION}"
103
+ }.map { |k, v| "#{k}=#{v}" }.join('&')
104
+
105
+ CGI.escape("(#{cache_key_components})")
106
+ end
107
+
108
+ def build_api_params(body)
109
+ result = {
110
+ 'url' => page_url,
111
+ 'token' => token,
112
+ 'lang_code' => lang_code,
113
+ 'url_pattern' => url_pattern,
114
+ 'lang_param_name' => lang_param_name,
115
+ 'translate_canonical_tag' => translate_canonical_tag,
116
+ 'insert_hreflangs' => insert_hreflangs,
117
+ 'hreflang_x_default_lang' => @store.settings['hreflang_x_default_lang'], # should not use fallback, so html swapper can calculate the default lang from js_data
118
+ 'product' => 'WOVN.rb',
119
+ 'version' => VERSION,
120
+ 'page_status_code' => @response_status_code,
121
+ 'body' => body
122
+ }
123
+
124
+ result['custom_lang_aliases'] = JSON.dump(custom_lang_aliases) unless custom_lang_aliases.empty?
125
+ result['custom_domain_langs'] = JSON.dump(custom_domain_langs) unless custom_domain_langs.empty?
126
+
127
+ result
128
+ end
129
+
130
+ def compress_request_data(data_hash)
131
+ ActiveSupport::Gzip.compress(data_hash)
132
+ end
133
+
134
+ def api_uri
135
+ Addressable::URI.parse("#{@store.settings['api_url']}/v0")
136
+ end
137
+
138
+ def api_timeout
139
+ @headers.search_engine_bot? ? @store.settings['api_timeout_search_engine_bots'] : @store.settings['api_timeout_seconds']
140
+ end
141
+
142
+ def settings_hash
143
+ Digest::MD5.hexdigest(JSON.dump(@store.settings))
144
+ end
145
+
146
+ def token
147
+ @store.settings['project_token']
148
+ end
149
+
150
+ def lang_code
151
+ @headers.lang_code
152
+ end
153
+
154
+ def url_pattern
155
+ @store.settings['url_pattern']
156
+ end
157
+
158
+ def lang_param_name
159
+ @store.settings['lang_param_name']
160
+ end
161
+
162
+ def custom_lang_aliases
163
+ @store.settings['custom_lang_aliases']
164
+ end
165
+
166
+ def translate_canonical_tag
167
+ @store.settings['translate_canonical_tag']
168
+ end
169
+
170
+ def insert_hreflangs
171
+ @store.settings['insert_hreflangs']
172
+ end
173
+
174
+ def custom_domain_langs
175
+ @store.custom_domain_langs.to_html_swapper_hash
176
+ end
177
+
178
+ def page_url
179
+ "#{@headers.protocol}://#{@headers.url}"
180
+ end
181
+
182
+ def page_pathname
183
+ @headers.pathname_with_trailing_slash_if_present
184
+ end
185
+ end
186
+ end