api_explorer 0.0.6 → 0.0.7

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.
data/README.md CHANGED
@@ -14,33 +14,56 @@ API Explorer is a tool that reads a specification and creates a console where de
14
14
  - Supports HTTP basic authentication and HMAC-SHA1 hash authentication.
15
15
 
16
16
  ## Precondition
17
- Given that it makes a request to the same server, it requires a multi-threaded server. On this example we will use 'thin' but it should work with 'unicorn' as well.
17
+ Given that it makes a request to the same server, it requires a multi-threaded server. On this example we will use 'thin' and 'unicorn'.
18
18
 
19
19
 
20
- ## Configure thin server on threaded mode (it should work with unicorn also)
20
+ ## Configure thin server on threaded mode
21
21
 
22
22
  Add thin to the Gemfile.
23
23
  ```
24
24
  gem 'thin', '~> 1.6.1'
25
25
  ```
26
26
 
27
+ Set thread safe mode in development.rb (or the right environment)
28
+
29
+ ```
30
+ config.thread_safe!
31
+ ```
32
+
27
33
  Bundle install
28
34
  ```
29
35
  bundle install
30
36
  ```
31
37
 
38
+ Test the server by running it with:
39
+ ```
40
+ thin start --threaded
41
+ ```
32
42
 
33
- Set thread safe mode in development.rb (or the right environment)
43
+ ## Alternative - Configure unicorn server
34
44
 
45
+ Add unicorn to the Gemfile.
35
46
  ```
36
- config.thread_safe!
47
+ gem "unicorn", "~> 4.7.0"
48
+ ```
49
+
50
+ Add the file 'unicorn.conf' to config/ with the following content:
51
+
52
+ ```
53
+ worker_processes 3
54
+ ```
55
+
56
+ Bundle install
57
+ ```
58
+ bundle install
37
59
  ```
38
60
 
39
61
  Test the server by running it with:
40
62
  ```
41
- thin start --threaded
63
+ unicorn_rails -c config/unicorn.conf
42
64
  ```
43
65
 
66
+
44
67
  ## Install the gem
45
68
 
46
69
  Add the gem to the Gemfile.
@@ -52,20 +75,23 @@ gem 'api_explorer'
52
75
  Create a file named ws_specification.json (or any name you desire) and place it on /lib. An example can be:
53
76
 
54
77
  ```
55
- { "methods": [
56
- { "name": "Users index",
57
- "url": "v1/users",
58
- "description": "The index of users",
59
- "method": "GET",
60
- "parameters": [{"name": "API_TOKEN"}]
61
- },
62
- { "name": "User login",
63
- "url": "v1/users/login",
64
- "description": "Users login",
65
- "method": "POST",
66
- "parameters": [{"name": "API_TOKEN"}, {"name": "email"}, {"name": "password"}]
67
- }
68
- ]
78
+ {
79
+ "methods": [
80
+ {
81
+ "name": "Users index",
82
+ "url": "v1/users",
83
+ "description": "The index of users",
84
+ "method": "GET",
85
+ "parameters": [{"name": "API_TOKEN"}]
86
+ },
87
+ {
88
+ "name": "User login",
89
+ "url": "v1/users/login",
90
+ "description": "Users login",
91
+ "method": "POST",
92
+ "parameters": [{"name": "API_TOKEN"}, {"name": "email"}, {"name": "password"}]
93
+ }
94
+ ]
69
95
  }
70
96
  ```
71
97
 
@@ -73,7 +99,7 @@ Create an initializer in /config/initializers/api_explorer.rb with the following
73
99
 
74
100
  ```
75
101
  ApiExplorer::use_file = true
76
- ApiExplorer::json_path = lib/ws_specification.json
102
+ ApiExplorer::json_path = 'lib/ws_specification.json'
77
103
  ```
78
104
 
79
105
  Another option can be:
@@ -98,16 +124,22 @@ That's it. Its ready to go.
98
124
 
99
125
  ## Run
100
126
 
101
- Start thin
127
+ Start thin (or unicorn)
102
128
 
103
129
  ```
104
130
  thin start --threaded
105
131
  ```
106
132
 
133
+ or
134
+
135
+ ```
136
+ unicorn_rails -c config/unicorn.conf
137
+ ```
138
+
107
139
  And go to
108
140
 
109
141
  ```
110
- http://localhost:3000/api_explorer
142
+ http://<base_path>/api_explorer
111
143
  ```
112
144
 
113
145
  ## Contribute
@@ -119,7 +151,6 @@ http://localhost:3000/api_explorer
119
151
  ## Next improvements
120
152
 
121
153
  - Better error handling
122
- - Test with unicorn
123
154
  - Test with Rails 4
124
155
  - More authentication methods
125
156
  - Support absolute URLs to test 3rd party APIs.
@@ -1,197 +1,218 @@
1
- // Place all the behaviors and hooks related to the matching controller here.
2
- // All this logic will automatically be available in application.js.
3
- $(document).ready(function(){
4
- var container = $("body.api_explorer")
5
- var parameters_container = $("#parameters_container", container);
6
- var headers_container = $("#headers_container", container);
7
- var authentication_container = $("#authentication_container", container);
8
-
9
- var method_description = $("#method_description", container);
10
- var select_method = $("#api_methods", container);
11
- var response_placeholder = $("#response_placeholder", container);
12
- var tab_history = $("#response_placeholder").find(".tab_history");
13
- var history_menu = tab_history.find(".history_menu");
14
- var authentication_method = $("#authentication_type", container);
15
-
16
- // Change selected method
17
- select_method.change(function(){
18
- $("#graph_path", container).val($(this).val());
19
-
20
-
21
-
22
- var position = $(this)[0].selectedIndex;
23
-
24
- // if a method is selected
25
- if (position > 0)
26
- $.get("api_explorer/method", {position: position}).done(function(data){
27
- parameters_container.html(data.parameters_html);
28
- method_description.html(data.description);
29
-
30
- parameters_container.show();
31
- headers_container.show();
32
- method_description.show();
33
- authentication_container.show();
34
- });
35
- else
36
- {
37
- // Clean everything
38
- parameters_container.html('');
39
- method_description.html('');
40
- parameters_container.hide();
41
- headers_container.hide();
42
- method_description.hide();
43
- authentication_container.hide();
44
- }
45
- })
46
-
47
- authentication_method.change(function(){
48
- if ($(this).val() != ''){
49
- $('.auth_wrapper', authentication_container).hide();
50
- $('input[type="text"]',authentication_container).val('');
51
- $('#' + $(this).val() ,authentication_container).show();
52
- }
53
- else{
54
- $('.auth_wrapper', authentication_container).hide();
55
- $('input[type="text"]',authentication_container).val('');
56
- }
57
- });
58
-
59
- // Clear parameters button
60
- $(container).on('click', '#clear_parameters', function(){
61
- $("input", parameters_container).val('')
62
- })
63
-
64
- $('#clear_headers', container).click(function(){
65
- $("input", headers_container).val('');
66
- $(".deletable", headers_container).remove();
67
-
68
- })
69
-
70
- $('#clear_authentication', container).click(function(){
71
- $("input", authentication_container).val('');
72
- $("select", authentication_container).val('');
73
- $(".auth_wrapper", authentication_container).hide();
74
- })
75
-
76
- // Add headers
77
- headers_container.on('focus', ".parameter_input",function(){
78
- header_line = $(this).parents(".headers_line");
79
- if (header_line.is(':last-child'))
80
- {
81
-
82
- header_line.parent().append('<div class="headers_line"><div class="header_field"><input type="text" placeholder="Header name" name="header[name][]" class="parameter_input" /></div><div class="header_field"><input type="text" placeholder="Value" name="header[value][]" class="parameter_input" /></div></div>');
83
-
84
- // Add delete button
85
- header_line.append('<div class="delete_btn"></div>');
86
- header_line.addClass('deletable');
87
- }
88
- });
89
-
90
- headers_container.on('click', ".delete_btn",function(){
91
- $(this).parents('.headers_line').remove();
92
- });
93
-
94
- var minimize_container = function(self, min_container)
95
- {
96
- min_container.addClass('minimized');
97
- self.removeClass('minimize');
98
- self.addClass('maximize');
99
- self.attr('title','Maximize');
100
- }
101
-
102
- var maximize_container = function(self, max_container)
103
- {
104
- max_container.removeClass('minimized');
105
- self.removeClass('maximize');
106
- self.addClass('minimize');
107
- self.attr('title','Minimize');
108
- }
109
-
110
- headers_container.on('click', ".minimize",function(){
111
- minimize_container($(this), headers_container);
112
- });
113
-
114
- headers_container.on('click', ".maximize",function(){
115
- maximize_container($(this),headers_container);
116
- });
117
-
118
- parameters_container.on('click', ".minimize",function(){
119
- minimize_container($(this),parameters_container);
120
- });
121
-
122
- parameters_container.on('click', ".maximize",function(){
123
- maximize_container($(this), parameters_container);
124
- });
125
-
126
- authentication_container.on('click', ".minimize",function(){
127
- minimize_container($(this),authentication_container);
128
- });
129
-
130
- authentication_container.on('click', ".maximize",function(){
131
- maximize_container($(this), authentication_container);
132
- });
133
-
134
- history_menu.on('click', '.history_item', function(){
135
- $(".history_item", history_menu).removeClass('active');
136
- $(this).addClass('active');
137
- var history_content = tab_history.find(".history_content");
138
- var timestamp = $(this).data('timestamp');
139
- $(".content_wrapper", history_content).hide();
140
-
141
- $("."+ timestamp, history_content).show();
142
- });
143
-
144
- //make request
145
- $("#api_explorer_submit", container).click(function(e){
146
- e.preventDefault();
147
-
148
- var data = $("input", parameters_container).serializeArray().concat($("input", headers_container).serializeArray()).concat($("input, select", authentication_container).serializeArray());
149
-
150
- data.push({name: 'url', value: $("#graph_path", container).val()});
151
- data.push({name: 'method', value: select_method.find('option:selected').data('method')});
152
-
153
- $.post("api_explorer/execute", data, function(response){
154
- headers_container.addClass('minimized');
155
- parameters_container.addClass('minimized');
156
- authentication_container.addClass('minimized');
157
-
158
- headers_container.find('.minimize').removeClass('minimize').addClass('maximize');
159
- parameters_container.find('.minimize').removeClass('minimize').addClass('maximize');
160
- authentication_container.find('.minimize').removeClass('minimize').addClass('maximize');
161
-
162
- response_placeholder.find(".tab_response").find(".content").html(response.response_html);
163
- response_placeholder.find(".tab_request").find(".content").html(response.request_html);
164
-
165
- var history_content = tab_history.find(".history_content");
166
-
167
- $(".history_item", history_menu).removeClass('active');
168
- // If I have more than 9 elements, remove the last one
169
- if ($(".history_item", history_menu).length > 9)
170
- {
171
- $(".history_item", history_menu).last().remove();
172
- $(".content_wrapper", history_content).last().remove();
173
- }
174
-
175
- history_content.prepend(response.history_html);
176
- history_menu.prepend("<div class='history_item active' data-timestamp='"+ response.timestamp + "'>" + response.http_method + " to "+response.request_url +" ( at " + response.date +" ) " + "</div>");
177
-
178
- $(".content_wrapper", history_content).hide();
179
- $("." + response.timestamp, history_content).show();
180
-
181
-
182
- response_placeholder.slideDown();
183
- response_placeholder.find(".tab_response").find('input[type="radio"]').prop("checked", true);
184
-
185
- $('html, body').animate({
186
- scrollTop: response_placeholder.offset().top + 50
187
- }, 500);
188
-
189
-
190
- console.log(response);
191
-
192
- }).error(function() {
193
- alert('There was an error executing the webservice. Please check if you are using a multithreaded server');
194
- });
195
-
196
- });
197
- })
1
+
2
+ $(function () {
3
+
4
+ // Match all containers and placeholders
5
+ var container = $("body.api_explorer"); // In order to avoid naming colisions, all the selectors are within this context
6
+ var parameters_container = $("#parameters_container", container);
7
+ var headers_container = $("#headers_container", container);
8
+ var authentication_container = $("#authentication_container", container);
9
+ var method_description = $("#method_description", container);
10
+ var select_method = $("#api_methods", container);
11
+ var response_placeholder = $("#response_placeholder", container);
12
+ var tab_history = $("#response_placeholder").find(".tab_history");
13
+ var history_menu = tab_history.find(".history_menu");
14
+ var authentication_method = $("#authentication_type", container);
15
+
16
+ // Change selected method
17
+ select_method.change(function(){
18
+
19
+ $("#graph_path", container).val($(this).val());
20
+
21
+ // Selected position
22
+ var position = $(this)[0].selectedIndex;
23
+
24
+ // if a method is selected
25
+ if (position > 0)
26
+ {
27
+ $.get("api_explorer/method", {position: position}).done(function(data){
28
+ parameters_container.html(data.parameters_html);
29
+ method_description.html(data.description);
30
+
31
+ parameters_container.show();
32
+ headers_container.show();
33
+ method_description.show();
34
+ authentication_container.show();
35
+ });
36
+ }
37
+ else
38
+ {
39
+ // Clean everything
40
+ parameters_container.html('');
41
+ method_description.html('');
42
+ parameters_container.hide();
43
+ headers_container.hide();
44
+ method_description.hide();
45
+ authentication_container.hide();
46
+ }
47
+ });
48
+
49
+ // Change authentication method
50
+ authentication_method.change(function(){
51
+ if ($(this).val() !== '')
52
+ {
53
+ $('.auth_wrapper', authentication_container).hide();
54
+ $('input[type="text"]',authentication_container).val('');
55
+ $('#' + $(this).val() ,authentication_container).show();
56
+ }
57
+ else{
58
+ // If 'none' is selected, hide authentication option containers
59
+ $('.auth_wrapper', authentication_container).hide();
60
+ $('input[type="text"]',authentication_container).val('');
61
+ }
62
+ });
63
+
64
+ // Clear parameters button
65
+ $(container).on('click', '#clear_parameters', function(){
66
+ $("input", parameters_container).val('');
67
+ });
68
+
69
+ // Clear the headers
70
+ $('#clear_headers', container).click(function(){
71
+ $("input", headers_container).val('');
72
+ $(".deletable", headers_container).remove();
73
+
74
+ });
75
+
76
+ // Clear authentication section
77
+ $('#clear_authentication', container).click(function(){
78
+ $("input", authentication_container).val('');
79
+ $("select", authentication_container).val('');
80
+ $(".auth_wrapper", authentication_container).hide();
81
+ });
82
+
83
+ // Add headers when focusing on headers input
84
+ headers_container.on('focus', ".parameter_input",function(){
85
+ header_line = $(this).parents(".headers_line");
86
+ if (header_line.is(':last-child'))
87
+ {
88
+
89
+ header_line.parent().append('<div class="headers_line"><div class="header_field"><input type="text" placeholder="Header name" name="header[name][]" class="parameter_input" /></div><div class="header_field"><input type="text" placeholder="Value" name="header[value][]" class="parameter_input" /></div></div>');
90
+
91
+ // Add delete button
92
+ header_line.append('<div class="delete_btn"></div>');
93
+ header_line.addClass('deletable');
94
+ }
95
+ });
96
+
97
+ // Delete header
98
+ headers_container.on('click', ".delete_btn",function(){
99
+ $(this).parents('.headers_line').remove();
100
+ });
101
+
102
+ // Funciton used to minimize sections
103
+ var minimize_container = function(self, min_container)
104
+ {
105
+ min_container.addClass('minimized');
106
+ self.removeClass('minimize');
107
+ self.addClass('maximize');
108
+ self.attr('title','Maximize');
109
+ };
110
+
111
+ // Function used to maximize sections
112
+ var maximize_container = function(self, max_container)
113
+ {
114
+ max_container.removeClass('minimized');
115
+ self.removeClass('maximize');
116
+ self.addClass('minimize');
117
+ self.attr('title','Minimize');
118
+ };
119
+
120
+ // Headers container minimize function
121
+ headers_container.on('click', ".minimize",function(){
122
+ minimize_container($(this), headers_container);
123
+ });
124
+
125
+ // Headers container maximize function
126
+ headers_container.on('click', ".maximize",function(){
127
+ maximize_container($(this),headers_container);
128
+ });
129
+
130
+ // Parameters container minimize function
131
+ parameters_container.on('click', ".minimize",function(){
132
+ minimize_container($(this),parameters_container);
133
+ });
134
+
135
+ // Parameters container maximize function
136
+ parameters_container.on('click', ".maximize",function(){
137
+ maximize_container($(this), parameters_container);
138
+ });
139
+
140
+ // Authentication container minimize function
141
+ authentication_container.on('click', ".minimize",function(){
142
+ minimize_container($(this),authentication_container);
143
+ });
144
+
145
+ // Authentication container maximize function
146
+ authentication_container.on('click', ".maximize",function(){
147
+ maximize_container($(this), authentication_container);
148
+ });
149
+
150
+ // History item selected
151
+ history_menu.on('click', '.history_item', function(){
152
+ $(".history_item", history_menu).removeClass('active');
153
+ $(this).addClass('active');
154
+ var history_content = tab_history.find(".history_content");
155
+ var timestamp = $(this).data('timestamp');
156
+ $(".content_wrapper", history_content).hide();
157
+
158
+ $("."+ timestamp, history_content).show();
159
+ });
160
+
161
+ // Make request
162
+ $("#api_explorer_submit", container).click(function(e) {
163
+ e.preventDefault();
164
+
165
+ // Build array of parameters
166
+ var data = $("input", parameters_container).serializeArray().concat($("input", headers_container).serializeArray()).concat($("input, select", authentication_container).serializeArray());
167
+ data.push({name: 'url', value: $("#graph_path", container).val()});
168
+ data.push({name: 'method', value: select_method.find('option:selected').data('method')});
169
+
170
+ // Send the information to the server
171
+ $.post("api_explorer/execute", data, function(response){
172
+ // Response returned, minimize headers, parameters and authentication
173
+ headers_container.addClass('minimized');
174
+ parameters_container.addClass('minimized');
175
+ authentication_container.addClass('minimized');
176
+
177
+ // Change minimize icon
178
+ headers_container.find('.minimize').removeClass('minimize').addClass('maximize');
179
+ parameters_container.find('.minimize').removeClass('minimize').addClass('maximize');
180
+ authentication_container.find('.minimize').removeClass('minimize').addClass('maximize');
181
+
182
+ // Set the html of the request/response
183
+ response_placeholder.find(".tab_response").find(".content").html(response.response_html);
184
+ response_placeholder.find(".tab_request").find(".content").html(response.request_html);
185
+
186
+ // Set History
187
+ var history_content = tab_history.find(".history_content");
188
+ $(".history_item", history_menu).removeClass('active');
189
+
190
+ // If I have more than 9 elements, remove the last one
191
+ if ($(".history_item", history_menu).length > 9)
192
+ {
193
+ $(".history_item", history_menu).last().remove();
194
+ $(".content_wrapper", history_content).last().remove();
195
+ }
196
+ history_content.prepend(response.history_html);
197
+ history_menu.prepend("<div class='history_item active' data-timestamp='"+ response.timestamp + "'>" + response.http_method + " to "+response.request_url +" ( at " + response.date +" ) " + "</div>");
198
+
199
+ // Select the current element in History
200
+ $(".content_wrapper", history_content).hide();
201
+ $("." + response.timestamp, history_content).show();
202
+
203
+ // Slide down the response placeholder and check the response tab as checked
204
+ response_placeholder.slideDown();
205
+ response_placeholder.find(".tab_response").find('input[type="radio"]').prop("checked", true);
206
+
207
+ // Scroll to response position
208
+ $('html, body').animate({
209
+ scrollTop: response_placeholder.offset().top + 50
210
+ }, 500);
211
+
212
+
213
+ }).error(function() {
214
+ alert('There was an error executing the webservice. Please check if you are using a multithreaded server');
215
+ });
216
+
217
+ });
218
+ });