api_explorer 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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
+ });