apic 0.0.1 → 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.
- checksums.yaml +4 -4
- data/README.md +55 -12
- data/app/assets/javascripts/apic/apic.js.coffee +1 -0
- data/app/assets/javascripts/apic/components/{console.js.coffee → apic_console.js.coffee} +46 -16
- data/app/assets/javascripts/apic/components/endpoints.js.coffee +1 -2
- data/app/assets/javascripts/apic/components/http-headers.js.coffee +1 -1
- data/app/assets/javascripts/apic/components/xhr_history.js.coffee +48 -0
- data/app/assets/stylesheets/apic/components/http-headers.css.scss +0 -3
- data/app/assets/stylesheets/apic/components/xhr-history.css.scss +16 -0
- data/app/controllers/apic/application_controller.rb +8 -0
- data/app/views/apic/application/_navigation.html.slim +2 -0
- data/app/views/apic/application/components/_endpoints.html.slim +1 -1
- data/app/views/apic/application/components/_xhr_history.html.slim +2 -0
- data/app/views/apic/application/index.html.slim +2 -0
- data/config/routes.rb +11 -2
- data/lib/apic/engine.rb +1 -0
- data/lib/apic/generators/install_generator.rb +22 -0
- data/lib/apic/generators/templates/apic.rb +10 -0
- data/lib/apic/version.rb +1 -1
- data/lib/apic.rb +5 -6
- metadata +12 -8
- data/app/controllers/apic/controller.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62e91d7da069396fc04033442798fcfa93717c2e
|
4
|
+
data.tar.gz: 09884be511addc4b3a701d8a16ce9e1373a08358
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34c1269243b0ffe1e7908d577a8776703445a62dfd1cd4aea88a88f2d166e964580c7d4420d2a83296324709b3f8721364fcbb79b2e04f7f62bf97ad538c0a09
|
7
|
+
data.tar.gz: 4353172bb5077836055d5778326664e3b05a84a6347b4026d3c6f9ed4a65a0fff394e614d997d71bd35cd2ea08b733c8766b332bd72978f49fb09307787a162b
|
data/README.md
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
-
=
|
1
|
+
= APIc
|
2
2
|
|
3
|
-
|
3
|
+
## What is it?
|
4
4
|
|
5
|
+
APIc is a bolt on API console for Rails 3+ applications.
|
6
|
+
It rounds up your endpoints and makes it dead easy to configure, send, review and replay any request.
|
7
|
+
|
8
|
+
|
9
|
+

|
5
10
|
|
6
11
|
What you need to do?
|
7
12
|
|
@@ -11,35 +16,73 @@ add the gem to your Gemfile
|
|
11
16
|
gem 'apic'
|
12
17
|
```
|
13
18
|
|
14
|
-
|
19
|
+
Run the generator!
|
15
20
|
|
16
21
|
```
|
17
|
-
|
22
|
+
rails generate apic:install
|
18
23
|
```
|
19
24
|
|
20
|
-
|
25
|
+
If you are using bundler:
|
21
26
|
|
22
27
|
```
|
23
|
-
|
28
|
+
bundle exec rails generate apic:install
|
29
|
+
|
24
30
|
```
|
25
31
|
|
26
|
-
|
32
|
+
Spin up your Rails application and navigate to
|
33
|
+
|
34
|
+
```
|
35
|
+
localhost:3000/apic
|
36
|
+
```
|
27
37
|
|
28
|
-
Filter routes on a regex match
|
29
38
|
|
30
39
|
|
40
|
+
## Configuration
|
41
|
+
|
42
|
+
### Controller Parameters
|
43
|
+
|
44
|
+
APIc needs to know about the parameters your PUT, PATCH and UPDATE requests require.
|
45
|
+
To make this as simple and painless as possible, APIc exposes a DSL to your controllers so you can specify what you need.
|
46
|
+
APIc knows what type of routes are available and will automatically add in the _method parameter and value for PATCH and DELETE requests.
|
47
|
+
|
31
48
|
```
|
32
|
-
|
49
|
+
class TestController << ActionController.base
|
50
|
+
|
51
|
+
apic_action_params create: [:name, :acceptance]
|
52
|
+
|
53
|
+
def create
|
54
|
+
# all your cool stuff that creates a new object
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
### Initializer
|
61
|
+
|
62
|
+
The apic:install generator will add in a default intializer providing examples of the route matching and authentication filtering.
|
63
|
+
|
33
64
|
```
|
65
|
+
config/initializers/apic.rb
|
66
|
+
```
|
67
|
+
|
68
|
+
#### Route Matching
|
69
|
+
|
70
|
+
APIc will load all routes in your rails app by default under the assumption that you are building your api as a dedicated service.
|
71
|
+
If this is not the case, you can specify a matching regular expression that APIc will use to find your API routes.
|
34
72
|
|
35
|
-
|
73
|
+
For example, if you have namespecs all of your api endpoints to /api/v1/ simply uncomment out the Apic.routes_matcher line in config/initializers/apic.rb
|
36
74
|
|
37
75
|
```
|
38
|
-
Apic.
|
76
|
+
Apic.route_matcher = /\/api\/v1\//
|
39
77
|
```
|
40
78
|
|
79
|
+
#### Authentication filters
|
41
80
|
|
42
|
-
|
81
|
+
When testing your API it is often convenient to know which routes require authentication as you will need to add those headers before sending your request.
|
82
|
+
If you specify in your configuration the before_filter you are using for authentication APIc will mark those routes as restricted.
|
43
83
|
|
84
|
+
```
|
85
|
+
Apic.authentication_filter = :authenticate
|
86
|
+
```
|
44
87
|
|
45
88
|
This project rocks and uses MIT-LICENSE.
|
@@ -9,6 +9,7 @@ $.fn.extend
|
|
9
9
|
params: '.parameter',
|
10
10
|
console: '.console',
|
11
11
|
console_log: '.console-log',
|
12
|
+
history: '.xhr-history',
|
12
13
|
host: 'localhost:3000',
|
13
14
|
request_timeout: 10000,
|
14
15
|
timeout_callback: null,
|
@@ -16,6 +17,8 @@ $.fn.extend
|
|
16
17
|
|
17
18
|
self = this
|
18
19
|
|
20
|
+
history = []
|
21
|
+
|
19
22
|
settings = $.extend settings, options
|
20
23
|
|
21
24
|
log_timeline = (method, uri) ->
|
@@ -25,13 +28,14 @@ $.fn.extend
|
|
25
28
|
|
26
29
|
log_request = (xhr) ->
|
27
30
|
self._start = new Date().getTime()
|
28
|
-
console.log xhr
|
29
|
-
log_message "Request URL", uri()
|
30
|
-
log_message "Request Method", endpoint().verb
|
31
|
-
log_message "Response Code", [xhr.status, xhr.statusText].join(' ')
|
32
|
-
log_message "Request Headers", xhr.getAllResponseHeaders()
|
33
31
|
|
34
|
-
|
32
|
+
$(settings.console_log).empty()
|
33
|
+
log_item "Request URL", uri()
|
34
|
+
log_item "Request Method", endpoint().verb
|
35
|
+
log_item "Response Code", [xhr.status, xhr.statusText].join(' ')
|
36
|
+
log_item "Request Headers", xhr.getAllResponseHeaders()
|
37
|
+
|
38
|
+
log_item = (title, message) ->
|
35
39
|
$(settings.console_log).append('<div><span class="log-header">' + title + '</span>:<span class="log-data"> ' + message + '</span></div>')
|
36
40
|
|
37
41
|
duration = ->
|
@@ -57,7 +61,6 @@ $.fn.extend
|
|
57
61
|
path += query_string()
|
58
62
|
path
|
59
63
|
|
60
|
-
$('#do-me').on('click', -> send.apply self)
|
61
64
|
|
62
65
|
value_for = (name) ->
|
63
66
|
$(settings.params + ' [name="' + name + '"]').val()
|
@@ -89,14 +92,19 @@ $.fn.extend
|
|
89
92
|
$(settings.console).text(xhr.responseText)
|
90
93
|
|
91
94
|
log_request xhr
|
95
|
+
record(xhr)
|
92
96
|
|
93
97
|
onerror = (response) ->
|
94
98
|
console.log response
|
95
99
|
|
96
|
-
request = () ->
|
100
|
+
request = (endpoint, headers, uri) ->
|
97
101
|
xhr = new XMLHttpRequest
|
98
|
-
xhr.open endpoint
|
99
|
-
|
102
|
+
xhr.open endpoint.verb, uri, true
|
103
|
+
$.each headers, (key, value) ->
|
104
|
+
if key is 'Authorization'
|
105
|
+
xhr.withCredentials = true
|
106
|
+
xhr.setRequestHeader(key, value)
|
107
|
+
|
100
108
|
xhr.onerror = (xhr) ->
|
101
109
|
onerror.apply self, [xhr]
|
102
110
|
xhr.onload = (response) ->
|
@@ -105,6 +113,8 @@ $.fn.extend
|
|
105
113
|
|
106
114
|
set_headers = (xhr) ->
|
107
115
|
$.each headers(), (key, value) ->
|
116
|
+
if key is 'Authorization'
|
117
|
+
xhr.withCredentials = true
|
108
118
|
xhr.setRequestHeader(key, value)
|
109
119
|
|
110
120
|
validate_params = () ->
|
@@ -112,14 +122,34 @@ $.fn.extend
|
|
112
122
|
for part in endpoint().parts
|
113
123
|
if value_for(part) is ""
|
114
124
|
missing.push(part)
|
115
|
-
|
116
|
-
|
125
|
+
if missing.length > 0
|
126
|
+
alert('url parts reqired: ' + missing)
|
117
127
|
missing.length is 0
|
118
128
|
|
119
|
-
|
129
|
+
record = (xhr) ->
|
130
|
+
history_item =
|
131
|
+
endpoint: endpoint()
|
132
|
+
headers: headers()
|
133
|
+
body: body()
|
134
|
+
uri: uri()
|
135
|
+
xhr: xhr
|
136
|
+
|
137
|
+
$(settings.history).trigger('add', [history_item])
|
138
|
+
|
139
|
+
send = (_point, _head, _bod, _u) ->
|
140
|
+
_point ||= endpoint()
|
141
|
+
_head ||= headers()
|
142
|
+
_bod ||= body()
|
143
|
+
_u ||= uri()
|
144
|
+
|
120
145
|
if validate_params()
|
121
|
-
xhr = request()
|
122
|
-
if
|
146
|
+
xhr = request(_point, _head, _u)
|
147
|
+
if _point.verb is 'GET'
|
123
148
|
xhr.send()
|
124
149
|
else
|
125
|
-
|
150
|
+
data = JSON.stringify(_bod)
|
151
|
+
xhr.send(data)
|
152
|
+
|
153
|
+
$('#do-me').on('click', -> send.apply self, [null])
|
154
|
+
$(self).on('send', (e, point, head, bod, u) -> send.apply self, [point, head, bod, u])
|
155
|
+
true
|
@@ -13,7 +13,6 @@ $.fn.extend
|
|
13
13
|
|
14
14
|
$.each endpoints, (key, value) ->
|
15
15
|
option = $('<option>'+ key + '</option>')
|
16
|
-
console.log value
|
17
16
|
option.text('[restricted] ' + option.text()) if value.authorization_required
|
18
17
|
$(settings.select).append(option)
|
19
18
|
|
@@ -32,7 +31,7 @@ $.fn.extend
|
|
32
31
|
el.find('#input-_method').val(endpoint.verb.toLowerCase())
|
33
32
|
|
34
33
|
selected = ->
|
35
|
-
endpoints[$(settings.select).val()]
|
34
|
+
endpoints[$(settings.select).val().replace('[restricted] ', '')]
|
36
35
|
|
37
36
|
field_set_for = (name, options={}) ->
|
38
37
|
clone = $(self).find(settings.template).clone()
|
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
$.fn.extend
|
3
|
+
|
4
|
+
xhr_history: (options) ->
|
5
|
+
defaults = {}
|
6
|
+
self = this
|
7
|
+
$(self).data('items', [])
|
8
|
+
|
9
|
+
refresh = ->
|
10
|
+
$(self).empty()
|
11
|
+
$.each items(), (index, item) ->
|
12
|
+
el = list_item(item)
|
13
|
+
el.data('request', item)
|
14
|
+
|
15
|
+
$(self).append el
|
16
|
+
|
17
|
+
list_item = (item) ->
|
18
|
+
$('<li class="xhr-history-item ' + item.xhr.statusText.toLowerCase() + '"><a href="#"><i class="icon-refresh icon-white ' + item.xhr.statusText.toLowerCase() + '"/><i>' + item.xhr.status + ' '+ item.endpoint.verb + ' ' + item.uri + '</span></a></li>')
|
19
|
+
|
20
|
+
items = ->
|
21
|
+
$(self).data('items')
|
22
|
+
|
23
|
+
add = (item)->
|
24
|
+
i = items()
|
25
|
+
i.push item
|
26
|
+
$(self).data('items',i)
|
27
|
+
refresh()
|
28
|
+
|
29
|
+
replay = (el) ->
|
30
|
+
request = $(el).data('request')
|
31
|
+
$('.console').trigger('send', [request.endpoint, request.headers, request.body, request.uri])
|
32
|
+
console.log($(el).data('request'))
|
33
|
+
|
34
|
+
show = ->
|
35
|
+
el = $('.history')
|
36
|
+
el.toggle()
|
37
|
+
|
38
|
+
li = $(event.target).closest('li')
|
39
|
+
if $(el).is(':visible')
|
40
|
+
li.addClass('active')
|
41
|
+
else
|
42
|
+
li.removeClass('active')
|
43
|
+
|
44
|
+
#$(self).on('refresh', -> refresh.apply self)
|
45
|
+
$(self).on('add', (e, item) -> add.apply self, [item])
|
46
|
+
$('.xhr-history').on('dblclick', 'li', (e) -> replay this)
|
47
|
+
$('.toggle-history').on('click', -> show.apply self)
|
48
|
+
this
|
@@ -0,0 +1,16 @@
|
|
1
|
+
.history {
|
2
|
+
display: none;
|
3
|
+
border-top: 1px solid #DDD;
|
4
|
+
padding: 5px;
|
5
|
+
}
|
6
|
+
.xhr-history {
|
7
|
+
list-style-type: none;
|
8
|
+
i.forbidden {
|
9
|
+
background-color: red;
|
10
|
+
margin-right: 5px;
|
11
|
+
}
|
12
|
+
i.ok {
|
13
|
+
background-color: green;
|
14
|
+
margin-right: 5px;
|
15
|
+
}
|
16
|
+
}
|
@@ -5,7 +5,7 @@ div.endpoints-component( data-endpoints="#{@endpoints.to_json}")
|
|
5
5
|
div.control-group
|
6
6
|
label.control-label(for="selectEndpoint") Api Endpoint
|
7
7
|
div.controls
|
8
|
-
select(id='selectEndpoint')
|
8
|
+
select.input-xxlarge(id='selectEndpoint')
|
9
9
|
|
10
10
|
div.control-group.template
|
11
11
|
label.control-label(for="inputParam") Param Name
|
data/config/routes.rb
CHANGED
data/lib/apic/engine.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
module Apic
|
3
|
+
module Generators
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path("../../generators/templates", __FILE__)
|
6
|
+
|
7
|
+
desc "creates initializer and add engine mount point to your routes"
|
8
|
+
|
9
|
+
def copy_initializer
|
10
|
+
template 'apic.rb', 'config/initializers/apic.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
def mount_engine
|
14
|
+
if Rails.version < '4.0.0'
|
15
|
+
route 'mount Apic::Engine, :at => "/apic"'
|
16
|
+
else
|
17
|
+
route 'mount Apic::Engine => "/apic"'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Specify a route matcher to restrict which application routes are available
|
2
|
+
# in the console. By default all routes will be loaded
|
3
|
+
#
|
4
|
+
# Apic.route_matcher = /\/api\/v1\//
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# Specify your authentication filter. Requests that use this filter will be marked
|
8
|
+
# as restricted in the Api endpoints list.
|
9
|
+
#
|
10
|
+
# Apic.authentication_filter = :authenticate
|
data/lib/apic/version.rb
CHANGED
data/lib/apic.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'apic/params_cache'
|
2
2
|
require "apic/extension"
|
3
3
|
require "apic/engine"
|
4
|
-
|
4
|
+
require "apic/generators/install_generator"
|
5
5
|
module Apic
|
6
6
|
|
7
|
-
mattr_accessor :
|
8
|
-
@@
|
7
|
+
mattr_accessor :authentication_filter
|
8
|
+
@@authentication_filter = nil
|
9
9
|
|
10
10
|
mattr_accessor :route_matcher
|
11
11
|
@@route_matcher = /\/api\//
|
@@ -35,12 +35,11 @@ module Apic
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.requires_authorization(controller, action_name)
|
38
|
-
return false unless @@
|
38
|
+
return false unless @@authentication_filter
|
39
39
|
controller = (controller + '_controller').camelize.constantize
|
40
40
|
controller._process_action_callbacks.any? do |callback|
|
41
|
-
p @@authorization_filter
|
42
41
|
eval <<-RUBY_EVAL
|
43
|
-
#{callback.filter == @@
|
42
|
+
#{callback.filter == @@authentication_filter} && #{callback.instance_values['compiled_options']}
|
44
43
|
RUBY_EVAL
|
45
44
|
end
|
46
45
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apic
|
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
|
- Randy Morgan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 3.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 3.2.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: slim-rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,25 +104,29 @@ extra_rdoc_files: []
|
|
104
104
|
files:
|
105
105
|
- app/assets/javascripts/apic/apic.js.coffee
|
106
106
|
- app/assets/javascripts/apic/application.js
|
107
|
-
- app/assets/javascripts/apic/components/
|
107
|
+
- app/assets/javascripts/apic/components/apic_console.js.coffee
|
108
108
|
- app/assets/javascripts/apic/components/endpoints.js.coffee
|
109
109
|
- app/assets/javascripts/apic/components/http-headers.js.coffee
|
110
|
+
- app/assets/javascripts/apic/components/xhr_history.js.coffee
|
110
111
|
- app/assets/stylesheets/apic/application.css.scss
|
111
112
|
- app/assets/stylesheets/apic/components/console.css.scss
|
112
113
|
- app/assets/stylesheets/apic/components/endpoints.css.scss
|
113
114
|
- app/assets/stylesheets/apic/components/http-headers.css.scss
|
115
|
+
- app/assets/stylesheets/apic/components/xhr-history.css.scss
|
114
116
|
- app/controllers/apic/application_controller.rb
|
115
|
-
- app/controllers/apic/controller.rb
|
116
117
|
- app/helpers/apic/application_helper.rb
|
117
118
|
- app/views/apic/application/_navigation.html.slim
|
118
119
|
- app/views/apic/application/components/_console.html.slim
|
119
120
|
- app/views/apic/application/components/_endpoints.html.slim
|
120
121
|
- app/views/apic/application/components/_http_headers.html.slim
|
122
|
+
- app/views/apic/application/components/_xhr_history.html.slim
|
121
123
|
- app/views/apic/application/index.html.slim
|
122
124
|
- app/views/layouts/apic/application.html.erb
|
123
125
|
- config/routes.rb
|
124
126
|
- lib/apic/engine.rb
|
125
127
|
- lib/apic/extension.rb
|
128
|
+
- lib/apic/generators/install_generator.rb
|
129
|
+
- lib/apic/generators/templates/apic.rb
|
126
130
|
- lib/apic/params_cache.rb
|
127
131
|
- lib/apic/version.rb
|
128
132
|
- lib/apic.rb
|