funky-simplehttp 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 19b2df5b95c721fd8b240d79bba007b27e1b051b
4
+ data.tar.gz: d83529c9ae13241bb3f5761118391cea43e37086
5
+ SHA512:
6
+ metadata.gz: 32cc670f116b166c49b5c9f3db867b3717da27fe105647186ddb8dbbb1c11c9b579665ee05a3d2ba09f2a386be10914e2e61e72d5170faa4bb06c7510734067d
7
+ data.tar.gz: 4f437d49945cc6842524b6041ab7abf42fe0aba310c13511ae485555081d2b6a8ae964a6ec8fdfcadeac8a73e509c7d199b0e61b8e5d851cd4ac038abe065047
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ out
2
+ out/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,17 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ funky-simplehttp (0.4.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (10.4.2)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ bundler (~> 1.7)
16
+ funky-simplehttp!
17
+ rake (~> 10.0)
data/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # SimpleHttp Class for mruby
2
+
3
+ POC to CloudWalk gems and libs, pure ruby implementation.
4
+
5
+ Simple http or https connection class for mruby.
6
+
7
+ Project based on matsumoto-r/mruby-simplehttp and iij/mruby-simplehttp
8
+
9
+ ## Contributing
10
+
11
+ 1. Fork it
12
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
13
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
14
+ 4. Push to the branch (`git push origin my-new-feature`)
15
+ 5. Create new Pull Request
16
+
17
+ # License
18
+ under the MIT License:
19
+
20
+ * http://www.opensource.org/licenses/mit-license.php
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ require 'rake'
2
+ #require "bundler/gem_tasks"
3
+
4
+ SIMPLEHTTP_ROOT = File.dirname(File.expand_path(__FILE__))
5
+ SIMPLEHTTP_OUT = File.join(SIMPLEHTTP_ROOT, "out", "simplehttp.mrb")
6
+
7
+ task :default => :build
8
+
9
+ task :check do
10
+ if ENV["MRBC"].nil?
11
+ if system("type cloudwalk > /dev/null 2>&1 ")
12
+ ENV["MRBC"] = "env cloudwalk compile"
13
+ elsif system("type mrbc > /dev/null 2>&1 ")
14
+ ENV["MRBC"] = "env mrbc"
15
+ else
16
+ puts "$MRBC isn't set or mrbc/cloudwalk isn't on $PATH"
17
+ exit 0
18
+ end
19
+ end
20
+ end
21
+
22
+ desc "Compile simplehttp to mrb"
23
+ task :build => :check do
24
+ sh "mkdir -p #{File.join(SIMPLEHTTP_ROOT, "out")}"
25
+ if ENV["MRBC"]
26
+ sh "#{ENV["MRBC"]} -g -o #{SIMPLEHTTP_OUT} #{File.join(SIMPLEHTTP_ROOT, "lib", "simplehttp.rb")} "
27
+ else
28
+ sh "env mrbc -g -o #{SIMPLEHTTP_OUT} #{File.join(SIMPLEHTTP_ROOT, "lib", "simplehttp.rb")} "
29
+ end
30
+ end
31
+
32
+ desc "Clobber/Clean"
33
+ task :clean => :check do
34
+ sh "mkdir -p out"
35
+ sh "rm -f #{SIMPLEHTTP_OUT}"
36
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'simplehttp.rb'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "funky-simplehttp"
8
+ spec.version = SimpleHttp.version
9
+ spec.authors = ["Thiago Scalone"]
10
+ spec.email = ["thiago@scalone.com.br"]
11
+ spec.summary = "Simplehttp"
12
+ spec.description = "Minimal HTTP implementation"
13
+ spec.homepage = "http://github.com/cloudwalkio/funky-simplehttp"
14
+ spec.license = "MIT"
15
+ spec.files = `git ls-files -z`.split("\x0") << "out/simplehttp.mrb"
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ end
data/lib/simplehttp.rb ADDED
@@ -0,0 +1,255 @@
1
+ class SimpleHttp
2
+ DEFAULTPORT = 80
3
+ DEFAULTHTTPSPORT = 443
4
+ HTTP_VERSION = "HTTP/1.0"
5
+ DEFAULT_ACCEPT = "*/*"
6
+ SEP = "\r\n"
7
+
8
+ def self.version
9
+ "0.4.2"
10
+ end
11
+
12
+ attr_accessor :socket, :socket_tcp, :support_fiber
13
+
14
+ def socket_class_exist?
15
+ c = Module.const_get("TCPSocket")
16
+ c.is_a?(Class)
17
+ rescue
18
+ return false
19
+ end
20
+
21
+ def uv_module_exist?
22
+ c = Module.const_get("UV")
23
+ c.is_a?(Module)
24
+ rescue
25
+ return false
26
+ end
27
+
28
+ def initialize(schema, address, port = nil)
29
+ @use_socket = false
30
+ @use_uv = false
31
+ if socket_class_exist?
32
+ @use_socket = true
33
+ end
34
+
35
+ if uv_module_exist?
36
+ @use_uv = true
37
+ end
38
+ @uri = {}
39
+ if @use_socket
40
+ # nothing
41
+ elsif @use_uv
42
+ ip = ""
43
+ UV::getaddrinfo(address, "http") do |x, info|
44
+ if info
45
+ ip = info.addr
46
+ end
47
+ end
48
+ UV::run()
49
+ @uri[:ip] = ip
50
+ else
51
+ raise "Not found Socket Class or UV Module"
52
+ end
53
+ @uri[:schema] = schema
54
+ @uri[:address] = address
55
+ if schema == "https"
56
+ @uri[:port] = port ? port.to_i : DEFAULTHTTPSPORT
57
+ else
58
+ @uri[:port] = port ? port.to_i : DEFAULTPORT
59
+ end
60
+ self
61
+ end
62
+
63
+ def address; @uri[:address]; end
64
+ def port; @uri[:port]; end
65
+
66
+ def get(path = "/", req = nil)
67
+ request("GET", path, req)
68
+ end
69
+
70
+ def post(path = "/", req = nil)
71
+ request("POST", path, req)
72
+ end
73
+
74
+ # private
75
+ def request(method, path, req)
76
+ @uri[:path] = path
77
+ if @uri[:path].nil?
78
+ @uri[:path] = "/"
79
+ elsif @uri[:path][0] != "/"
80
+ @uri[:path] = "/" + @uri[:path]
81
+ end
82
+ request_header = create_request_header(method.upcase.to_s, req)
83
+ response_text = send_request(request_header)
84
+ SimpleHttpResponse.new(response_text)
85
+ end
86
+
87
+ def read_fiber
88
+ response_text = ""
89
+ loop do
90
+ return "" if (@socket_tcp.nil? || @socket_tcp.closed?)
91
+ usleep(10000)
92
+ if (available = socket.bytes_available) > 0
93
+ usleep(10000)
94
+ t = socket.read(available)
95
+ usleep(10000)
96
+ break if t.nil?
97
+ response_text << t
98
+ end
99
+ finish = Fiber.yield(false)
100
+ if finish
101
+ return response_text
102
+ end
103
+ end
104
+ response_text
105
+ end
106
+
107
+ def read_normal
108
+ response_text = ""
109
+ while (t = socket.read(1024))
110
+ response_text += t
111
+ end
112
+ response_text
113
+ end
114
+
115
+ def support_fiber?
116
+ @support_fiber
117
+ end
118
+
119
+ def send_request(request_header)
120
+ response_text = ""
121
+ if @socket
122
+ socket.write(request_header)
123
+ if support_fiber?
124
+ response_text = read_fiber
125
+ else
126
+ response_text = read_normal
127
+ end
128
+ elsif @use_socket
129
+ @socket = TCPSocket.new(@uri[:address], @uri[:port])
130
+ if @uri[:schema] == "https"
131
+ entropy = PolarSSL::Entropy.new
132
+ ctr_drbg = PolarSSL::CtrDrbg.new entropy
133
+ ssl = PolarSSL::SSL.new
134
+ ssl.set_endpoint PolarSSL::SSL::SSL_IS_CLIENT
135
+ ssl.set_rng ctr_drbg
136
+ ssl.set_socket socket
137
+ ssl.handshake
138
+ ssl.write request_header
139
+ while chunk = ssl.read(2048)
140
+ response_text += chunk
141
+ end
142
+ ssl.close_notify
143
+ socket.close
144
+ ssl.close
145
+ else
146
+ socket.write(request_header)
147
+ while (t = socket.read(1024))
148
+ response_text += t
149
+ end
150
+ socket.close
151
+ end
152
+ elsif @use_uv
153
+ socket = UV::TCP.new()
154
+ socket.connect(UV.ip4_addr(@uri[:ip].sin_addr, @uri[:port])) do |x|
155
+ if x == 0
156
+ socket.write(request_header) do |x|
157
+ socket.read_start do |b|
158
+ response_text += b.to_s
159
+ end
160
+ end
161
+ else
162
+ socket.close()
163
+ end
164
+ end
165
+ UV::run()
166
+ else
167
+ raise "Not found Socket Class or UV Module"
168
+ end
169
+ response_text
170
+ end
171
+
172
+ def create_request_header(method, req)
173
+ req = {} unless req
174
+ str = ""
175
+ body = ""
176
+ str += sprintf("%s %s %s", method, @uri[:path], HTTP_VERSION) + SEP
177
+ header = {}
178
+ req.each do |key,value|
179
+ header[key.capitalize] = value
180
+ end
181
+ header["Host"] = @uri[:address] unless header.keys.include?("Host")
182
+ header["Accept"] = DEFAULT_ACCEPT unless header.keys.include?("Accept")
183
+ header["Connection"] = "close"
184
+ if header["Body"]
185
+ body = header["Body"]
186
+ header.delete("Body")
187
+ end
188
+ if method == "POST" && (not header.keys.include?("content-length".capitalize))
189
+ header["Content-Length"] = (body || '').length
190
+ end
191
+ header.keys.sort.each do |key|
192
+ str += sprintf("%s: %s", key, header[key]) + SEP
193
+ end
194
+ str + SEP + body
195
+ end
196
+
197
+ class SimpleHttpResponse
198
+ SEP = SimpleHttp::SEP
199
+ def initialize(response_text)
200
+ @response = {}
201
+ @headers = {}
202
+ if response_text.empty?
203
+ @response["header"] = nil
204
+ elsif response_text.include?(SEP + SEP)
205
+ @response["header"], @response["body"] = response_text.split(SEP + SEP, 2)
206
+ else
207
+ @response["header"] = response_text
208
+ end
209
+ parse_header
210
+ self
211
+ end
212
+
213
+ def [](key); @response[key]; end
214
+ def []=(key, value); @response[key] = value; end
215
+
216
+ def header; @response['header']; end
217
+ def headers; @headers; end
218
+ def body; @response['body']; end
219
+ def status; @response['status']; end
220
+ def code; @response['code']; end
221
+ def date; @response['date']; end
222
+ def content_type; @response['content-type']; end
223
+ def content_length; @response['content-length']; end
224
+
225
+ def each(&block)
226
+ if block
227
+ @response.each do |k,v| block.call(k,v) end
228
+ end
229
+ end
230
+ def each_name(&block)
231
+ if block
232
+ @response.each do |k,v| block.call(k) end
233
+ end
234
+ end
235
+
236
+ # private
237
+ def parse_header
238
+ return unless @response["header"]
239
+ h = @response["header"].split(SEP)
240
+ if h[0].include?("HTTP/1")
241
+ @response["status"] = h[0].split(" ", 2).last
242
+ @response["code"] = h[0].split(" ", 3)[1].to_i
243
+ end
244
+ h.each do |line|
245
+ if line.include?(": ")
246
+ k,v = line.split(": ")
247
+ @response[k.downcase] = v
248
+ @headers[k.downcase] = v
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+
255
+
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: funky-simplehttp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.2
5
+ platform: ruby
6
+ authors:
7
+ - Thiago Scalone
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Minimal HTTP implementation
42
+ email:
43
+ - thiago@scalone.com.br
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - Gemfile.lock
51
+ - README.md
52
+ - Rakefile
53
+ - funky-simplehttp.gemspec
54
+ - lib/simplehttp.rb
55
+ - out/simplehttp.mrb
56
+ homepage: http://github.com/cloudwalkio/funky-simplehttp
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.2.2
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: Simplehttp
80
+ test_files: []
81
+ has_rdoc: