endpointer 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -14
- data/bin/console +2 -2
- data/bin/endpointer +6 -1
- data/endpointer.gemspec +2 -2
- data/lib/endpointer/argument_parser.rb +18 -4
- data/lib/endpointer/cacher.rb +7 -2
- data/lib/endpointer/errors/invalid_arguments_error.rb +7 -0
- data/lib/endpointer/errors/invalid_cache_dir_error.rb +7 -0
- data/lib/endpointer/options.rb +8 -1
- data/lib/endpointer/performer_factory.rb +4 -1
- data/lib/endpointer/performers/get.rb +9 -2
- data/lib/endpointer/performers/method.rb +1 -7
- data/lib/endpointer/performers/post.rb +10 -2
- data/lib/endpointer/performers.rb +0 -1
- data/lib/endpointer/resource_executor.rb +4 -5
- data/lib/endpointer/version.rb +1 -1
- data/lib/endpointer.rb +8 -5
- metadata +6 -5
- data/bin/setup +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc331a3a040610cc6532a7a9ca8efb99a91076f7
|
4
|
+
data.tar.gz: 7a398693347e0bdfc2b737db2bab9b63b2236a0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b1ace4fe1e824dbadbcaa67b2a28d8b77b6cfe44ddf880eb3958f222e8c2efd5e9ca0103b1e8e44bf57d5dbad8681d719fcaa78819f7a5fcef95e806c72288f
|
7
|
+
data.tar.gz: bd145e7528efdf64b91bdf01f30071857e8bf1155c3b9ad55916bfecf02b7fd7ccb7ad7fc7be52810234095894afc9b1896c53d90da80e3572489b319fca47a0
|
data/README.md
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/endpointer.svg)](http://badge.fury.io/rb/endpointer) [![Build Status](https://travis-ci.org/zenonas/endpointer.svg?branch=master)](https://travis-ci.org/zenonas/endpointer) [![Code Climate](https://codeclimate.com/github/zenonas/endpointer/badges/gpa.svg)](https://codeclimate.com/github/zenonas/endpointer) [![Test Coverage](https://codeclimate.com/github/zenonas/endpointer/badges/coverage.svg)](https://codeclimate.com/github/zenonas/endpointer/coverage) [![Issue Count](https://codeclimate.com/github/zenonas/endpointer/badges/issue_count.svg)](https://codeclimate.com/github/zenonas/endpointer)
|
4
4
|
|
5
|
-
Endpointer is a small gem that tries to act as a caching proxy between your dev machine and any web service. The motivation was to provide an easy to configure and use fake web service that is able to host
|
5
|
+
Endpointer is a small gem that tries to act as a caching proxy between your dev machine and any web service. The motivation was to provide an easy to configure and use fake web service that is able to host any amount of resources, returning canned responses, that are easy to modify. Please note the gem is still in early and active development and as such some features may be missing. For a list of features that are still missing consult [the list at the end of this readme](#upcoming-features). If you would like a feature please feel free to raise an issue or a pull request. All contributions are welcome.
|
6
6
|
|
7
7
|
## Requirements
|
8
8
|
|
9
|
-
* Ruby 2.
|
9
|
+
* Ruby 2.2+ (Tests running against MRI 2.4.0, 2.3.3, and JRuby 9.1.6.0)
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
@@ -47,26 +47,39 @@ You can then invoke endpointer by executing
|
|
47
47
|
|
48
48
|
$ endpointer [--invalidate] <path_to_json_config_file>
|
49
49
|
|
50
|
-
|
51
|
-
|
50
|
+
Or, include it in a config.ru
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
|
54
|
+
#config.ru
|
55
|
+
require 'endpointer'
|
56
|
+
|
57
|
+
run Endpointer.app(['--invalidate', '<path_to_json_file>'])
|
58
|
+
```
|
59
|
+
|
60
|
+
Endpointer will attempt to return a cached resource, if one is found to match the request. Otherwise, a call to the real service will be performed and the response, if successful, persisted.
|
61
|
+
|
62
|
+
A simple example request to endpointer using cURL:
|
52
63
|
|
53
64
|
$ curl http://localhost:4567/get
|
54
65
|
|
55
|
-
If the request is to be executed against the real service the headers defined in the config will be used with their default values unless overridden
|
66
|
+
If the request is to be executed against the real service the headers defined in the config will be used with their default values unless overridden. An example request overriding the Accept header follows.
|
56
67
|
|
57
68
|
$ curl -H "Accept: text/plain" http://localhost:4567/get
|
58
69
|
|
59
70
|
### Caching
|
60
71
|
|
61
|
-
By default endpointer will use your operating
|
72
|
+
By default endpointer will use your operating system's temp directory to store its cache files `(TMP_DIR/endpointer_cache)`. In order to configure the cache path you need to pass the `--cache-dir=<path>` argument.
|
73
|
+
|
74
|
+
$ endpointer [--invalidate] [--cache-dir=/path/to/cache] <path_to_json_config_file>
|
62
75
|
|
63
|
-
You can provide the `--invalidate` flag to the command line to invalidate the cache. This empties the endpointer_cache directory
|
76
|
+
You can provide the `--invalidate` flag to the command line to invalidate the cache. This empties the endpointer_cache directory.
|
64
77
|
|
65
78
|
## Development
|
66
79
|
|
67
|
-
After checking out the repo, run `
|
80
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
68
81
|
|
69
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
82
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
70
83
|
|
71
84
|
## Contributing
|
72
85
|
|
@@ -74,14 +87,12 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/zenona
|
|
74
87
|
|
75
88
|
### Upcoming features
|
76
89
|
|
77
|
-
As mentioned above I'm actively going to work on improving endpointer and the following are a few features that I would like to see implemented. Feel free to suggest new ones or work on one
|
90
|
+
As mentioned above I'm actively going to work on improving endpointer and the following are a few features that I would like to see implemented. Feel free to suggest new ones or work on one yourself.
|
78
91
|
|
79
|
-
* Custom cache path
|
80
92
|
* The ability to easily edit cached files. Maybe a second executable that allows you to edit the canned responses in a pretty JSON format
|
81
|
-
* Support all HTTP verbs(currently only GET, POST are supported methods)
|
82
93
|
* A `--debug` flag to the command line that will give a pry window on every request allowing you to play with the Request and Response objects.
|
83
|
-
*
|
84
|
-
*
|
94
|
+
* Configurable port(this can already be done if using config.ru)
|
95
|
+
* Support multiple key/value stores for caching. Currently only uses local YAML files. One Suggestion is Redis support.
|
85
96
|
|
86
97
|
## License
|
87
98
|
|
data/bin/console
CHANGED
data/bin/endpointer
CHANGED
@@ -3,4 +3,9 @@
|
|
3
3
|
require "bundler/setup"
|
4
4
|
require "endpointer"
|
5
5
|
|
6
|
-
|
6
|
+
begin
|
7
|
+
Endpointer.run ARGV
|
8
|
+
rescue Endpointer::Errors::InvalidArgumentsError
|
9
|
+
STDERR.puts "Usage: endpointer [--invalidate] [--cache-dir=/path/to/cache] <path_to_json_config>.json"
|
10
|
+
exit 1
|
11
|
+
end
|
data/endpointer.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Zen Kyprianou"]
|
10
10
|
spec.email = ["endpointer@zenonas.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{
|
13
|
-
spec.description = %q{Allows you to define endpoints to serve via a
|
12
|
+
spec.summary = %q{For when you stacks too big for your box}
|
13
|
+
spec.description = %q{Allows you to define endpoints to serve via a small caching proxy}
|
14
14
|
spec.homepage = "https://github.com/zenonas/endpointer"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -5,6 +5,11 @@ require 'json'
|
|
5
5
|
module Endpointer
|
6
6
|
class ArgumentParser
|
7
7
|
|
8
|
+
VALID_OPTIONS = [
|
9
|
+
'--invalidate',
|
10
|
+
'--cache-dir='
|
11
|
+
]
|
12
|
+
|
8
13
|
def initialize(arguments)
|
9
14
|
@arguments = arguments
|
10
15
|
end
|
@@ -20,11 +25,23 @@ module Endpointer
|
|
20
25
|
build_options_from(options)
|
21
26
|
end
|
22
27
|
|
28
|
+
def valid?
|
29
|
+
return false unless config_file
|
30
|
+
valid_arguments = VALID_OPTIONS + [config_file]
|
31
|
+
return false if @arguments.any? { |arg|
|
32
|
+
valid_arguments.none? { |valid_opt| arg.include?(valid_opt) }
|
33
|
+
}
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
23
37
|
private
|
24
38
|
|
25
39
|
def build_options_from(parsed_options)
|
26
40
|
invalidate = parsed_options.include?("--invalidate")
|
27
|
-
|
41
|
+
cache_dir_arg = parsed_options.find { |opt| opt.match(/^--cache-dir/) }
|
42
|
+
cache_dir = cache_dir_arg.split('=').last unless cache_dir_arg.nil?
|
43
|
+
|
44
|
+
Options.new(invalidate, cache_dir)
|
28
45
|
end
|
29
46
|
|
30
47
|
def config_file
|
@@ -35,9 +52,6 @@ module Endpointer
|
|
35
52
|
JSON.parse(File.read(config_file))
|
36
53
|
end
|
37
54
|
|
38
|
-
def resources_from_config_file
|
39
|
-
end
|
40
|
-
|
41
55
|
def option_argument?(argument)
|
42
56
|
argument.match(/^--.*/)
|
43
57
|
end
|
data/lib/endpointer/cacher.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'endpointer/errors/cached_item_not_found_error'
|
2
|
+
require 'endpointer/errors/invalid_cache_dir_error'
|
2
3
|
require 'endpointer/cache_container'
|
3
4
|
require 'yaml'
|
4
5
|
|
@@ -40,8 +41,12 @@ module Endpointer
|
|
40
41
|
end
|
41
42
|
|
42
43
|
def initialize_path(path)
|
43
|
-
|
44
|
-
|
44
|
+
begin
|
45
|
+
@path = path
|
46
|
+
Dir.mkdir(@path) unless File.exists?(@path)
|
47
|
+
rescue Errno::ENOENT => e
|
48
|
+
raise Endpointer::Errors::InvalidCacheDirError.new(e.message)
|
49
|
+
end
|
45
50
|
end
|
46
51
|
end
|
47
52
|
end
|
data/lib/endpointer/options.rb
CHANGED
@@ -1,4 +1,11 @@
|
|
1
1
|
module Endpointer
|
2
|
-
class Options
|
2
|
+
class Options
|
3
|
+
|
4
|
+
attr_accessor :invalidate, :cache_dir
|
5
|
+
|
6
|
+
def initialize(invalidate = nil, cache_dir = nil)
|
7
|
+
@invalidate = invalidate || false
|
8
|
+
@cache_dir = cache_dir || File.join(Dir.tmpdir, "endpointer_cache")
|
9
|
+
end
|
3
10
|
end
|
4
11
|
end
|
@@ -6,7 +6,10 @@ module Endpointer
|
|
6
6
|
|
7
7
|
PERFORMERS = {
|
8
8
|
get: Endpointer::Performers::Get,
|
9
|
-
post: Endpointer::Performers::Post
|
9
|
+
post: Endpointer::Performers::Post,
|
10
|
+
put: Endpointer::Performers::Post,
|
11
|
+
patch: Endpointer::Performers::Post,
|
12
|
+
delete: Endpointer::Performers::Get
|
10
13
|
}
|
11
14
|
|
12
15
|
def self.create(method)
|
@@ -4,12 +4,19 @@ require 'rest-client'
|
|
4
4
|
|
5
5
|
module Endpointer
|
6
6
|
module Performers
|
7
|
-
class Get
|
7
|
+
class Get
|
8
|
+
include Endpointer::Performers::Method
|
8
9
|
|
9
10
|
def execute(request, resource)
|
11
|
+
execute_method(resource.method, request, resource)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def execute_method(method, request, resource)
|
10
17
|
begin
|
11
18
|
url = File.join(create_hostname(resource), create_path(request))
|
12
|
-
response = RestClient::Request.execute(method:
|
19
|
+
response = RestClient::Request.execute(method: method, url: url, headers: create_headers(request, resource))
|
13
20
|
rescue RestClient::ExceptionWithResponse => e
|
14
21
|
response = e.response
|
15
22
|
end
|
@@ -3,13 +3,7 @@ require 'uri'
|
|
3
3
|
|
4
4
|
module Endpointer
|
5
5
|
module Performers
|
6
|
-
|
7
|
-
|
8
|
-
def execute(request, resource)
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
6
|
+
module Method
|
13
7
|
def create_headers(request, resource)
|
14
8
|
resource.headers.keys.each_with_object({}) do |key, header|
|
15
9
|
header[key] = request_header_or_default(key, request, resource)
|
@@ -4,11 +4,19 @@ require 'rest-client'
|
|
4
4
|
|
5
5
|
module Endpointer
|
6
6
|
module Performers
|
7
|
-
class Post
|
7
|
+
class Post
|
8
|
+
include Endpointer::Performers::Method
|
9
|
+
|
8
10
|
def execute(request, resource)
|
11
|
+
execute_method(resource.method, request, resource)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def execute_method(method, request, resource)
|
9
17
|
begin
|
10
18
|
url = File.join(create_hostname(resource), create_path(request))
|
11
|
-
response = RestClient.
|
19
|
+
response = RestClient.send(method,
|
12
20
|
url,
|
13
21
|
request.body.string,
|
14
22
|
create_headers(request, resource)
|
@@ -6,19 +6,18 @@ module Endpointer
|
|
6
6
|
|
7
7
|
def perform(request, resource, options)
|
8
8
|
begin
|
9
|
-
cache.get(resource)
|
9
|
+
cache(options.cache_dir).get(resource)
|
10
10
|
rescue Endpointer::Errors::CachedItemNotFoundError => e
|
11
11
|
response = Endpointer::PerformerFactory.create(resource.method).execute(request, resource)
|
12
|
-
cache.set(resource, response)
|
12
|
+
cache(options.cache_dir).set(resource, response)
|
13
13
|
response
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
-
def cache
|
20
|
-
@cache ||= Endpointer::Cacher.new(
|
19
|
+
def cache(cache_dir)
|
20
|
+
@cache ||= Endpointer::Cacher.new(cache_dir)
|
21
21
|
end
|
22
|
-
|
23
22
|
end
|
24
23
|
end
|
data/lib/endpointer/version.rb
CHANGED
data/lib/endpointer.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
require "endpointer/version"
|
2
2
|
require "endpointer/argument_parser"
|
3
3
|
require "endpointer/app_creator"
|
4
|
+
require "endpointer/errors/invalid_arguments_error"
|
4
5
|
|
5
6
|
module Endpointer
|
6
7
|
|
7
|
-
CACHE_DIR = File.join(Dir.tmpdir, "endpointer_cache")
|
8
|
-
|
9
8
|
def self.run(arguments)
|
9
|
+
app(arguments).run!
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.app(arguments)
|
10
13
|
argument_parser = ArgumentParser.new(arguments)
|
14
|
+
raise Errors::InvalidArgumentsError unless argument_parser.valid?
|
11
15
|
options = argument_parser.parse_options
|
12
|
-
Cacher.new(
|
13
|
-
|
14
|
-
app.run!
|
16
|
+
Cacher.new(options.cache_dir).invalidate if options.invalidate
|
17
|
+
AppCreator.new.create(argument_parser.parse_resources, options)
|
15
18
|
end
|
16
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: endpointer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zen Kyprianou
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -150,7 +150,7 @@ dependencies:
|
|
150
150
|
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
-
description: Allows you to define endpoints to serve via a
|
153
|
+
description: Allows you to define endpoints to serve via a small caching proxy
|
154
154
|
email:
|
155
155
|
- endpointer@zenonas.com
|
156
156
|
executables:
|
@@ -169,7 +169,6 @@ files:
|
|
169
169
|
- Rakefile
|
170
170
|
- bin/console
|
171
171
|
- bin/endpointer
|
172
|
-
- bin/setup
|
173
172
|
- endpointer.gemspec
|
174
173
|
- lib/endpointer.rb
|
175
174
|
- lib/endpointer/app.rb
|
@@ -178,6 +177,8 @@ files:
|
|
178
177
|
- lib/endpointer/cache_container.rb
|
179
178
|
- lib/endpointer/cacher.rb
|
180
179
|
- lib/endpointer/errors/cached_item_not_found_error.rb
|
180
|
+
- lib/endpointer/errors/invalid_arguments_error.rb
|
181
|
+
- lib/endpointer/errors/invalid_cache_dir_error.rb
|
181
182
|
- lib/endpointer/errors/performer_not_found_error.rb
|
182
183
|
- lib/endpointer/options.rb
|
183
184
|
- lib/endpointer/performer_factory.rb
|
@@ -213,5 +214,5 @@ rubyforge_project:
|
|
213
214
|
rubygems_version: 2.6.8
|
214
215
|
signing_key:
|
215
216
|
specification_version: 4
|
216
|
-
summary:
|
217
|
+
summary: For when you stacks too big for your box
|
217
218
|
test_files: []
|