eval_in 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/eval_in.rb CHANGED
@@ -11,7 +11,7 @@ module EvalIn
11
11
  ResultNotFound = Class.new EvalInError
12
12
 
13
13
  # @example Generated with
14
- # curl https://eval.in | ruby -rnokogiri -e 'puts Nokogiri::HTML($stdin.read).css("option").map { |o| o["value"] }'
14
+ # nokogiri https://eval.in -e 'puts $_.xpath("//option/@value")'
15
15
  KNOWN_LANGUAGES = %w[
16
16
  c/gcc-4.4.3
17
17
  c/gcc-4.9.1
@@ -81,38 +81,29 @@ module EvalIn
81
81
  # result = EvalIn.call 'puts "hello, #{gets}"', stdin: 'world', language: "ruby/mri-2.1"
82
82
  # result.output # => "hello, world\n"
83
83
  def self.call(code, options={})
84
- fetch_result post_code(code, options)
84
+ url = post_code(code, options)
85
+ fetch_result url, options
85
86
  end
86
87
 
87
88
  # @param url [String] the url with the result
89
+ # @option options [String] :context Will be included in the user agent
88
90
  #
89
91
  # @example
90
92
  # result = EvalIn.fetch_result "https://eval.in/147.json"
91
93
  # result.output # => "Hello Charlie! "
92
- def self.fetch_result(url)
93
- build_result fetch_result_json jsonify_url url
94
+ def self.fetch_result(raw_url, options={})
95
+ raw_json_url = jsonify_url(raw_url)
96
+ build_result fetch_result_json(raw_json_url, options)
94
97
  end
95
98
 
96
99
  # @api private
97
100
  def self.post_code(code, options)
98
- uri = URI(options.fetch(:url, "https://eval.in/"))
101
+ url = options.fetch(:url, "https://eval.in/")
99
102
  input = options.fetch(:stdin, "")
100
103
  language = options.fetch(:language) { raise ArgumentError, ":language is mandatory, but options only has #{options.keys.inspect}" }
101
- user_agent = 'http://rubygems.org/gems/eval_in'
102
- user_agent << " (#{options[:context]})" if options[:context]
103
- path = uri.path
104
- path = '/' if path.empty?
105
-
106
- # stole this out of implementation for post_form https://github.com/ruby/ruby/blob/2afed6eceff2951b949db7ded8167a75b431bad6/lib/net/http.rb#L503
107
- request = Net::HTTP::Post.new(path)
108
- request.form_data = {"utf8" => "√", "code" => code, "execute" => "on", "lang" => language, "input" => input}
109
- request['User-Agent'] = user_agent
110
- request.basic_auth uri.user, uri.password if uri.user
111
- net = Net::HTTP.new(uri.hostname, uri.port)
112
- # net.set_debug_output $stdout
113
- result = Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) { |http|
114
- http.request(request)
115
- }
104
+ form_data = {"utf8" => "√", "code" => code, "execute" => "on", "lang" => language, "input" => input}
105
+
106
+ result = post_request url, form_data, user_agent_for(options[:context])
116
107
 
117
108
  if result.code == '302'
118
109
  jsonify_url result['location']
@@ -125,19 +116,10 @@ module EvalIn
125
116
  end
126
117
 
127
118
  # @api private
128
- def self.fetch_result_json(location)
129
- # Can't just use Net::HTTP.get, b/c it doesn't use ssl on 1.9.3
130
- # https://github.com/ruby/ruby/blob/v2_1_2/lib/net/http.rb#L478-479
131
- # https://github.com/ruby/ruby/blob/v1_9_3_547/lib/net/http.rb#L454
132
- uri = URI location
133
- Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) { |http|
134
- body = http.request_get(uri.request_uri).body
135
- if body
136
- JSON.parse(body).merge('url' => location)
137
- else
138
- raise ResultNotFound, "No json at #{location.inspect}"
139
- end
140
- }
119
+ def self.fetch_result_json(raw_url, options={})
120
+ result = get_request raw_url, user_agent_for(options[:context])
121
+ return JSON.parse(result.body).merge('url' => raw_url) if result.body
122
+ raise ResultNotFound, "No json at #{raw_url.inspect}"
141
123
  end
142
124
 
143
125
  # @api private
@@ -164,4 +146,43 @@ module EvalIn
164
146
  uri.path = Pathname.new(uri.path).sub_ext('.json').to_s
165
147
  uri.to_s
166
148
  end
149
+
150
+ # @private
151
+ def self.user_agent_for(context)
152
+ 'http://rubygems.org/gems/eval_in'.tap do |agent|
153
+ context && agent.concat(" (#{context})")
154
+ end
155
+ end
156
+
157
+ # @api private
158
+ # Can't just use Net::HTTP.get, b/c it doesn't use ssl on 1.9.3
159
+ # https://github.com/ruby/ruby/blob/v2_1_2/lib/net/http.rb#L478-479
160
+ # https://github.com/ruby/ruby/blob/v1_9_3_547/lib/net/http.rb#L454
161
+ def self.get_request(raw_url, user_agent)
162
+ generic_request_for raw_url: raw_url,
163
+ request_type: Net::HTTP::Get,
164
+ user_agent: user_agent
165
+ end
166
+
167
+ # @private
168
+ def self.post_request(raw_url, form_data, user_agent)
169
+ generic_request_for raw_url: raw_url,
170
+ request_type: Net::HTTP::Post,
171
+ user_agent: user_agent,
172
+ form_data: form_data
173
+ end
174
+
175
+ # @private
176
+ # stole this out of implementation for post_form https://github.com/ruby/ruby/blob/2afed6eceff2951b949db7ded8167a75b431bad6/lib/net/http.rb#L503
177
+ # can use this to view the request: http.set_debug_output $stdout
178
+ def self.generic_request_for(params)
179
+ uri = URI params.fetch(:raw_url)
180
+ path = uri.path
181
+ path = '/' if path.empty?
182
+ request = params.fetch(:request_type).new(path)
183
+ request['User-Agent'] = params[:user_agent] if params.key? :user_agent
184
+ request.form_data = params[:form_data] if params.key? :form_data
185
+ request.basic_auth uri.user, uri.password if uri.user
186
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) { |http| http.request request }
187
+ end
167
188
  end
@@ -1,3 +1,3 @@
1
1
  module EvalIn
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.5'
3
3
  end
data/spec/eval_in_spec.rb CHANGED
@@ -27,8 +27,10 @@ RSpec.describe EvalIn, integration: true do
27
27
  WebMock.disable_net_connect!
28
28
  end
29
29
 
30
+ let(:context) { 'eval_in integration test' }
31
+
30
32
  it 'evaluates Ruby code through eval.in' do
31
- result = EvalIn.call 'print "hello, #{gets}"', stdin: "world", language: "ruby/mri-2.1", context: 'eval_in integration test'
33
+ result = EvalIn.call 'print "hello, #{gets}"', stdin: "world", language: "ruby/mri-2.1", context: context
32
34
  expect(result.exitstatus ).to eq 0
33
35
  expect(result.language ).to eq "ruby/mri-2.1"
34
36
  expect(result.language_friendly).to eq "Ruby — MRI 2.1"
@@ -48,6 +50,18 @@ RSpec.describe EvalIn, integration: true do
48
50
  expect(result.status ).to match /OK \([\d.]+ sec real, [\d.]+ sec wall, \d MB, \d+ syscalls\)/
49
51
  expect(result.url ).to match %r(https://eval.in/147.json)
50
52
  end
53
+
54
+ it 'is in sync with known languages' do
55
+ # iffy solution, but it's simple and works,
56
+ # Rexml might get taken out of stdlib, so is more likely than this regex to fail in the future,
57
+ # and I don't want to add dep on Nokogiri (w/ libxml & libxslt) where a small regex works adequately
58
+ current_known_languages = EvalIn.get_request('https://eval.in', context)
59
+ .body
60
+ .each_line
61
+ .map { |line| line[/option.*?value="([^"]+)"/, 1] }
62
+ .compact
63
+ expect(EvalIn::KNOWN_LANGUAGES).to eq current_known_languages
64
+ end
51
65
  end
52
66
 
53
67
  RSpec.describe EvalIn::Result do
@@ -309,8 +323,9 @@ end
309
323
  RSpec.describe 'fetch_result' do
310
324
  include WebMock::API
311
325
 
312
- def stub_eval_in(url)
326
+ def stub_eval_in(url, options={})
313
327
  stub_request(:get, url)
328
+ .with(headers: {'User-Agent' => options.fetch(:user_agent, 'http://rubygems.org/gems/eval_in')})
314
329
  .to_return(status: 200, body: json_result)
315
330
  end
316
331
 
@@ -336,6 +351,11 @@ RSpec.describe 'fetch_result' do
336
351
  expect(EvalIn.fetch_result('https://eval.in/1').url).to eq 'https://eval.in/1.json'
337
352
  expect(EvalIn.fetch_result('https://eval.in/1.json').url).to eq 'https://eval.in/1.json'
338
353
  end
354
+
355
+ it 'can take a context for the user agent' do
356
+ stub_eval_in 'https://eval.in/1.json', user_agent: 'http://rubygems.org/gems/eval_in (c)'
357
+ expect(EvalIn.fetch_result('https://eval.in/1', context: 'c').url).to eq 'https://eval.in/1.json'
358
+ end
339
359
  end
340
360
 
341
361
 
metadata CHANGED
@@ -1,80 +1,67 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eval_in
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Josh Cheek
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-08-31 00:00:00.000000000 Z
12
+ date: 2014-09-01 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rspec
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
- - - "~>"
19
+ - - ~>
18
20
  - !ruby/object:Gem::Version
19
21
  version: '3.0'
20
22
  type: :development
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
- - - "~>"
27
+ - - ~>
25
28
  - !ruby/object:Gem::Version
26
29
  version: '3.0'
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: webmock
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
- - - "~>"
35
+ - - ~>
32
36
  - !ruby/object:Gem::Version
33
37
  version: '1.18'
34
38
  type: :development
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
- - - "~>"
43
+ - - ~>
39
44
  - !ruby/object:Gem::Version
40
45
  version: '1.18'
41
- description: |+
42
- Safely evaluates code (Ruby and others) by sending it through https://eval.in
43
-
44
- == Languages and Versions
45
-
46
- Ruby | MRI 1.0, MRI 1.8.7, MRI 1.9.3, MRI 2.0.0, MRI 2.1
47
- C | GCC 4.4.3, GCC 4.9.1
48
- C++ | C++11 (GCC 4.9.1), GCC 4.4.3, GCC 4.9.1
49
- CoffeeScript | CoffeeScript 1.7.1 (Node 0.10.29)
50
- Fortran | F95 (GCC 4.4.3)
51
- Haskell | Hugs98 September 2006
52
- Io | Io 20131204
53
- JavaScript | Node 0.10.29
54
- Lua | Lua 5.1.5, Lua 5.2.3
55
- OCaml | OCaml 4.01.0
56
- PHP | PHP 5.5.14
57
- Pascal | Free Pascal 2.6.4
58
- Perl | Perl 5.20.0
59
- Python | CPython 2.7.8, CPython 3.4.1
60
- Slash | Slash HEAD
61
- x86 Assembly | NASM 2.07
62
-
63
- == Example:
64
-
65
- It's this simple:
66
-
67
- result = EvalIn.call 'puts "example"', language: "ruby/mri-2.1"
68
- result.output # returns "example\n"
69
-
46
+ description: ! "Safely evaluates code (Ruby and others) by sending it through https://eval.in\n\n==
47
+ Languages and Versions\n\n Ruby | MRI 1.0, MRI 1.8.7, MRI 1.9.3, MRI 2.0.0,
48
+ MRI 2.1\n C | GCC 4.4.3, GCC 4.9.1\n C++ | C++11 (GCC 4.9.1),
49
+ GCC 4.4.3, GCC 4.9.1\n CoffeeScript | CoffeeScript 1.7.1 (Node 0.10.29)\n Fortran
50
+ \ | F95 (GCC 4.4.3)\n Haskell | Hugs98 September 2006\n Io |
51
+ Io 20131204\n JavaScript | Node 0.10.29\n Lua | Lua 5.1.5, Lua 5.2.3\n
52
+ \ OCaml | OCaml 4.01.0\n PHP | PHP 5.5.14\n Pascal |
53
+ Free Pascal 2.6.4\n Perl | Perl 5.20.0\n Python | CPython 2.7.8,
54
+ CPython 3.4.1\n Slash | Slash HEAD\n x86 Assembly | NASM 2.07\n\n== Example:\n\nIt's
55
+ this simple:\n\n result = EvalIn.call 'puts \"example\"', language: \"ruby/mri-2.1\"\n
56
+ \ result.output # returns \"example\\n\"\n\n"
70
57
  email:
71
58
  - josh.cheek@gmail.com
72
59
  executables: []
73
60
  extensions: []
74
61
  extra_rdoc_files: []
75
62
  files:
76
- - ".gitignore"
77
- - ".travis.yml"
63
+ - .gitignore
64
+ - .travis.yml
78
65
  - Gemfile
79
66
  - Readme.md
80
67
  - eval_in.gemspec
@@ -84,26 +71,27 @@ files:
84
71
  homepage: https://github.com/JoshCheek/eval_in
85
72
  licenses:
86
73
  - WTFPL
87
- metadata: {}
88
74
  post_install_message:
89
75
  rdoc_options: []
90
76
  require_paths:
91
77
  - lib
92
78
  required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
93
80
  requirements:
94
- - - ">="
81
+ - - ! '>='
95
82
  - !ruby/object:Gem::Version
96
83
  version: '0'
97
84
  required_rubygems_version: !ruby/object:Gem::Requirement
85
+ none: false
98
86
  requirements:
99
- - - ">="
87
+ - - ! '>='
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0'
102
90
  requirements: []
103
91
  rubyforge_project:
104
- rubygems_version: 2.4.1
92
+ rubygems_version: 1.8.23.2
105
93
  signing_key:
106
- specification_version: 4
94
+ specification_version: 3
107
95
  summary: Evaluates code (Ruby and others) safely by sending it to https://eval.in
108
96
  test_files:
109
97
  - spec/eval_in_spec.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 8331a9a20d6f485a925ca9e29ff4daf3c5beebad
4
- data.tar.gz: 4c62d600cddd2acf41608da7832a2aa268a5a05e
5
- SHA512:
6
- metadata.gz: fd354b9ded63f728f01eb81b37952ae8ba97e2ceae8dd7b1d6e7cb76e06eb0d6eb2395ff74902e71f76497ddf470cf0b4dc49331c0153a2ff2f59aeb9ab9dadd
7
- data.tar.gz: 0f15ac725abf2c871d3e50bc08244fbc6a2b8c8173bcdeb068ab4c4c7ed99ebeb53e1f3db0c00e11ab38a07bca5d3cddb142679b906086e76ab6654efa4eaf2c