contactology 0.0.1

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.
Files changed (86) hide show
  1. data/.gitignore +5 -0
  2. data/.infinity_test +16 -0
  3. data/.rspec +3 -0
  4. data/.rvmrc +41 -0
  5. data/.watchr +36 -0
  6. data/Gemfile +6 -0
  7. data/Rakefile +1 -0
  8. data/contactology.gemspec +28 -0
  9. data/lib/contactology.rb +125 -0
  10. data/lib/contactology/api.rb +80 -0
  11. data/lib/contactology/basic_object.rb +21 -0
  12. data/lib/contactology/campaign.rb +127 -0
  13. data/lib/contactology/campaign/preview.rb +11 -0
  14. data/lib/contactology/campaigns.rb +2 -0
  15. data/lib/contactology/campaigns/standard.rb +80 -0
  16. data/lib/contactology/campaigns/transactional.rb +58 -0
  17. data/lib/contactology/configuration.rb +42 -0
  18. data/lib/contactology/contact.rb +193 -0
  19. data/lib/contactology/errors.rb +4 -0
  20. data/lib/contactology/issue.rb +24 -0
  21. data/lib/contactology/issues.rb +18 -0
  22. data/lib/contactology/list.rb +192 -0
  23. data/lib/contactology/list_proxy.rb +25 -0
  24. data/lib/contactology/parser.rb +5 -0
  25. data/lib/contactology/send_result.rb +35 -0
  26. data/lib/contactology/stash.rb +29 -0
  27. data/lib/contactology/transactional_message.rb +38 -0
  28. data/lib/contactology/version.rb +3 -0
  29. data/spec/factories/campaigns.rb +18 -0
  30. data/spec/factories/contacts.rb +3 -0
  31. data/spec/factories/issues.rb +9 -0
  32. data/spec/factories/lists.rb +3 -0
  33. data/spec/factories/transactional_messages.rb +5 -0
  34. data/spec/fixtures/net/campaign/destroy.yml +246 -0
  35. data/spec/fixtures/net/campaign/find/failure.yml +36 -0
  36. data/spec/fixtures/net/campaign/find/success.yml +176 -0
  37. data/spec/fixtures/net/campaign/find_by_name/failure.yml +36 -0
  38. data/spec/fixtures/net/campaign/find_by_name/success.yml +211 -0
  39. data/spec/fixtures/net/campaign/preview.yml +106 -0
  40. data/spec/fixtures/net/campaigns/standard/create/failure.yml +106 -0
  41. data/spec/fixtures/net/campaigns/standard/create/invalid.yml +141 -0
  42. data/spec/fixtures/net/campaigns/standard/create/success.yml +176 -0
  43. data/spec/fixtures/net/campaigns/standard/send_campaign/failure.yml +316 -0
  44. data/spec/fixtures/net/campaigns/standard/send_campaign/success.yml +316 -0
  45. data/spec/fixtures/net/campaigns/transactional/create/failure.yml +36 -0
  46. data/spec/fixtures/net/campaigns/transactional/create/success.yml +71 -0
  47. data/spec/fixtures/net/contact/active.yml +106 -0
  48. data/spec/fixtures/net/contact/change_email/success.yml +176 -0
  49. data/spec/fixtures/net/contact/change_email/unknown.yml +36 -0
  50. data/spec/fixtures/net/contact/create.yml +106 -0
  51. data/spec/fixtures/net/contact/destroy.yml +141 -0
  52. data/spec/fixtures/net/contact/find/active.yml +106 -0
  53. data/spec/fixtures/net/contact/find/suppressed.yml +141 -0
  54. data/spec/fixtures/net/contact/find/unknown.yml +36 -0
  55. data/spec/fixtures/net/contact/lists/empty.yml +106 -0
  56. data/spec/fixtures/net/contact/lists/full.yml +246 -0
  57. data/spec/fixtures/net/contact/lists/unknown.yml +71 -0
  58. data/spec/fixtures/net/contact/suppress.yml +141 -0
  59. data/spec/fixtures/net/list/all.yml +141 -0
  60. data/spec/fixtures/net/list/create.yml +106 -0
  61. data/spec/fixtures/net/list/destroy.yml +176 -0
  62. data/spec/fixtures/net/list/find/success.yml +141 -0
  63. data/spec/fixtures/net/list/find/unknown.yml +36 -0
  64. data/spec/fixtures/net/list/import/success.yml +351 -0
  65. data/spec/fixtures/net/list/subscribe/success.yml +211 -0
  66. data/spec/fixtures/net/list/unsubscribe/success.yml +246 -0
  67. data/spec/fixtures/net/transactional_message/send_message/failure.yml +176 -0
  68. data/spec/fixtures/net/transactional_message/send_message/success.yml +176 -0
  69. data/spec/models/contactology/api_spec.rb +51 -0
  70. data/spec/models/contactology/campaign_spec.rb +75 -0
  71. data/spec/models/contactology/campaigns/standard_spec.rb +84 -0
  72. data/spec/models/contactology/campaigns/transactional_spec.rb +28 -0
  73. data/spec/models/contactology/configuration_spec.rb +29 -0
  74. data/spec/models/contactology/contact_spec.rb +175 -0
  75. data/spec/models/contactology/issues_spec.rb +34 -0
  76. data/spec/models/contactology/list_spec.rb +125 -0
  77. data/spec/models/contactology/send_result_spec.rb +65 -0
  78. data/spec/models/contactology/stash_spec.rb +65 -0
  79. data/spec/models/contactology/transactional_message_spec.rb +65 -0
  80. data/spec/models/contactology_spec.rb +67 -0
  81. data/spec/requests/contacts_spec.rb +4 -0
  82. data/spec/spec_helper.rb +15 -0
  83. data/spec/support/contactology.rb +34 -0
  84. data/spec/support/factory_girl.rb +19 -0
  85. data/spec/support/vcr.rb +11 -0
  86. metadata +282 -0
@@ -0,0 +1,25 @@
1
+ require 'contactology/basic_object'
2
+ require 'contactology/list'
3
+
4
+ module Contactology
5
+ class ListProxy < ::Contactology::BasicObject
6
+ attr_reader :list_id
7
+
8
+ def initialize(list_id)
9
+ @list_id = list_id
10
+ end
11
+
12
+
13
+ private
14
+
15
+
16
+ def get_list(id)
17
+ List.find(id)
18
+ end
19
+
20
+ def method_missing(method, *args, &block)
21
+ @list ||= get_list(list_id)
22
+ @list.send(method, *args, &block) if @list
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module Contactology
2
+ class Parser < HTTParty::Parser
3
+ SupportedFormats.merge!({'text/plain' => :json})
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ require 'contactology/issues'
2
+
3
+ module Contactology
4
+ ##
5
+ # Contains the campaign send request results which indicate success or
6
+ # failure, as well as any issues found with the campaign.
7
+ #
8
+ class SendResult
9
+ attr_reader :issues
10
+
11
+ def initialize(response)
12
+ @success = response['success']
13
+ @issues = Issues.new(response['issues'])
14
+ end
15
+
16
+ ##
17
+ # Public: Indicates whether or not the send was successful
18
+ #
19
+ # Returns true when successful.
20
+ # Returns false when unsuccessful.
21
+ #
22
+ def successful?
23
+ !!@success
24
+ end
25
+
26
+ ##
27
+ # Public: Returns the spam score of the campaign.
28
+ #
29
+ # Returns a numeric from 0 to 100 (where higher is better).
30
+ #
31
+ def score
32
+ @issues.score
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ require 'hashie/trash'
2
+
3
+ module Contactology
4
+ ##
5
+ # A Stash is a 'suppressing' Hashie::Trash where keys that are not defined
6
+ # are simply ignored and unavailable to the local object.
7
+ #
8
+ # A Stash is useful when you need to read data from another application,
9
+ # but you only want a predefined subset of the returned data to become
10
+ # available, locally.
11
+ #
12
+ class Stash < ::Hashie::Trash
13
+ def []=(property, value)
14
+ if self.class.translations.include? property.to_sym
15
+ send("#{property}=", value)
16
+ elsif property_exists? property
17
+ super
18
+ end
19
+ end
20
+
21
+
22
+ private
23
+
24
+
25
+ def property_exists?(property)
26
+ self.class.property?(property.to_sym)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,38 @@
1
+ require 'contactology/stash'
2
+
3
+ module Contactology
4
+ class TransactionalMessage < Contactology::Stash
5
+ extend API
6
+
7
+ property :campaign, :required => true
8
+ property :contact, :required => true
9
+ property :source, :required => true
10
+ property :replacements, :required => true
11
+
12
+ def replacements
13
+ self['replacements'] || Hash.new
14
+ end
15
+
16
+ def send_message(options = {})
17
+ self.class.query('Campaign_Send_Transactional', options.merge({
18
+ 'campaignId' => campaign.id,
19
+ 'contact' => normalize_contact(contact),
20
+ 'source' => source,
21
+ 'replacements' => {:_contactology => 'Contactology'}.merge(replacements),
22
+ :on_error => false,
23
+ :on_timeout => false,
24
+ :on_success => true
25
+ }))
26
+ end
27
+
28
+
29
+ private
30
+
31
+
32
+ def normalize_contact(contact)
33
+ return contact if contact.kind_of?(Hash)
34
+
35
+ { 'email' => contact.email }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module Contactology
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,18 @@
1
+ Factory.define :standard_campaign, :class => Contactology::Campaigns::Standard do |c|
2
+ c.content 'text' => 'This is a good message! {COMPANY_ADDRESS}'
3
+ c.name 'factory campaign'
4
+ c.recipients { Factory.build_via_new :list }
5
+ c.sender_email 'nate@envylabs.com'
6
+ c.sender_name 'Nate Bibler'
7
+ c.subject 'Factory Campaign Message'
8
+ end
9
+
10
+ Factory.define :transactional_campaign, :class => Contactology::Campaigns::Transactional do |c|
11
+ c.content 'text' => 'This is a good email. {COMPANY_ADDRESS}'
12
+ c.name 'factory campaign'
13
+ c.sender_email 'sender@example.com'
14
+ c.sender_name 'Sender Example'
15
+ c.subject 'Test Creation'
16
+ c.test_contact 'email' => 'test-contact@example.com'
17
+ c.test_replacements 'first_name' => 'John'
18
+ end
@@ -0,0 +1,3 @@
1
+ Factory.define :contact, :class => Contactology::Contact do |c|
2
+ c.email 'factory-contact@example.com'
3
+ end
@@ -0,0 +1,9 @@
1
+ Factory.define :issue, :class => Contactology::Issue do |i|
2
+ i.level ''
3
+ i.type 'SPAM'
4
+ i.text 'BODY: TVD_SPACE_RATIO'
5
+ i.message ''
6
+ i.context ''
7
+ i.col ''
8
+ i.deduction 29
9
+ end
@@ -0,0 +1,3 @@
1
+ Factory.define :list, :class => Contactology::List do |l|
2
+ l.name 'Factory List'
3
+ end
@@ -0,0 +1,5 @@
1
+ Factory.define :transactional_message, :class => Contactology::TransactionalMessage do |m|
2
+ m.campaign { Factory.build_via_new :transactional_campaign }
3
+ m.contact { Factory.attributes_for :contact }
4
+ m.source 'Factory Created'
5
+ end
@@ -0,0 +1,246 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: https://api.emailcampaigns.net:443/2/REST/?key=%{API_KEY}&method=List_Add_Public&name=Factory%20List
6
+ body:
7
+ headers:
8
+ accept:
9
+ - application/json
10
+ user-agent:
11
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ x-powered-by:
18
+ - PHP/5.2.10
19
+ set-cookie:
20
+ - PHPSESSID=6a8cdfd44b31c3d7987dd6492f075491; path=/
21
+ expires:
22
+ - Thu, 19 Nov 1981 08:52:00 GMT
23
+ cache-control:
24
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
25
+ pragma:
26
+ - no-cache
27
+ content-type:
28
+ - text/plain;charset=UTF-8
29
+ transfer-encoding:
30
+ - chunked
31
+ date:
32
+ - Wed, 03 Aug 2011 18:23:53 GMT
33
+ server:
34
+ - lighttpd/1.4.28
35
+ body: "46"
36
+ http_version: "1.1"
37
+ - !ruby/struct:VCR::HTTPInteraction
38
+ request: !ruby/struct:VCR::Request
39
+ method: :get
40
+ uri: https://api.emailcampaigns.net:443/2/REST/?key=%{API_KEY}&listId=46&method=List_Get_Info
41
+ body:
42
+ headers:
43
+ accept:
44
+ - application/json
45
+ user-agent:
46
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
47
+ response: !ruby/struct:VCR::Response
48
+ status: !ruby/struct:VCR::ResponseStatus
49
+ code: 200
50
+ message: OK
51
+ headers:
52
+ x-powered-by:
53
+ - PHP/5.2.10
54
+ set-cookie:
55
+ - PHPSESSID=295f4ba34b7f033e8cad0c6cf83b9b75; path=/
56
+ expires:
57
+ - Thu, 19 Nov 1981 08:52:00 GMT
58
+ cache-control:
59
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
60
+ pragma:
61
+ - no-cache
62
+ content-type:
63
+ - text/plain;charset=UTF-8
64
+ transfer-encoding:
65
+ - chunked
66
+ date:
67
+ - Wed, 03 Aug 2011 18:23:57 GMT
68
+ server:
69
+ - lighttpd/1.4.28
70
+ body: "{\"listId\":\"46\",\"name\":\"Factory List\",\"description\":null,\"type\":\"public\",\"optIn\":false}"
71
+ http_version: "1.1"
72
+ - !ruby/struct:VCR::HTTPInteraction
73
+ request: !ruby/struct:VCR::Request
74
+ method: :get
75
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignName=factory%20campaign&key=%{API_KEY}&method=Campaign_Create_Standard&senderEmail=nate@envylabs.com&senderName=Nate%20Bibler&subject=Factory%20Campaign%20Message&content%5Btext%5D=This%20is%20a%20good%20message!%20%7BCOMPANY_ADDRESS%7D&recipients%5Blist%5D=46
76
+ body:
77
+ headers:
78
+ accept:
79
+ - application/json
80
+ user-agent:
81
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
82
+ response: !ruby/struct:VCR::Response
83
+ status: !ruby/struct:VCR::ResponseStatus
84
+ code: 200
85
+ message: OK
86
+ headers:
87
+ x-powered-by:
88
+ - PHP/5.2.10
89
+ set-cookie:
90
+ - PHPSESSID=3b70f5bce9c49f9029c6ff3472b58274; path=/
91
+ expires:
92
+ - Thu, 19 Nov 1981 08:52:00 GMT
93
+ cache-control:
94
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
95
+ pragma:
96
+ - no-cache
97
+ content-type:
98
+ - text/plain;charset=UTF-8
99
+ transfer-encoding:
100
+ - chunked
101
+ date:
102
+ - Wed, 03 Aug 2011 18:23:58 GMT
103
+ server:
104
+ - lighttpd/1.4.28
105
+ body: "33"
106
+ http_version: "1.1"
107
+ - !ruby/struct:VCR::HTTPInteraction
108
+ request: !ruby/struct:VCR::Request
109
+ method: :get
110
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignId=33&key=%{API_KEY}&method=Campaign_Get_Info
111
+ body:
112
+ headers:
113
+ accept:
114
+ - application/json
115
+ user-agent:
116
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
117
+ response: !ruby/struct:VCR::Response
118
+ status: !ruby/struct:VCR::ResponseStatus
119
+ code: 200
120
+ message: OK
121
+ headers:
122
+ x-powered-by:
123
+ - PHP/5.2.10
124
+ set-cookie:
125
+ - PHPSESSID=f0b1859e137c96c71fa9dacdf108536e; path=/
126
+ expires:
127
+ - Thu, 19 Nov 1981 08:52:00 GMT
128
+ cache-control:
129
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
130
+ pragma:
131
+ - no-cache
132
+ content-type:
133
+ - text/plain;charset=UTF-8
134
+ transfer-encoding:
135
+ - chunked
136
+ date:
137
+ - Wed, 03 Aug 2011 18:23:59 GMT
138
+ server:
139
+ - lighttpd/1.4.28
140
+ body: "{\"campaignId\":\"33\",\"campaignName\":\"factory campaign\",\"type\":\"standard\",\"contentType\":\"standard\",\"status\":\"draft\",\"recipients\":{\"list\":[\"46\"]},\"subject\":\"Factory Campaign Message\",\"senderName\":\"Nate Bibler\",\"senderEmail\":\"nate@envylabs.com\",\"recipientName\":\"\",\"replyToName\":\"\",\"replyToEmail\":null,\"content\":{\"html\":\"\",\"text\":\"This is a good message! {COMPANY_ADDRESS}\"},\"startTime\":\"2011-08-03 18:23:58\",\"authenticate\":false,\"trackReplies\":false,\"showInArchive\":false,\"viewInBrowser\":false,\"trackOpens\":true,\"trackClickThruHTML\":true,\"trackClickThruText\":true,\"googleAnalyticsName\":null,\"automaticTweet\":false,\"clickTaleName\":null,\"clickTaleCustomFields\":[\"\"],\"useCustomUrlParameters\":null,\"customUrlParameters\":null}"
141
+ http_version: "1.1"
142
+ - !ruby/struct:VCR::HTTPInteraction
143
+ request: !ruby/struct:VCR::Request
144
+ method: :get
145
+ uri: https://api.emailcampaigns.net:443/2/REST/?key=%{API_KEY}&listId=46&method=List_Delete
146
+ body:
147
+ headers:
148
+ accept:
149
+ - application/json
150
+ user-agent:
151
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
152
+ response: !ruby/struct:VCR::Response
153
+ status: !ruby/struct:VCR::ResponseStatus
154
+ code: 200
155
+ message: OK
156
+ headers:
157
+ x-powered-by:
158
+ - PHP/5.2.10
159
+ set-cookie:
160
+ - PHPSESSID=84399ae8907f376ee7017cb061cb3b3f; path=/
161
+ expires:
162
+ - Thu, 19 Nov 1981 08:52:00 GMT
163
+ cache-control:
164
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
165
+ pragma:
166
+ - no-cache
167
+ content-type:
168
+ - text/plain;charset=UTF-8
169
+ transfer-encoding:
170
+ - chunked
171
+ date:
172
+ - Wed, 03 Aug 2011 18:24:00 GMT
173
+ server:
174
+ - lighttpd/1.4.28
175
+ body: "true"
176
+ http_version: "1.1"
177
+ - !ruby/struct:VCR::HTTPInteraction
178
+ request: !ruby/struct:VCR::Request
179
+ method: :get
180
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignId=33&key=%{API_KEY}&method=Campaign_Delete
181
+ body:
182
+ headers:
183
+ accept:
184
+ - application/json
185
+ user-agent:
186
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
187
+ response: !ruby/struct:VCR::Response
188
+ status: !ruby/struct:VCR::ResponseStatus
189
+ code: 200
190
+ message: OK
191
+ headers:
192
+ x-powered-by:
193
+ - PHP/5.2.10
194
+ set-cookie:
195
+ - PHPSESSID=fb7cd68453b20088187ed9db9ef0a4ff; path=/
196
+ expires:
197
+ - Thu, 19 Nov 1981 08:52:00 GMT
198
+ cache-control:
199
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
200
+ pragma:
201
+ - no-cache
202
+ content-type:
203
+ - text/plain;charset=UTF-8
204
+ transfer-encoding:
205
+ - chunked
206
+ date:
207
+ - Wed, 03 Aug 2011 18:24:00 GMT
208
+ server:
209
+ - lighttpd/1.4.28
210
+ body: "true"
211
+ http_version: "1.1"
212
+ - !ruby/struct:VCR::HTTPInteraction
213
+ request: !ruby/struct:VCR::Request
214
+ method: :get
215
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignId=33&key=%{API_KEY}&method=Campaign_Get_Info
216
+ body:
217
+ headers:
218
+ accept:
219
+ - application/json
220
+ user-agent:
221
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
222
+ response: !ruby/struct:VCR::Response
223
+ status: !ruby/struct:VCR::ResponseStatus
224
+ code: 200
225
+ message: OK
226
+ headers:
227
+ x-powered-by:
228
+ - PHP/5.2.10
229
+ set-cookie:
230
+ - PHPSESSID=518ac479af356a6ffd117517bb197180; path=/
231
+ expires:
232
+ - Thu, 19 Nov 1981 08:52:00 GMT
233
+ cache-control:
234
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
235
+ pragma:
236
+ - no-cache
237
+ content-type:
238
+ - text/plain;charset=UTF-8
239
+ transfer-encoding:
240
+ - chunked
241
+ date:
242
+ - Wed, 03 Aug 2011 18:24:01 GMT
243
+ server:
244
+ - lighttpd/1.4.28
245
+ body: "{\"result\":\"error\",\"message\":\"Input Error: campaignId 33 not found\",\"code\":601}"
246
+ http_version: "1.1"
@@ -0,0 +1,36 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignId=123456789&key=%{API_KEY}&method=Campaign_Get_Info
6
+ body:
7
+ headers:
8
+ accept:
9
+ - application/json
10
+ user-agent:
11
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ x-powered-by:
18
+ - PHP/5.2.10
19
+ set-cookie:
20
+ - PHPSESSID=891a04fa52890eb18f50ca10b699a8d1; path=/
21
+ expires:
22
+ - Thu, 19 Nov 1981 08:52:00 GMT
23
+ cache-control:
24
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
25
+ pragma:
26
+ - no-cache
27
+ content-type:
28
+ - text/plain;charset=UTF-8
29
+ transfer-encoding:
30
+ - chunked
31
+ date:
32
+ - Wed, 03 Aug 2011 18:24:35 GMT
33
+ server:
34
+ - lighttpd/1.4.28
35
+ body: "{\"result\":\"error\",\"message\":\"Input Error: campaignId 123456789 not found\",\"code\":601}"
36
+ http_version: "1.1"