htcp 0.0.2
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/.gitignore +5 -0
- data/LICENSE +21 -0
- data/README.rdoc +55 -0
- data/Rakefile +16 -0
- data/VERSION +1 -0
- data/bin/htcp-client +3 -0
- data/htcp.gemspec +64 -0
- data/init.rb +1 -0
- data/lib/htcp.rb +7 -0
- data/lib/htcp/autoload.rb +28 -0
- data/lib/htcp/client.rb +40 -0
- data/lib/htcp/message/auth.rb +13 -0
- data/lib/htcp/message/base.rb +33 -0
- data/lib/htcp/message/constructor.rb +17 -0
- data/lib/htcp/message/data.rb +27 -0
- data/lib/htcp/message/header.rb +20 -0
- data/lib/htcp/message/op_data/clr.rb +17 -0
- data/lib/htcp/message/specifier.rb +20 -0
- data/spec/htcp/client_spec.rb +73 -0
- data/spec/spec_helper.rb +1 -0
- metadata +83 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2008-2010 Alexey Kovyrin
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
= Ruby Implementation of the HTCP Protocol Client
|
2
|
+
|
3
|
+
This simple library implements HTCP protocol (http://www.htcp.org/) and could be used in any
|
4
|
+
Ruby project to manage any HTCP-compliant caching server (authors use it for Squid 2.7 servers
|
5
|
+
management).
|
6
|
+
|
7
|
+
|
8
|
+
== What commands are supported?
|
9
|
+
|
10
|
+
At this moment the only supported HTCP command is CLR that could be used to remove a cached
|
11
|
+
page from any HTCP-compliant server.
|
12
|
+
|
13
|
+
|
14
|
+
== How to install?
|
15
|
+
|
16
|
+
There are two options when approaching htcp-ruby installation:
|
17
|
+
|
18
|
+
* using the gem (recommended and could be used in non-Rails projects)
|
19
|
+
* install as a Rails plugin
|
20
|
+
|
21
|
+
To install as a gem in a Rails project, add this to your environment.rb:
|
22
|
+
|
23
|
+
config.gem 'htcp'
|
24
|
+
|
25
|
+
And then run the command:
|
26
|
+
|
27
|
+
sudo rake gems:install
|
28
|
+
|
29
|
+
To install loops as a Rails plugin you need to do the following:
|
30
|
+
|
31
|
+
./script/plugin install git://github.com/kovyrin/htcp-ruby.git
|
32
|
+
|
33
|
+
This will install the whole package in your vendor/plugins directory.
|
34
|
+
For merb applications, just check out the code and place it to the vendor/plugins directory.
|
35
|
+
|
36
|
+
|
37
|
+
== How to use?
|
38
|
+
|
39
|
+
Here is a simple code that could be used to purge a page from a caching server:
|
40
|
+
|
41
|
+
# Instantiate HTCP client
|
42
|
+
# It is possible to pass an array of servers to the constructor,
|
43
|
+
# in that case any request sent to the client will be sent out
|
44
|
+
# to all specified servers
|
45
|
+
htcp = Htcp::Client.new('cache01.local')
|
46
|
+
|
47
|
+
# Send CLR request and purge a page from the cache
|
48
|
+
htcp.clr("http://www.yoursite.com/some/page/url")
|
49
|
+
|
50
|
+
|
51
|
+
== Who are the authors?
|
52
|
+
|
53
|
+
This plugin has been created in Scribd.com for our internal use and then the sources were opened for other
|
54
|
+
people to use. All the code in this package has been developed by Alexey Kovyrin for Scribd.com and is
|
55
|
+
released under the MIT license. For more details, see LICENSE file.
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
4
|
+
gemspec.name = 'htcp'
|
5
|
+
gemspec.summary = 'HTCP Protocol Client implemented in Ruby'
|
6
|
+
gemspec.description = 'This simple library implements HTCP protocol (www.htcp.org/) and could be used in any Ruby project to manage any HTCP-compliant caching server (authors use it for Squid 2.7 servers management).'
|
7
|
+
gemspec.email = 'alexey@kovyrin.net'
|
8
|
+
gemspec.homepage = 'http://github.com/kovyrin/htcp-ruby'
|
9
|
+
gemspec.rubyforge_project = 'htcp'
|
10
|
+
gemspec.authors = ['Alexey Kovyrin']
|
11
|
+
gemspec.files.include ['lib/**/*']
|
12
|
+
end
|
13
|
+
Jeweler::GemcutterTasks.new
|
14
|
+
rescue LoadError
|
15
|
+
puts 'Jeweler not available. Install it with: sudo gem install jeweler'
|
16
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.2
|
data/bin/htcp-client
ADDED
data/htcp.gemspec
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{htcp}
|
8
|
+
s.version = "0.0.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Alexey Kovyrin"]
|
12
|
+
s.date = %q{2010-05-29}
|
13
|
+
s.default_executable = %q{htcp-client}
|
14
|
+
s.description = %q{This simple library implements HTCP protocol (www.htcp.org/) and could be used in any Ruby project to manage any HTCP-compliant caching server (authors use it for Squid 2.7 servers management).}
|
15
|
+
s.email = %q{alexey@kovyrin.net}
|
16
|
+
s.executables = ["htcp-client"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE",
|
19
|
+
"README.rdoc"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".gitignore",
|
23
|
+
"LICENSE",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"bin/htcp-client",
|
28
|
+
"htcp.gemspec",
|
29
|
+
"init.rb",
|
30
|
+
"lib/htcp.rb",
|
31
|
+
"lib/htcp/autoload.rb",
|
32
|
+
"lib/htcp/client.rb",
|
33
|
+
"lib/htcp/message/auth.rb",
|
34
|
+
"lib/htcp/message/base.rb",
|
35
|
+
"lib/htcp/message/constructor.rb",
|
36
|
+
"lib/htcp/message/data.rb",
|
37
|
+
"lib/htcp/message/header.rb",
|
38
|
+
"lib/htcp/message/op_data/clr.rb",
|
39
|
+
"lib/htcp/message/specifier.rb",
|
40
|
+
"spec/htcp/client_spec.rb",
|
41
|
+
"spec/spec_helper.rb"
|
42
|
+
]
|
43
|
+
s.homepage = %q{http://github.com/kovyrin/htcp-ruby}
|
44
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
45
|
+
s.require_paths = ["lib"]
|
46
|
+
s.rubyforge_project = %q{htcp}
|
47
|
+
s.rubygems_version = %q{1.3.6}
|
48
|
+
s.summary = %q{HTCP Protocol Client implemented in Ruby}
|
49
|
+
s.test_files = [
|
50
|
+
"spec/htcp/client_spec.rb",
|
51
|
+
"spec/spec_helper.rb"
|
52
|
+
]
|
53
|
+
|
54
|
+
if s.respond_to? :specification_version then
|
55
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
59
|
+
else
|
60
|
+
end
|
61
|
+
else
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'lib/htcp')
|
data/lib/htcp.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Htcp
|
2
|
+
module Autoload
|
3
|
+
# @private
|
4
|
+
def __p(*path) File.join(Htcp::LIB_ROOT, 'htcp', *path) end
|
5
|
+
end
|
6
|
+
extend Autoload
|
7
|
+
|
8
|
+
# Define autoloaded modules/classes
|
9
|
+
autoload :Client, __p('client')
|
10
|
+
|
11
|
+
module Message
|
12
|
+
extend Autoload
|
13
|
+
|
14
|
+
autoload :Base, __p('message/base')
|
15
|
+
autoload :Constructor, __p('message/constructor')
|
16
|
+
|
17
|
+
autoload :Auth, __p('message/auth')
|
18
|
+
autoload :Data, __p('message/data')
|
19
|
+
autoload :Header, __p('message/header')
|
20
|
+
autoload :Specifier, __p('message/specifier')
|
21
|
+
|
22
|
+
module OpData
|
23
|
+
extend Autoload
|
24
|
+
|
25
|
+
autoload :Clr, __p('message/op_data/clr')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/htcp/client.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Htcp
|
4
|
+
class Client
|
5
|
+
DEFAULT_PORT = 4827
|
6
|
+
|
7
|
+
def initialize(*servers_list)
|
8
|
+
@servers = servers_list.flatten
|
9
|
+
end
|
10
|
+
|
11
|
+
def clr(url, headers = '')
|
12
|
+
message = Htcp::Message::Constructor.new(
|
13
|
+
:opcode => Htcp::Message::OpData::Clr::OP_CODE,
|
14
|
+
:rd => 0,
|
15
|
+
:trans_id => Time.now.to_i,
|
16
|
+
:op_data => Htcp::Message::OpData::Clr.new(:uri => url, :headers => headers)
|
17
|
+
)
|
18
|
+
send_messages(message)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def send_messages(message)
|
24
|
+
message = message.to_s
|
25
|
+
@servers.each { |s| send_message(s, message) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def send_message(server, message)
|
29
|
+
host, port = parse_server(server)
|
30
|
+
UDPSocket.new.send(message, 0, host, port)
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_server(server)
|
34
|
+
host, port = server.split(':')
|
35
|
+
port = port.to_i
|
36
|
+
port = DEFAULT_PORT if port.zero?
|
37
|
+
return host, port
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Htcp
|
2
|
+
module Message
|
3
|
+
class Base
|
4
|
+
# Put 16-bit int(s) to request.
|
5
|
+
def encode_int8(*ints)
|
6
|
+
request = ''
|
7
|
+
ints.each { |i| request << [i].pack('C') }
|
8
|
+
return request
|
9
|
+
end
|
10
|
+
|
11
|
+
# Put 16-bit int(s) to request.
|
12
|
+
def encode_int16(*ints)
|
13
|
+
request = ''
|
14
|
+
ints.each { |i| request << [i].pack('n') }
|
15
|
+
return request
|
16
|
+
end
|
17
|
+
|
18
|
+
# Put 32-bit int(s) to request.
|
19
|
+
def encode_int32(*ints)
|
20
|
+
request = ''
|
21
|
+
ints.each { |i| request << [i].pack('N') }
|
22
|
+
return request
|
23
|
+
end
|
24
|
+
|
25
|
+
# Put string(s) to request (first length, then the string itself).
|
26
|
+
def encode_string(*strings)
|
27
|
+
request = ''
|
28
|
+
strings.each { |s| request << encode_int16(s.length) + s }
|
29
|
+
return request
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Htcp
|
2
|
+
module Message
|
3
|
+
class Constructor
|
4
|
+
def initialize(params)
|
5
|
+
@header = Htcp::Message::Header.new(params[:head] || {})
|
6
|
+
@data = Htcp::Message::Data.new(params[:data] || params)
|
7
|
+
@auth = Htcp::Message::Auth.new(params[:auth] || {})
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
payload = @data.to_s + @auth.to_s
|
12
|
+
@header.payload_len = payload.length
|
13
|
+
@header.to_s + payload
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Htcp
|
2
|
+
module Message
|
3
|
+
class Data < Htcp::Message::Base
|
4
|
+
def initialize(params)
|
5
|
+
@params = params
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
# Process data fields
|
10
|
+
rr = @params[:response] ? 1 : 0
|
11
|
+
response_code = @params[:response] || 0
|
12
|
+
f1 = (rr.zero?) ? @params[:rd] : @params[:mo]
|
13
|
+
|
14
|
+
# Compose request
|
15
|
+
request = ''
|
16
|
+
|
17
|
+
request << encode_int8(response_code << 4 | @params[:opcode])
|
18
|
+
request << encode_int8((f1 << 1) | rr)
|
19
|
+
request << encode_int32(@params[:trans_id])
|
20
|
+
request << @params[:op_data].to_s
|
21
|
+
|
22
|
+
# Encode request with string
|
23
|
+
encode_int16(request.length + 2) + request
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Htcp
|
2
|
+
module Message
|
3
|
+
class Header < Htcp::Message::Base
|
4
|
+
attr_accessor :payload_len
|
5
|
+
|
6
|
+
def initialize(params)
|
7
|
+
@params = {
|
8
|
+
:major => 0,
|
9
|
+
:minor => 0
|
10
|
+
}.merge(params)
|
11
|
+
|
12
|
+
@payload_len = 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
encode_int16(@payload_len + 4) + encode_int8(@params[:major], @params[:minor])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Htcp
|
2
|
+
module Message
|
3
|
+
module OpData
|
4
|
+
class Clr < Htcp::Message::Base
|
5
|
+
OP_CODE = 4
|
6
|
+
|
7
|
+
def initialize(params)
|
8
|
+
@specifier = Htcp::Message::Specifier.new(params)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
encode_int16(0) + @specifier.to_s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Htcp
|
2
|
+
module Message
|
3
|
+
class Specifier < Htcp::Message::Base
|
4
|
+
def initialize(params)
|
5
|
+
@params = params
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
request = ''
|
10
|
+
|
11
|
+
request << encode_string(@params[:method] || 'GET')
|
12
|
+
request << encode_string(@params[:uri])
|
13
|
+
request << encode_string(@params[:version] || 'HTTP/1.1')
|
14
|
+
request << encode_string(@params[:headers] || '')
|
15
|
+
|
16
|
+
return request
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Htcp::Client do
|
4
|
+
context "in constructor" do
|
5
|
+
it "should accept one server" do
|
6
|
+
Htcp::Client.new('foo')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should accept a list of servers" do
|
10
|
+
Htcp::Client.new('foo', 'bar')
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should accept an array of servers" do
|
14
|
+
Htcp::Client.new(['foo', 'bar'])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should accept alist of arrays of servers" do
|
18
|
+
Htcp::Client.new(['foo', 'bar'], 'baz', ['blah'])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "in parse_server method" do
|
23
|
+
before do
|
24
|
+
@htcp = Htcp::Client.new('foo')
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should accept a 'host:port' server format" do
|
28
|
+
@htcp.send(:parse_server, 'foo:123').should == [ 'foo', 123 ]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should accept a 'host' server format" do
|
32
|
+
@htcp.send(:parse_server, 'foo').should == [ 'foo', Htcp::Client::DEFAULT_PORT ]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should accept a 'host:invalid_port' server format" do
|
36
|
+
@htcp.send(:parse_server, 'foo:blah').should == [ 'foo', Htcp::Client::DEFAULT_PORT ]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "in clr method" do
|
41
|
+
before do
|
42
|
+
@htcp = Htcp::Client.new('127.0.0.1')
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when called without additional headers" do
|
46
|
+
it "should compose a CLR request and try to send it out" do
|
47
|
+
@htcp.should_receive(:send_messages)
|
48
|
+
@htcp.clr('http://www.blah.com/foo/bar?baz=blah')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when called with additional headers" do
|
53
|
+
it "should compose a CLR request and try to send it out" do
|
54
|
+
@htcp.should_receive(:send_messages)
|
55
|
+
@htcp.clr('http://www.blah.com/foo/bar?baz=blah', 'Foo: bar')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "in send_message method" do
|
61
|
+
it "should send the message out to one server when only one server specified" do
|
62
|
+
htcp = Htcp::Client.new('127.0.0.1')
|
63
|
+
htcp.should_receive(:send_message).once
|
64
|
+
htcp.clr('http://www.blah.com/foo/bar?baz=blah')
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should send the message out to all servers when many servers specified" do
|
68
|
+
htcp = Htcp::Client.new('127.0.0.1', '127.0.0.2')
|
69
|
+
htcp.should_receive(:send_message).twice
|
70
|
+
htcp.clr('http://www.blah.com/foo/bar?baz=blah')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'lib', 'htcp')
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: htcp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Alexey Kovyrin
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-29 00:00:00 -04:00
|
18
|
+
default_executable: htcp-client
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: This simple library implements HTCP protocol (www.htcp.org/) and could be used in any Ruby project to manage any HTCP-compliant caching server (authors use it for Squid 2.7 servers management).
|
22
|
+
email: alexey@kovyrin.net
|
23
|
+
executables:
|
24
|
+
- htcp-client
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
- Rakefile
|
35
|
+
- VERSION
|
36
|
+
- bin/htcp-client
|
37
|
+
- htcp.gemspec
|
38
|
+
- init.rb
|
39
|
+
- lib/htcp.rb
|
40
|
+
- lib/htcp/autoload.rb
|
41
|
+
- lib/htcp/client.rb
|
42
|
+
- lib/htcp/message/auth.rb
|
43
|
+
- lib/htcp/message/base.rb
|
44
|
+
- lib/htcp/message/constructor.rb
|
45
|
+
- lib/htcp/message/data.rb
|
46
|
+
- lib/htcp/message/header.rb
|
47
|
+
- lib/htcp/message/op_data/clr.rb
|
48
|
+
- lib/htcp/message/specifier.rb
|
49
|
+
- spec/htcp/client_spec.rb
|
50
|
+
- spec/spec_helper.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://github.com/kovyrin/htcp-ruby
|
53
|
+
licenses: []
|
54
|
+
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --charset=UTF-8
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project: htcp
|
77
|
+
rubygems_version: 1.3.6
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: HTCP Protocol Client implemented in Ruby
|
81
|
+
test_files:
|
82
|
+
- spec/htcp/client_spec.rb
|
83
|
+
- spec/spec_helper.rb
|