apic 0.0.3 → 0.0.4
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 +9 -1
- data/app/assets/javascripts/apic/components/apic_console.js.coffee +46 -42
- data/app/assets/javascripts/apic/components/endpoints.js.coffee +35 -3
- data/app/assets/javascripts/apic/components/http-headers.js.coffee +6 -0
- data/app/assets/javascripts/apic/components/xhr_history.js.coffee +2 -3
- data/app/assets/stylesheets/apic/components/endpoints.css.scss +3 -0
- data/app/views/apic/application/components/_endpoints.html.slim +31 -4
- data/app/views/apic/application/components/_http_headers.html.slim +1 -1
- data/lib/apic/route_wrapper.rb +1 -1
- data/lib/apic/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0e7799efebd063e0552aaa1e4d228a52cf7686f
|
4
|
+
data.tar.gz: 275901e0611bfe5f365b369f5b3875ebeab71e07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01d892744c5de8ba1fd36943517c9452ee3d57d907be6fff7ae8eb1198cd6ce275ade2f47c4d9b1501ad14e530b33b880af277879c45061b179705a127e511ed
|
7
|
+
data.tar.gz: 47347d896f2546785217e2af4ddbde1bc6ef3919b18495a078f4aa29c6fe456c601d52f10873f8206c0113d67c84ad9e1e050b0d82ac47fcbd76cbda150d46cb
|
data/README.md
CHANGED
@@ -57,6 +57,8 @@ class TestController < ActionController.base
|
|
57
57
|
end
|
58
58
|
```
|
59
59
|
|
60
|
+
Additionally, you can specify custom parameters via the UI so if you dont want to declare your action parameters in your controllers you can always add them from the APIc console.
|
61
|
+
|
60
62
|
### Initializer
|
61
63
|
|
62
64
|
The apic:install generator will mount APIc to /apic and add in a default intializer providing examples of the route matching and authentication filtering.
|
@@ -131,7 +133,13 @@ This project rocks and uses MIT-LICENSE.
|
|
131
133
|
|
132
134
|
### Change log
|
133
135
|
|
134
|
-
#### 2013.10.05
|
136
|
+
#### 2013.10.05 version 0.0.4
|
137
|
+
- Added support for declaring customized parameters in the APIc console UI.
|
138
|
+
- Patched bug in action_params collection
|
139
|
+
- Improved log output to show full request and response details.
|
140
|
+
- Improved replay to rebuild the headers and endpoint section of the APIc console UI when you click on a history item.
|
141
|
+
|
142
|
+
#### 2013.10.05 version 0.0.3
|
135
143
|
- Removed the default 'api' route matching.
|
136
144
|
- Rationalized route matching to ensure that internal and apic routes are not exposed as endpoints.
|
137
145
|
- Altered history links to replay on single click instead of double click.
|
@@ -4,15 +4,15 @@
|
|
4
4
|
$.fn.extend
|
5
5
|
apic_console: (options) ->
|
6
6
|
settings =
|
7
|
-
endpoint: '.endpoints-component'
|
8
|
-
headers: '.http-headers'
|
9
|
-
params: '.parameter'
|
10
|
-
console: '.console'
|
11
|
-
console_log: '.console-log'
|
12
|
-
history: '.xhr-history'
|
13
|
-
host: 'localhost:3000'
|
14
|
-
request_timeout: 10000
|
15
|
-
timeout_callback: null
|
7
|
+
endpoint: '.endpoints-component'
|
8
|
+
headers: '.http-headers'
|
9
|
+
params: '.parameter'
|
10
|
+
console: '.console'
|
11
|
+
console_log: '.console-log'
|
12
|
+
history: '.xhr-history'
|
13
|
+
host: 'localhost:3000'
|
14
|
+
request_timeout: 10000
|
15
|
+
timeout_callback: null
|
16
16
|
response_callback: null
|
17
17
|
|
18
18
|
self = this
|
@@ -21,31 +21,14 @@ $.fn.extend
|
|
21
21
|
|
22
22
|
settings = $.extend settings, options
|
23
23
|
|
24
|
-
log_timeline = (method, uri) ->
|
25
|
-
self._end = new Date().getTime()
|
26
|
-
if console.log
|
27
|
-
console.log 'Finished: (time: ' + duration() + '):' + method + ' ' + uri
|
28
|
-
|
29
|
-
log_request = (xhr) ->
|
30
|
-
self._start = new Date().getTime()
|
31
|
-
|
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) ->
|
39
|
-
$(settings.console_log).append('<div><span class="log-header">' + title + '</span>:<span class="log-data"> ' + message + '</span></div>')
|
40
|
-
|
41
24
|
duration = ->
|
42
25
|
seconds = 0
|
43
|
-
time = _end - _start
|
26
|
+
time = self._end - self._start
|
44
27
|
try
|
45
28
|
seconds = ((time/10) / 60).toFixed(2)
|
46
29
|
catch e
|
47
30
|
0
|
48
|
-
seconds
|
31
|
+
seconds + ' seconds'
|
49
32
|
|
50
33
|
endpoint = ->
|
51
34
|
$(settings.endpoint).data('endpoint')
|
@@ -57,21 +40,23 @@ $.fn.extend
|
|
57
40
|
path = endpoint().path
|
58
41
|
for part in endpoint().parts
|
59
42
|
path = path.replace(':' + part, value_for part)
|
60
|
-
|
61
|
-
|
43
|
+
if endpoint().verb is 'GET' and query_string().lenght > 0
|
44
|
+
path = [path, query_string()].join('?')
|
62
45
|
path
|
63
46
|
|
64
47
|
|
65
48
|
value_for = (name) ->
|
66
|
-
$(settings.params + ' [name="' + name + '"]').val()
|
49
|
+
$(settings.params + ' input[name="' + name + '"]').val()
|
67
50
|
|
68
51
|
parameters = ->
|
69
52
|
endpoint().template
|
70
53
|
|
71
54
|
body = ->
|
72
55
|
hash = {}
|
73
|
-
|
74
|
-
|
56
|
+
$.each $(settings.params + ' input'), (index, input) ->
|
57
|
+
name = $(input).attr 'name'
|
58
|
+
unless endpoint().parts.indexOf(name) >= 0
|
59
|
+
hash[name] = value_for name
|
75
60
|
hash
|
76
61
|
|
77
62
|
query_string = ->
|
@@ -81,6 +66,10 @@ $.fn.extend
|
|
81
66
|
args.join '&'
|
82
67
|
|
83
68
|
onload = (xhr) ->
|
69
|
+
self._end = new Date().getTime()
|
70
|
+
request = record(xhr)
|
71
|
+
$(settings.console_log).text JSON.stringify(request, undefined, 2)
|
72
|
+
|
84
73
|
if xhr.status is 200
|
85
74
|
try
|
86
75
|
json = JSON.parse(xhr.responseText)
|
@@ -91,11 +80,8 @@ $.fn.extend
|
|
91
80
|
else
|
92
81
|
$(settings.console).text(xhr.responseText)
|
93
82
|
|
94
|
-
log_request xhr
|
95
|
-
record(xhr)
|
96
|
-
|
97
83
|
onerror = (response) ->
|
98
|
-
console.
|
84
|
+
$(settings.console).text 'A network error has occurred. Please refresh the page and ensure that network connections to your API are possible'
|
99
85
|
|
100
86
|
request = (endpoint, headers, uri) ->
|
101
87
|
xhr = new XMLHttpRequest
|
@@ -127,16 +113,32 @@ $.fn.extend
|
|
127
113
|
missing.length is 0
|
128
114
|
|
129
115
|
record = (xhr) ->
|
116
|
+
params = {}
|
117
|
+
$.map $(settings.params + " input"), (param) ->
|
118
|
+
params[$(param).attr('name')] = $(param).val()
|
119
|
+
|
130
120
|
history_item =
|
131
|
-
endpoint: endpoint()
|
132
|
-
headers: headers()
|
133
|
-
body: body()
|
134
121
|
uri: uri()
|
135
|
-
|
122
|
+
duration: duration()
|
123
|
+
headers: headers()
|
124
|
+
parameters: params
|
125
|
+
response: {status: xhr.status, statusText: xhr.statusText }
|
126
|
+
responseHeaders: xhr.getAllResponseHeaders().split('\r\n')
|
127
|
+
endpoint: endpoint()
|
128
|
+
if endpoint().verb != 'GET'
|
129
|
+
history_item['body'] = body()
|
136
130
|
|
137
131
|
$(settings.history).trigger('add', [history_item])
|
132
|
+
history_item
|
133
|
+
|
134
|
+
replay = (request) ->
|
135
|
+
r = $.extend true, {}, request
|
136
|
+
$(settings.headers).trigger 'set', [r.headers]
|
137
|
+
$(settings.endpoint).trigger 'set', [r.endpoint, r.parameters]
|
138
|
+
send r.endpoint, r.headers, r.body, r.uri
|
138
139
|
|
139
140
|
send = (_point, _head, _bod, _u) ->
|
141
|
+
self._start = new Date().getTime()
|
140
142
|
_point ||= endpoint()
|
141
143
|
_head ||= headers()
|
142
144
|
_bod ||= body()
|
@@ -151,5 +153,7 @@ $.fn.extend
|
|
151
153
|
xhr.send(data)
|
152
154
|
|
153
155
|
$('#do-me').on('click', -> send.apply self, [null])
|
154
|
-
|
156
|
+
|
157
|
+
$(self).on('replay', (e, request) -> replay.apply self, [request])
|
158
|
+
|
155
159
|
true
|
@@ -3,7 +3,8 @@ $.fn.extend
|
|
3
3
|
settings =
|
4
4
|
select: '#selectEndpoint',
|
5
5
|
template: '.template',
|
6
|
-
parameter: '.parameter'
|
6
|
+
parameter: '.parameter',
|
7
|
+
restricted: '[restricted] '
|
7
8
|
|
8
9
|
self = this
|
9
10
|
|
@@ -13,14 +14,39 @@ $.fn.extend
|
|
13
14
|
|
14
15
|
$.each endpoints, (key, value) ->
|
15
16
|
option = $('<option>'+ key + '</option>')
|
16
|
-
option.text(
|
17
|
+
option.text(settings.restricted + option.text()) if value.authentication_required
|
17
18
|
$(settings.select).append(option)
|
18
19
|
|
20
|
+
add = (name) ->
|
21
|
+
if !!name
|
22
|
+
el = field_set_for name
|
23
|
+
$(el).find('.icon-remove').removeClass('hide')
|
24
|
+
$(el).find('.remove-parameter').on('click', -> remove.apply self, [el])
|
25
|
+
$('#endpointsModal').modal('hide')
|
26
|
+
|
27
|
+
create = ->
|
28
|
+
$('#inputParameterFieldName').val('')
|
29
|
+
$('#endpointsModal').modal('show')
|
30
|
+
|
31
|
+
remove = (el) ->
|
32
|
+
el.remove()
|
33
|
+
|
19
34
|
change = ->
|
20
35
|
endpoint = selected()
|
21
36
|
$(self).data('endpoint', endpoint)
|
22
37
|
populate_params endpoint
|
23
38
|
|
39
|
+
set = (point, param) ->
|
40
|
+
option = if point.authentication_required then settings.restricted + point.key else point.key
|
41
|
+
$(settings.select).val(option)
|
42
|
+
|
43
|
+
change()
|
44
|
+
|
45
|
+
$.each param, (key, value) ->
|
46
|
+
add(key) if $('input[name="' + key + '"]').length == 0
|
47
|
+
field = $('input[name="' + key + '"]')
|
48
|
+
$(field).val(value)
|
49
|
+
|
24
50
|
populate_params = (endpoint) ->
|
25
51
|
$(self).find(settings.parameter).remove()
|
26
52
|
$.each endpoint.parts, (index, name) ->
|
@@ -31,7 +57,7 @@ $.fn.extend
|
|
31
57
|
el.find('#input-_method').val(endpoint.verb.toLowerCase())
|
32
58
|
|
33
59
|
selected = ->
|
34
|
-
endpoints[$(settings.select).val().replace(
|
60
|
+
endpoints[$(settings.select).val().replace(settings.restricted, '')]
|
35
61
|
|
36
62
|
field_set_for = (name, options={}) ->
|
37
63
|
clone = $(self).find(settings.template).clone()
|
@@ -45,8 +71,14 @@ $.fn.extend
|
|
45
71
|
if options.required
|
46
72
|
clone.find('input').prop('required',true)
|
47
73
|
$(self).find('form').append(clone)
|
74
|
+
clone
|
48
75
|
|
49
76
|
$(settings.select).on 'change', -> change.apply self
|
77
|
+
$('.create-parameter').on 'click', -> create.apply self
|
78
|
+
$('.add-parameter').on 'click', ->
|
79
|
+
add.apply self, [$('#inputParameterFieldName').val()]
|
80
|
+
|
81
|
+
$(self).on 'set', (e, point, params) -> set.apply self, [point, params]
|
50
82
|
change.apply self
|
51
83
|
|
52
84
|
this
|
@@ -49,6 +49,11 @@ $.fn.extend
|
|
49
49
|
$('#inputHttpHeaderFieldName').typeahead({source: settings.headers})
|
50
50
|
selected = undefined
|
51
51
|
|
52
|
+
set = (data) ->
|
53
|
+
$(self).data('items', data)
|
54
|
+
populate()
|
55
|
+
true
|
56
|
+
|
52
57
|
add = ->
|
53
58
|
name = $('#inputHttpHeaderFieldName').val()
|
54
59
|
value = $('#inputHttpHeaderValue').val()
|
@@ -126,6 +131,7 @@ $.fn.extend
|
|
126
131
|
$('.http-headers-list').on('click', 'li', -> select this)
|
127
132
|
$('.http-headers-list').on('dblclick', 'li', -> edit.apply self)
|
128
133
|
$('.edit-headers').on('click', -> show.apply self)
|
134
|
+
$(self).on 'set', (e, headers) -> set.apply self, [headers]
|
129
135
|
|
130
136
|
this
|
131
137
|
|
@@ -15,7 +15,7 @@ $.fn.extend
|
|
15
15
|
$(self).append el
|
16
16
|
|
17
17
|
list_item = (item) ->
|
18
|
-
$('<li class="xhr-history-item ' + item.
|
18
|
+
$('<li class="xhr-history-item ' + item.response.statusText.toLowerCase() + '"><a href="#"><i class="icon-refresh icon-white ' + item.response.statusText.toLowerCase() + '"/><i>' + item.response.status + ' '+ item.endpoint.verb + ' ' + item.uri + '</span></a></li>')
|
19
19
|
|
20
20
|
items = ->
|
21
21
|
$(self).data('items')
|
@@ -28,8 +28,7 @@ $.fn.extend
|
|
28
28
|
|
29
29
|
replay = (el) ->
|
30
30
|
request = $(el).data('request')
|
31
|
-
$('.console').trigger('
|
32
|
-
console.log($(el).data('request'))
|
31
|
+
$('.console').trigger('replay', [request])
|
33
32
|
|
34
33
|
show = ->
|
35
34
|
el = $('.history')
|
@@ -1,4 +1,4 @@
|
|
1
|
-
div.endpoints-component(
|
1
|
+
div.endpoints-component(data-endpoints="#{@endpoints.to_json}")
|
2
2
|
h4 Endpoints
|
3
3
|
div.endpoints
|
4
4
|
form.form-horizontal
|
@@ -6,9 +6,36 @@ div.endpoints-component( data-endpoints="#{@endpoints.to_json}")
|
|
6
6
|
label.control-label(for="selectEndpoint") Api Endpoint
|
7
7
|
div.controls
|
8
8
|
select.input-xxlarge(id='selectEndpoint')
|
9
|
-
|
10
|
-
|
11
|
-
label.control-label(for="inputParam") Param Name
|
9
|
+
div.control-group
|
10
|
+
label.control-label Parameters
|
12
11
|
div.controls
|
12
|
+
a.btn.create-parameter(href='#endpointsModal')
|
13
|
+
== "+"
|
14
|
+
|
15
|
+
div.controls.parameters
|
16
|
+
|
17
|
+
div.control-group.template
|
18
|
+
label.control-label(for="inputParam") Param Name
|
19
|
+
div.controls
|
20
|
+
div.input-prepend
|
21
|
+
span.add-on.remove-parameter
|
22
|
+
i.icon-remove.hide
|
13
23
|
input.input-xxlarge(id="inputParam" type="text")
|
14
24
|
|
25
|
+
div.modal.hide.fade#endpointsModal
|
26
|
+
div.modal-header
|
27
|
+
button.close(type='button' data-dismiss='modal' aria-hidden='true')
|
28
|
+
== "×"
|
29
|
+
h4 Custom Parameter
|
30
|
+
div.modal-body
|
31
|
+
form.form-horizontal
|
32
|
+
div.control-group
|
33
|
+
label.control-label(for='inputParameterFieldName') Value
|
34
|
+
div.controls
|
35
|
+
input.input-xlarge#inputParameterFieldName(type='text' placeholder='Parameter Name')
|
36
|
+
|
37
|
+
div.modal-footer
|
38
|
+
a.btn(href='#' data-dismiss='modal') Cancel
|
39
|
+
a.btn.btn-primary.add-parameter(href='#') Ok
|
40
|
+
|
41
|
+
|
@@ -10,7 +10,7 @@ div.row.headers
|
|
10
10
|
a(href='#' class='btn remove-http-header')
|
11
11
|
== "-"
|
12
12
|
|
13
|
-
div.modal.hide.fade
|
13
|
+
div.modal.hide.fade#httpHeadersModal
|
14
14
|
div.modal-header
|
15
15
|
button.close(type='button' data-dismiss='modal' aria-hidden='true')
|
16
16
|
== "×"
|
data/lib/apic/route_wrapper.rb
CHANGED
data/lib/apic/version.rb
CHANGED