wku-ruby-rets 2.0.7
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +104 -0
- data/MIT-LICENSE +19 -0
- data/README.md +43 -0
- data/Rakefile +12 -0
- data/lib/rets/base/core.rb +303 -0
- data/lib/rets/base/sax_metadata.rb +63 -0
- data/lib/rets/base/sax_search.rb +58 -0
- data/lib/rets/client.rb +75 -0
- data/lib/rets/exceptions.rb +37 -0
- data/lib/rets/http.rb +346 -0
- data/lib/rets/stream_http.rb +170 -0
- data/lib/rets/version.rb +3 -0
- data/lib/ruby-rets.rb +9 -0
- metadata +99 -0
@@ -0,0 +1,170 @@
|
|
1
|
+
# This is a slightly crazy hack, but it's saner if we can just use Net::HTTP and then fallback on the StreamHTTP class when we need to do stream parsing.
|
2
|
+
# If we were to do it ourselves with Sockets, it would be a bigger pain to manage that, and we would have to do roughly the same setup as below anyway.
|
3
|
+
# Essentially, for the hack of using instance_variable_get/instance_variable_set, we get a simple stream parser, without having to write our own HTTP class.
|
4
|
+
module RETS
|
5
|
+
class StreamHTTP
|
6
|
+
ENCODABLE = RUBY_VERSION >= "1.9.0"
|
7
|
+
|
8
|
+
##
|
9
|
+
# Initializes a new HTTP stream which can be passed to Nokogiri for SAX parsing.
|
10
|
+
# @param [Net::HTTPResponse] response
|
11
|
+
# Unused HTTP response, no calls to any of the read_body or other methods can have been called.
|
12
|
+
def initialize(response)
|
13
|
+
@response = response
|
14
|
+
@left_to_read = @response.content_length
|
15
|
+
@content_length = @response.content_length
|
16
|
+
@chunked = @response.chunked?
|
17
|
+
@socket = @response.instance_variable_get(:@socket)
|
18
|
+
@left_over = ""
|
19
|
+
@digest = Digest::SHA1.new
|
20
|
+
@total_size = 0
|
21
|
+
|
22
|
+
if @response.header.key?("content-type") and @response["content-type"] =~ /.*charset=(.*)/i
|
23
|
+
@encoding = $1.to_s.upcase
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# The total size read from the stream, can be called either while reading or at the end.
|
29
|
+
def size
|
30
|
+
@total_size
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# SHA1 hash of the data read from the stream
|
35
|
+
def hash
|
36
|
+
@digest.hexdigest
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Detected encoding
|
41
|
+
def encoding
|
42
|
+
@encoding
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Read
|
47
|
+
#
|
48
|
+
# @param [Integer] read_len
|
49
|
+
# How many bytes to read from the HTTP stream
|
50
|
+
def read(read_len)
|
51
|
+
# If we closed the connection, return nil without calling anything again to avoid EOF
|
52
|
+
# or other errors
|
53
|
+
return nil if @closed
|
54
|
+
|
55
|
+
if @left_to_read
|
56
|
+
# We hit the end of what we need to read, if this is a chunked request, then we need to check for the next chunk
|
57
|
+
if @left_to_read <= read_len
|
58
|
+
data = @socket.read(@left_to_read)
|
59
|
+
@total_size += @left_to_read
|
60
|
+
@left_to_read = nil
|
61
|
+
@read_clfr = true
|
62
|
+
# Reading from known buffer still
|
63
|
+
else
|
64
|
+
@left_to_read -= read_len
|
65
|
+
@total_size += read_len
|
66
|
+
data = @socket.read(read_len)
|
67
|
+
end
|
68
|
+
|
69
|
+
elsif @chunked
|
70
|
+
# We finished reading the chunks, read the last 2 to get \r\n out of the way, and then find the next chunk
|
71
|
+
if @read_clfr
|
72
|
+
@read_clfr = nil
|
73
|
+
@socket.read(2)
|
74
|
+
end
|
75
|
+
|
76
|
+
data, chunk_read = "", 0
|
77
|
+
while true
|
78
|
+
# Read first line to get the chunk length
|
79
|
+
line = @socket.readline
|
80
|
+
|
81
|
+
len = line.slice(/[0-9a-fA-F]+/) or raise Net::HTTPBadResponse.new("wrong chunk size line: #{line}")
|
82
|
+
len = len.hex
|
83
|
+
|
84
|
+
# Nothing left, read off the final \r\n
|
85
|
+
if len == 0
|
86
|
+
@socket.read(2)
|
87
|
+
@socket.close
|
88
|
+
@response.instance_variable_set(:@read, true)
|
89
|
+
|
90
|
+
@closed = true
|
91
|
+
break
|
92
|
+
end
|
93
|
+
|
94
|
+
# Reading this chunk will set us over the buffer amount
|
95
|
+
# Read what we can of it (if anything), and send back what we have and queue a read for the rest
|
96
|
+
if ( chunk_read + len ) > read_len
|
97
|
+
can_read = len - ( ( chunk_read + len ) - read_len )
|
98
|
+
|
99
|
+
@left_to_read = len - can_read
|
100
|
+
@total_size += can_read
|
101
|
+
|
102
|
+
data << @socket.read(can_read) if can_read > 0
|
103
|
+
break
|
104
|
+
# We can just return the chunk as-is
|
105
|
+
else
|
106
|
+
@total_size += len
|
107
|
+
chunk_read += len
|
108
|
+
|
109
|
+
data << @socket.read(len)
|
110
|
+
@socket.read(2)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# If we don't have a content length, then we need to keep reading until we run out of data
|
115
|
+
elsif !@content_length
|
116
|
+
if @left_over.length > 0
|
117
|
+
data = @left_over
|
118
|
+
@left_over = ""
|
119
|
+
data += @socket.readline
|
120
|
+
else
|
121
|
+
data = @socket.readline
|
122
|
+
end
|
123
|
+
|
124
|
+
if data.length > read_len
|
125
|
+
@left_over = data[4000,data.length]
|
126
|
+
data = data[0,4000]
|
127
|
+
end
|
128
|
+
|
129
|
+
@total_size += data.length if data
|
130
|
+
end
|
131
|
+
|
132
|
+
# We've finished reading, set this so Net::HTTP doesn't try and read it again
|
133
|
+
if !data or data == ""
|
134
|
+
@response.instance_variable_set(:@read, true)
|
135
|
+
|
136
|
+
nil
|
137
|
+
else
|
138
|
+
if data.length >= @total_size and !@chunked
|
139
|
+
@response.instance_variable_set(:@read, true)
|
140
|
+
end
|
141
|
+
|
142
|
+
if ENCODABLE and @encoding
|
143
|
+
data = data.force_encoding(@encoding) if @encoding
|
144
|
+
data = data.encode("UTF-8")
|
145
|
+
end
|
146
|
+
|
147
|
+
@digest.update(data)
|
148
|
+
data
|
149
|
+
end
|
150
|
+
|
151
|
+
# Mark as read finished, return the last bits of data (if any)
|
152
|
+
rescue EOFError
|
153
|
+
@response.instance_variable_set(:@read, true)
|
154
|
+
@socket.close
|
155
|
+
@closed = true
|
156
|
+
|
157
|
+
if data and data != ""
|
158
|
+
@digest.update(data)
|
159
|
+
data
|
160
|
+
else
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
##
|
166
|
+
# Does nothing, only used because Nokogiri requires it in a SAX parser.
|
167
|
+
def close
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/lib/rets/version.rb
ADDED
data/lib/ruby-rets.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
path = File.expand_path("../rets", __FILE__)
|
2
|
+
require "#{path}/version"
|
3
|
+
require "#{path}/exceptions"
|
4
|
+
require "#{path}/client"
|
5
|
+
require "#{path}/http"
|
6
|
+
require "#{path}/stream_http"
|
7
|
+
require "#{path}/base/core"
|
8
|
+
require "#{path}/base/sax_search"
|
9
|
+
require "#{path}/base/sax_metadata"
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wku-ruby-rets
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean Coleman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.5.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.5.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.8.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.8.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: guard-rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.6.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.6.0
|
55
|
+
description: Gem for pulling data from RETS (http://rets.org) servers.
|
56
|
+
email:
|
57
|
+
- sean@seancoleman.net
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- CHANGELOG.md
|
63
|
+
- MIT-LICENSE
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- lib/rets/base/core.rb
|
67
|
+
- lib/rets/base/sax_metadata.rb
|
68
|
+
- lib/rets/base/sax_search.rb
|
69
|
+
- lib/rets/client.rb
|
70
|
+
- lib/rets/exceptions.rb
|
71
|
+
- lib/rets/http.rb
|
72
|
+
- lib/rets/stream_http.rb
|
73
|
+
- lib/rets/version.rb
|
74
|
+
- lib/ruby-rets.rb
|
75
|
+
homepage: http://github.com/Placester/ruby-rets
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.3.6
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project: ruby-rets
|
95
|
+
rubygems_version: 2.2.2
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: RETS 1.x library for Ruby
|
99
|
+
test_files: []
|