localhook 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +41 -0
- data/Rakefile +1 -0
- data/bin/localhook +4 -0
- data/lib/localhook.rb +5 -0
- data/lib/localhook/command.rb +51 -0
- data/lib/localhook/event_source.rb +56 -0
- data/lib/localhook/version.rb +3 -0
- data/lib/localhook/webhook_forwarder.rb +35 -0
- data/localhook.gemspec +29 -0
- data/spec/command_spec.rb +23 -0
- data/spec/event_source_spec.rb +31 -0
- data/spec/webbook_forwarder_spec.rb +39 -0
- metadata +162 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8ab14906758ff1242dd8322ec1fb39f7f17d9101
|
4
|
+
data.tar.gz: 50e268e4b5d8c5239270fdb32b976577e6c8dd98
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4333fd6974a59eba698b78d5d97e1fc4c2b3486f4dca0fb8fad13b7f79f4b49b9820b6ac45114e40e5d9b5b0c7e29a120f43998491d0f8e4ac50b203ef8349a3
|
7
|
+
data.tar.gz: c2d435287c5652fb9814fea89aa6ce6d0911356b995538334745981710145856bf3b5458fb92573e5718221a13ec0ef278a5363c74472219fe8295a46d28f5db
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Francis Chong
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Localhook
|
2
|
+
|
3
|
+
## What is Localhook?
|
4
|
+
|
5
|
+
Localhook let you receive webhooks behind a firewall.
|
6
|
+
|
7
|
+
A WebHook is an HTTP callback: an HTTP POST that occurs when something happens. Many popular services (GitHub, Stripe, ActiveCampaign, Papertrail, etc) support updates via webhooks. However, since these webhook requests are made over Internet, it's difficult receive them when testing from behind a firewall.
|
8
|
+
|
9
|
+
Localhook lets you host a public endpoint for other services and tunnels requests to a private endpoint on your computer.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Install localhook client:
|
14
|
+
|
15
|
+
``
|
16
|
+
gem install localhook
|
17
|
+
``
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
First, you must host your own localhook server on internet. Check [localhook-server](https://github.com/siuying/localhook-server) for details.
|
22
|
+
|
23
|
+
To expose a local webhook ``http://localhost:3000/webhook`` to internet:
|
24
|
+
|
25
|
+
```
|
26
|
+
localhook https://localhook.mydomain.com http://localhost:3000 --token=1234
|
27
|
+
```
|
28
|
+
|
29
|
+
Instead of giving third party url "http://localhost:3000/webhook", you give them
|
30
|
+
``https://localhook.mydomain.com/endpoint1/webhook```.
|
31
|
+
|
32
|
+
Any POST request sent to ``https://localhook.mydomain.com/endpoint1/webhook`` will be
|
33
|
+
forwarded to ``http://localhost:3000/webhook``.
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
1. Fork it ( http://github.com/<my-github-username>/localhook/fork )
|
38
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
39
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
40
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
41
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/localhook
ADDED
data/lib/localhook.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'claide'
|
2
|
+
require 'colored'
|
3
|
+
|
4
|
+
require_relative './event_source'
|
5
|
+
require_relative './webhook_forwarder'
|
6
|
+
|
7
|
+
module Localhook
|
8
|
+
class Command < ::CLAide::Command
|
9
|
+
attr_reader :remote_server, :local_server
|
10
|
+
self.command = 'localhook'
|
11
|
+
self.description = "Localhook let you receive webhooks on localhost."
|
12
|
+
self.arguments = "<remote-server> <local-server>"
|
13
|
+
|
14
|
+
def initialize(argv)
|
15
|
+
@remote_server = argv.shift_argument
|
16
|
+
@local_server = argv.shift_argument
|
17
|
+
@token = argv.option('token')
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.options
|
22
|
+
[
|
23
|
+
['--token=<token>', 'Authentication Token']
|
24
|
+
].concat(super)
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate!
|
28
|
+
if @remote_server.nil?
|
29
|
+
help! "missing remote-server parameter"
|
30
|
+
end
|
31
|
+
if @local_server.nil?
|
32
|
+
help! "missing local-server parameter"
|
33
|
+
end
|
34
|
+
if @token.nil?
|
35
|
+
help! "missing token"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
EventMachine.run do
|
41
|
+
puts "forward remote server (#{@remote_server}) webhooks to #{@local_server}"
|
42
|
+
@forwarder = WebhookForwarder.new(@local_server)
|
43
|
+
@source = EventSource.new(@remote_server, @forwarder, @token)
|
44
|
+
@source.error do |error|
|
45
|
+
puts "error connecting to eventsource: #{error}"
|
46
|
+
end
|
47
|
+
@source.start
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'em-eventsource'
|
2
|
+
require 'yajl'
|
3
|
+
|
4
|
+
module Localhook
|
5
|
+
class EventSource < ::EventMachine::EventSource
|
6
|
+
attr_reader :forwarder
|
7
|
+
attr_reader :endpoint
|
8
|
+
|
9
|
+
VALID_URL = %r{^(https?://[^/]+)/?$}
|
10
|
+
|
11
|
+
def initialize(base_url, forwarder, token)
|
12
|
+
unless base_url =~ VALID_URL
|
13
|
+
raise ArgumentError, "Invalid base_url \"#{base_url}\", it should be in format: (https|http)://<host>(:<port>)?/?"
|
14
|
+
end
|
15
|
+
|
16
|
+
base_url = base_url.match(VALID_URL)[1]
|
17
|
+
super("#{base_url}/_localhook?token=#{token}")
|
18
|
+
|
19
|
+
@forwarder = forwarder
|
20
|
+
|
21
|
+
@parser = Yajl::Parser.new(:symbolize_keys => true)
|
22
|
+
@parser.on_parse_complete = method(:data_parsed)
|
23
|
+
self.on "webhook" do |message|
|
24
|
+
@parser.parse(message)
|
25
|
+
end
|
26
|
+
self.on "endpoint" do |message|
|
27
|
+
@endpoint = message
|
28
|
+
puts "Connected to endpoint: #{message}"
|
29
|
+
end
|
30
|
+
self.on "error" do |error|
|
31
|
+
puts "Error: #{error}"
|
32
|
+
self.close
|
33
|
+
raise "Server response with an error: #{error}"
|
34
|
+
end
|
35
|
+
|
36
|
+
# never timeout
|
37
|
+
self.inactivity_timeout = 0
|
38
|
+
end
|
39
|
+
|
40
|
+
def data_parsed(data)
|
41
|
+
# binding.pry
|
42
|
+
case data[:action]
|
43
|
+
when "post"
|
44
|
+
# convert headers array to Hash, if needed
|
45
|
+
headers = data[:headers]
|
46
|
+
headers = headers.inject({}){|map, v| map[v[0]] = v[1]; map } if headers.is_a?(Array)
|
47
|
+
path = data[:path]
|
48
|
+
query = data[:query_string]
|
49
|
+
body = data[:body]
|
50
|
+
forwarder.post(path, query, headers, body)
|
51
|
+
else
|
52
|
+
raise "unknown action '#{data[:action]}' (#{data}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'em-http-request'
|
2
|
+
|
3
|
+
module Localhook
|
4
|
+
# Forward webhook to destination.
|
5
|
+
# Note: this should be used inside eventmachine
|
6
|
+
class WebhookForwarder
|
7
|
+
attr_reader :url
|
8
|
+
attr_reader :http_options
|
9
|
+
|
10
|
+
VALID_URL = %r{^(https?://[^/]+)/?$}
|
11
|
+
DEFAULT_OPTIONS = {:connect_timeout => 5}
|
12
|
+
|
13
|
+
# Create a WebhookForwarder
|
14
|
+
# url - the base url of the destination webhook
|
15
|
+
# http_options - the http options passed to em
|
16
|
+
def initialize(url, http_options={})
|
17
|
+
unless url =~ VALID_URL
|
18
|
+
raise ArgumentError, "Invalid url \"#{url}\", it should be in format: (https|http)://<host>(:<port>)?/?"
|
19
|
+
end
|
20
|
+
|
21
|
+
@url = url.match(VALID_URL)[1]
|
22
|
+
@http_options = DEFAULT_OPTIONS.merge(http_options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# path - string, the path of the request
|
26
|
+
# query - string, the query string
|
27
|
+
# headers - Hash, the header of the request
|
28
|
+
# body - String, the body of the request
|
29
|
+
def post(path, query, headers, body)
|
30
|
+
http = EventMachine::HttpRequest.new(url, http_options).post :head => headers, :path => path, :query => query, :body => body
|
31
|
+
http.callback { puts "forward url -> #{url}" }
|
32
|
+
http.errback { puts "ERROR: failed forward to url #{url}" }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/localhook.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'localhook/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "localhook"
|
8
|
+
spec.version = Localhook::VERSION
|
9
|
+
spec.authors = ["Francis Chong"]
|
10
|
+
spec.email = ["francis@ignition.hk"]
|
11
|
+
spec.summary = %q{Localhook let you receive webhooks on localhost.}
|
12
|
+
spec.description = %q{Localhook makes it super easy to connect public webhook endpoints with development environments.}
|
13
|
+
spec.homepage = "https://github.com/siuying/localhook"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "claide"
|
22
|
+
spec.add_dependency "em-http-request"
|
23
|
+
spec.add_dependency "em-eventsource"
|
24
|
+
spec.add_dependency "yajl-ruby"
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency "pry"
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative '../lib/localhook'
|
2
|
+
|
3
|
+
describe Localhook::EventSource do
|
4
|
+
context "-initialize" do
|
5
|
+
it "accept parameters" do
|
6
|
+
argv = CLAide::ARGV.new(['http://mylocalhook.com', 'http://localhost:3000'])
|
7
|
+
command = Localhook::Command.new(argv)
|
8
|
+
|
9
|
+
expect(command.remote_server).to eq("http://mylocalhook.com")
|
10
|
+
expect(command.local_server).to eq("http://localhost:3000")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "-run" do
|
15
|
+
it "raise error on missing parameters" do
|
16
|
+
argv = CLAide::ARGV.new(['http://mylocalhook.com'])
|
17
|
+
command = Localhook::Command.new(argv)
|
18
|
+
expect {
|
19
|
+
command.run
|
20
|
+
}.to raise_error
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative '../lib/localhook'
|
2
|
+
require 'yajl'
|
3
|
+
|
4
|
+
describe Localhook::EventSource do
|
5
|
+
context "-initialize" do
|
6
|
+
it "set url via base_url and token parameter" do
|
7
|
+
forwarder = Localhook::EventSource.new("http://localhost:8080", double(:forwarder), "t")
|
8
|
+
expect(forwarder.url).to eq("http://localhost:8080/_localhook?token=t")
|
9
|
+
|
10
|
+
forwarder = Localhook::EventSource.new("http://localhost:8080/", double(:forwarder), "t")
|
11
|
+
expect(forwarder.url).to eq("http://localhost:8080/_localhook?token=t")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "-data_parsed" do
|
16
|
+
let(:forwarder) { double(:forwarder) }
|
17
|
+
subject { Localhook::EventSource.new("http://www.google.com", forwarder, "1") }
|
18
|
+
|
19
|
+
it "call forwarder.post() when parsed action 'post'" do
|
20
|
+
message = {:action => "post",
|
21
|
+
:query_string => "a=1",
|
22
|
+
:path => "/a/b",
|
23
|
+
:body => "{}",
|
24
|
+
:headers => [["User-Agent", "rspec"]]
|
25
|
+
}
|
26
|
+
|
27
|
+
expect(forwarder).to receive(:post).with("/a/b", "a=1", {"User-Agent" => "rspec"}, "{}")
|
28
|
+
subject.data_parsed(message)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../lib/localhook'
|
2
|
+
require 'yajl'
|
3
|
+
|
4
|
+
describe Localhook::WebhookForwarder do
|
5
|
+
context "initialize" do
|
6
|
+
it "accept valid url" do
|
7
|
+
forwarder = Localhook::WebhookForwarder.new("http://localhost:8080")
|
8
|
+
expect(forwarder.url).to eq("http://localhost:8080")
|
9
|
+
|
10
|
+
forwarder = Localhook::WebhookForwarder.new("http://localhost:8080/")
|
11
|
+
expect(forwarder.url).to eq("http://localhost:8080")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "merge input options with default options" do
|
15
|
+
options = {a: 1}
|
16
|
+
forwarder = Localhook::WebhookForwarder.new("http://localhost:8080", options)
|
17
|
+
expect(forwarder.http_options).to eq(Localhook::WebhookForwarder::DEFAULT_OPTIONS.merge(options))
|
18
|
+
end
|
19
|
+
|
20
|
+
it "raise exception for invalid url" do
|
21
|
+
expect {
|
22
|
+
Localhook::WebhookForwarder.new("http://localhost:8080/a/b")
|
23
|
+
}.to raise_error(ArgumentError)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "post" do
|
28
|
+
subject { Localhook::WebhookForwarder.new("http://localhost:8080") }
|
29
|
+
it "forward request to remote server via em" do
|
30
|
+
params = {head: {}, path: "/a/b", query: "", body: ""}
|
31
|
+
request = double(:request)
|
32
|
+
expect(request).to receive(:post).with(params).and_return(request)
|
33
|
+
expect(request).to receive(:callback)
|
34
|
+
expect(request).to receive(:errback)
|
35
|
+
expect(EventMachine::HttpRequest).to receive(:new).with(subject.url, subject.http_options).and_return(request)
|
36
|
+
subject.post("/a/b", "", {}, "")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: localhook
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Francis Chong
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: claide
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: em-http-request
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: em-eventsource
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yajl-ruby
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.5'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.5'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Localhook makes it super easy to connect public webhook endpoints with
|
112
|
+
development environments.
|
113
|
+
email:
|
114
|
+
- francis@ignition.hk
|
115
|
+
executables:
|
116
|
+
- localhook
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- ".gitignore"
|
121
|
+
- Gemfile
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- bin/localhook
|
126
|
+
- lib/localhook.rb
|
127
|
+
- lib/localhook/command.rb
|
128
|
+
- lib/localhook/event_source.rb
|
129
|
+
- lib/localhook/version.rb
|
130
|
+
- lib/localhook/webhook_forwarder.rb
|
131
|
+
- localhook.gemspec
|
132
|
+
- spec/command_spec.rb
|
133
|
+
- spec/event_source_spec.rb
|
134
|
+
- spec/webbook_forwarder_spec.rb
|
135
|
+
homepage: https://github.com/siuying/localhook
|
136
|
+
licenses:
|
137
|
+
- MIT
|
138
|
+
metadata: {}
|
139
|
+
post_install_message:
|
140
|
+
rdoc_options: []
|
141
|
+
require_paths:
|
142
|
+
- lib
|
143
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
requirements: []
|
154
|
+
rubyforge_project:
|
155
|
+
rubygems_version: 2.2.0
|
156
|
+
signing_key:
|
157
|
+
specification_version: 4
|
158
|
+
summary: Localhook let you receive webhooks on localhost.
|
159
|
+
test_files:
|
160
|
+
- spec/command_spec.rb
|
161
|
+
- spec/event_source_spec.rb
|
162
|
+
- spec/webbook_forwarder_spec.rb
|