apic 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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