eval_in 0.1.4 → 0.1.5
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.
- data/lib/eval_in.rb +54 -33
- data/lib/eval_in/version.rb +1 -1
- data/spec/eval_in_spec.rb +22 -2
- metadata +30 -42
- checksums.yaml +0 -7
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
|
-
#
|
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
|
-
|
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(
|
93
|
-
|
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
|
-
|
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
|
-
|
102
|
-
|
103
|
-
|
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(
|
129
|
-
|
130
|
-
|
131
|
-
#
|
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
|
data/lib/eval_in/version.rb
CHANGED
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:
|
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
|
+
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-
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
-
|
77
|
-
-
|
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:
|
92
|
+
rubygems_version: 1.8.23.2
|
105
93
|
signing_key:
|
106
|
-
specification_version:
|
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
|