apitest 0.1.9 → 0.2.0
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 +61 -4
- data/app/assets/javascripts/apitest/application.coffee +33 -7
- data/app/assets/stylesheets/apitest/application.scss +2 -0
- data/app/controllers/apitest/apitest_controller.rb +13 -10
- data/app/views/apitest/apitest/show.slim +28 -8
- data/app/views/layouts/apitest/application.slim +1 -1
- data/lib/apitest.rb +12 -12
- data/lib/apitest/error.rb +35 -0
- data/lib/apitest/module_error.rb +11 -0
- data/lib/apitest/reader.rb +14 -0
- data/lib/apitest/service_error.rb +41 -0
- data/lib/apitest/version.rb +1 -1
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 573eef6c4af633b41ade5cf70edc2abb18676367
|
4
|
+
data.tar.gz: d128c020fe260b55e550d90b2e4c59089db4e63d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1b50589b5877b6f1c96d8bfc00d86962a96e3954d7da75e5667a34eb514d7e872a49372f25607b146a5d2cf430837575148f02585fd0e0c1bd7efbc8a0dc265
|
7
|
+
data.tar.gz: fcb4faabaad7d12e54d5ffb56320f721b3214a5b92ae35da169b25dbb6a9ad35f986dca6bfb6ab171460ee130cbd77b4790174e9f4e04b65dc12d89602b0053a
|
data/README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# Apitest
|
2
|
-
- 通过在API controller
|
2
|
+
- 通过在API controller里配置常量,生成API文档
|
3
3
|
- 并附带一个测试界面,辅助API开发。
|
4
4
|
- 适用与API开发人员,客户端/前端开发人员交流验证文档。
|
5
|
-
-
|
5
|
+
- 目前无出参,需要提交后,得到。无法完全替代API文档
|
6
6
|
|
7
7
|
## Version
|
8
|
-
0.
|
8
|
+
0.2.0
|
9
9
|
|
10
10
|
## Installation
|
11
11
|
添加如下代码到 Gemfile:
|
@@ -137,14 +137,71 @@ Rails.application.routes.draw do
|
|
137
137
|
end
|
138
138
|
```
|
139
139
|
|
140
|
+
如果所有API有公共必填项,例如token,version,可如下配置
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
Rails.application.routes.draw do
|
144
|
+
|
145
|
+
apitest_for '/apitest' do
|
146
|
+
Apitest::public_required [ 'token' , 'version' ]
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
```
|
151
|
+
|
152
|
+
可以在指定APITEST中关闭公共必填项,比如登录API,可在具体方法的APIDOC中使用false设定
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
token:false
|
156
|
+
```
|
157
|
+
|
158
|
+
完整配置方法如下
|
159
|
+
```ruby
|
160
|
+
class Api::V1::LoginController < ApplicationController
|
161
|
+
|
162
|
+
APIDOC = {
|
163
|
+
type: '业务API' ,
|
164
|
+
group_name: '用户登录' ,
|
165
|
+
sort: 1 ,
|
166
|
+
apis: {
|
167
|
+
create: {
|
168
|
+
api_name: '登录' ,
|
169
|
+
path: '/api/v1/login' ,
|
170
|
+
method: 'post' ,
|
171
|
+
token: false , # 这里可关闭该API的token选项
|
172
|
+
params: {
|
173
|
+
mobile: {
|
174
|
+
required: true ,
|
175
|
+
} ,
|
176
|
+
password: {
|
177
|
+
required: true
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
}
|
183
|
+
def create
|
184
|
+
...
|
185
|
+
end
|
186
|
+
|
187
|
+
```
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
|
140
194
|
|
141
195
|
|
142
196
|
## TODO
|
143
197
|
- [x] 可自定义api目录
|
144
198
|
- [x] 可自定义theme
|
145
199
|
- [x] 可配置分类
|
146
|
-
- [
|
200
|
+
- [x] 可设定公共必填项,比如token、客户端类型、客户端版本号
|
201
|
+
- [x] 公共必填项可在指定API中关闭
|
202
|
+
- [x] 支持header token和params token
|
147
203
|
- [ ] ERROR类工具
|
204
|
+
- [ ] 出参example
|
148
205
|
- [ ] Apitest Example 网站
|
149
206
|
- [ ] 使用前端route
|
150
207
|
- [ ] 生成前端mock数据
|
@@ -5,6 +5,7 @@
|
|
5
5
|
#= require jquery3
|
6
6
|
#= require jquery_ujs
|
7
7
|
#= require turbolinks
|
8
|
+
#= require lodash
|
8
9
|
#= require bootstrap
|
9
10
|
#= require adminlte/adminlte
|
10
11
|
#= require vue
|
@@ -17,6 +18,7 @@ $(document).on "turbolinks:load" , ->
|
|
17
18
|
vm = new Vue
|
18
19
|
el : '#apitest_show'
|
19
20
|
data :
|
21
|
+
apitest_tab_show : 'api_test'
|
20
22
|
root_url : null
|
21
23
|
apis : null
|
22
24
|
ws : null
|
@@ -24,21 +26,39 @@ $(document).on "turbolinks:load" , ->
|
|
24
26
|
current_group : ''
|
25
27
|
current_api : ''
|
26
28
|
token : ''
|
27
|
-
|
29
|
+
token_type : ''
|
30
|
+
token_set : {}
|
31
|
+
token_get : []
|
32
|
+
headers : {}
|
28
33
|
mounted : ->
|
29
34
|
@apis = $('#data').data('apis')
|
30
|
-
@
|
35
|
+
@token_set = $('#data').data('token-set')
|
36
|
+
@token_get = $('#data').data('token-get')
|
37
|
+
@token_type = @token_set[0]
|
31
38
|
@output_area = $('#server-logs-output')
|
32
39
|
@root_url = $('#data').data('root-url')
|
33
40
|
@get_log()
|
41
|
+
@set_token(localStorage.apitest_token)
|
42
|
+
# @token_set()
|
34
43
|
|
35
44
|
methods :
|
36
|
-
|
45
|
+
set_token : (token) ->
|
46
|
+
@token = token
|
47
|
+
localStorage.apitest_token = token
|
48
|
+
@set_header_token() if @token_set[0] == 'header'
|
49
|
+
|
50
|
+
set_header_token : ->
|
51
|
+
@headers[@token_set[1]] = @token
|
52
|
+
|
53
|
+
fetch_token : (params) ->
|
54
|
+
token = eval 'params["' + @token_get.join('"]["') + '"]'
|
55
|
+
@set_token(token) if token
|
56
|
+
|
37
57
|
group_select : (name) ->
|
38
58
|
@current_group = name
|
39
59
|
@current_api = ''
|
40
60
|
|
41
|
-
api_select : (name
|
61
|
+
api_select : (name) ->
|
42
62
|
@current_api = name
|
43
63
|
|
44
64
|
api_submit : (e) ->
|
@@ -50,17 +70,23 @@ $(document).on "turbolinks:load" , ->
|
|
50
70
|
postData = {}
|
51
71
|
|
52
72
|
elm.find('.params').each ->
|
53
|
-
|
54
73
|
postData[$(this).attr('name')] = $(this).val() unless $(this).attr('name').indexOf(':id') >= 0
|
55
|
-
|
74
|
+
|
56
75
|
$.ajax
|
57
76
|
url : path
|
58
77
|
type : method
|
59
78
|
data : postData
|
79
|
+
headers : @headers
|
60
80
|
success : (data) =>
|
61
81
|
result_pre.jsonViewer(data)
|
82
|
+
@fetch_token(data)
|
62
83
|
error : (data) =>
|
63
|
-
|
84
|
+
try
|
85
|
+
result_pre.jsonViewer(JSON.parse(data.responseText))
|
86
|
+
catch e
|
87
|
+
result_pre.text(data.responseText)
|
88
|
+
|
89
|
+
|
64
90
|
|
65
91
|
clear_result : (e) ->
|
66
92
|
$(e.target).parents('.api').find('.result_pre').html('')
|
@@ -5,7 +5,10 @@ module Apitest
|
|
5
5
|
before_action :get_doc ,:root_url
|
6
6
|
def initialize
|
7
7
|
super
|
8
|
-
@apidocs
|
8
|
+
@apidocs = {}
|
9
|
+
@headers = Apitest::set_headers
|
10
|
+
@token_set = Apitest::token_setting[:set]
|
11
|
+
@token_get = Apitest::token_setting[:get]
|
9
12
|
end
|
10
13
|
def index
|
11
14
|
respond_to do |format|
|
@@ -29,24 +32,24 @@ module Apitest
|
|
29
32
|
def get_doc(path_root = nil)
|
30
33
|
path_root ||= "app/controllers/#{Apitest.api_dir}/"
|
31
34
|
Dir.glob("#{path_root}*").each do |path|
|
32
|
-
@apidocs[path.gsub("#{path_root}" , '')] = get_version_doc "#{path}
|
35
|
+
@apidocs[path.gsub("#{path_root}" , '')] = get_version_doc "#{path}" if File.directory?(path) && !path.gsub("#{path_root}" , '').blank?
|
33
36
|
end
|
34
37
|
end
|
35
38
|
|
36
|
-
def get_version_doc(path_root)
|
37
|
-
docs = Apitest::default_types.clone
|
39
|
+
def get_version_doc(path_root , docs = {})
|
40
|
+
docs = Apitest::default_types.clone if docs.blank?
|
38
41
|
Dir.glob("#{path_root}/*").each do |path|
|
39
42
|
if File.directory?(path)
|
40
|
-
docs = docs.merge get_version_doc(path)
|
43
|
+
docs = docs.merge get_version_doc(path , docs)
|
41
44
|
else
|
42
45
|
class_match = File.open(path).read.match(/class (.*) </)
|
43
46
|
controller_class = class_match[1].constantize if class_match && class_match[1]
|
44
47
|
if defined? controller_class::APIDOC
|
45
|
-
doc
|
46
|
-
doc[:sort]
|
48
|
+
doc = controller_class::APIDOC
|
49
|
+
doc[:sort] = 99 if doc[:sort].blank?
|
47
50
|
doc[:apis].each do |k,v|
|
48
51
|
d = doc[:apis][k]
|
49
|
-
d
|
52
|
+
d = public_required d unless Apitest::public_required.blank?
|
50
53
|
d[:params] = {':id' => { required: true }}.merge d[:params] if d[:path].include? ':id'
|
51
54
|
end
|
52
55
|
|
@@ -55,13 +58,13 @@ module Apitest
|
|
55
58
|
end
|
56
59
|
end
|
57
60
|
end
|
58
|
-
docs
|
61
|
+
return docs
|
59
62
|
end
|
60
63
|
def public_required(api)
|
61
64
|
Apitest::public_required.reverse.each do |need|
|
62
65
|
api[:params] = need.merge api[:params] if api[need.keys.first.to_sym] != false
|
63
66
|
end
|
64
|
-
api
|
67
|
+
return api
|
65
68
|
end
|
66
69
|
end
|
67
70
|
end
|
@@ -66,24 +66,44 @@ section.content
|
|
66
66
|
td 参数
|
67
67
|
td
|
68
68
|
table.table.table-hover.table-bordered
|
69
|
+
tr v-if="token_type == 'params'"
|
70
|
+
td
|
71
|
+
span style="color:red;width:10px;display:inline-block"
|
72
|
+
span *
|
73
|
+
span token
|
74
|
+
td
|
75
|
+
input.form-control.params name="token" :value="token"
|
69
76
|
tr v-for="(value , name , index) in api.params"
|
70
|
-
td.col-md-2
|
77
|
+
td.col-md-2
|
71
78
|
span style="color:red;width:10px;display:inline-block"
|
72
79
|
span v-if="value.required" *
|
73
80
|
span ="{{name}}"
|
74
|
-
td v-if="
|
75
|
-
|
76
|
-
|
77
|
-
|
81
|
+
td v-if="value.nested == true"
|
82
|
+
table.table.table-hover
|
83
|
+
tr v-for="(v , n , i) in value" v-if="n != 'nested'"
|
84
|
+
td.col-md-3
|
85
|
+
span style="color:red;width:10px;display:inline-block"
|
86
|
+
span v-if="v.required" *
|
87
|
+
span ="{{name}}[{{n}}]"
|
88
|
+
td
|
89
|
+
input.form-control.params :name="name + '[' + n + ']'"
|
90
|
+
span style="line-height:25px" = "{{v.text}}"
|
91
|
+
td v-else=""
|
78
92
|
input.form-control.params :name="name"
|
79
93
|
span style="line-height:25px" = "{{value.text}}"
|
94
|
+
/ td v-if="name == 'token'" v-bind:class="{'border-top-none': index == 0}"
|
95
|
+
/ input.form-control.params :name="name" :value="token"
|
96
|
+
/ span style="line-height:25px" = "{{value.text}}"
|
97
|
+
/ td v-if="name != 'token'" v-bind:class="{'border-top-none': index == 0}"
|
98
|
+
/ input.form-control.params :name="name"
|
99
|
+
/ span style="line-height:25px" = "{{value.text}}"
|
80
100
|
tr
|
81
101
|
td
|
82
102
|
td
|
83
103
|
button.btn.bg-olive.btn-flat @click="api_submit" 提交
|
84
|
-
button.btn.bg-orange.btn-flat style="margin-left:10px;margin-right:10px"
|
85
|
-
button.btn.bg-purple.btn-flat style="margin-left:10px;margin-right:10px"
|
86
|
-
button.btn.btn-warning.btn-flat style="margin-right:10px"
|
104
|
+
button.btn.bg-orange.btn-flat style="margin-left:10px;margin-right:10px" @click="clear_result" 清空结果
|
105
|
+
button.btn.bg-purple.btn-flat style="margin-left:10px;margin-right:10px" @click="show_server_log" 查看server log
|
106
|
+
button.btn.btn-warning.btn-flat style="margin-right:10px" @click="clear_log" 清空log
|
87
107
|
tr
|
88
108
|
td
|
89
109
|
td
|
@@ -31,6 +31,6 @@ html
|
|
31
31
|
=yield
|
32
32
|
footer.main-footer
|
33
33
|
-if params[:action] == 'show'
|
34
|
-
#data data-root-url="#{@root_url}" data-ws-url="ws://#{request.host}:9527" data-apis="#{@apidocs[params[:id]].to_json}" data-token="#{
|
34
|
+
#data data-root-url="#{@root_url}" data-ws-url="ws://#{request.host}:9527" data-apis="#{@apidocs[params[:id]].to_json}" data-headers="#{@headers.to_json}" data-token-set="#{@token_set.to_json}" data-token-get="#{@token_get.to_json}"
|
35
35
|
|
36
36
|
|
data/lib/apitest.rb
CHANGED
@@ -7,6 +7,7 @@ require "font-awesome-rails"
|
|
7
7
|
require "ionicons-rails"
|
8
8
|
require 'eventmachine'
|
9
9
|
require 'eventmachine-tail'
|
10
|
+
require 'lodash-rails'
|
10
11
|
require 'websocket-eventmachine-server'
|
11
12
|
|
12
13
|
module Apitest
|
@@ -14,6 +15,8 @@ module Apitest
|
|
14
15
|
@theme
|
15
16
|
@default_types
|
16
17
|
@public_required
|
18
|
+
@token_setting
|
19
|
+
|
17
20
|
class << self
|
18
21
|
def api_dir(dir = nil)
|
19
22
|
@api_dir = dir if dir
|
@@ -44,6 +47,15 @@ module Apitest
|
|
44
47
|
@public_required
|
45
48
|
end
|
46
49
|
|
50
|
+
def token_setting(setting = nil)
|
51
|
+
@token_setting = setting if setting
|
52
|
+
@token_setting
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_headers
|
56
|
+
@token_setting[:set] && @token_setting[:set][1] ? {@token_setting[:set][1] => ''} : {}
|
57
|
+
end
|
58
|
+
|
47
59
|
def start_server_log_listen
|
48
60
|
Process.detach(
|
49
61
|
fork do
|
@@ -68,18 +80,6 @@ module Apitest
|
|
68
80
|
)
|
69
81
|
end
|
70
82
|
end
|
71
|
-
|
72
|
-
class Reader < EventMachine::FileTail
|
73
|
-
def initialize(path, startpos=-1, &block)
|
74
|
-
super(path, startpos)
|
75
|
-
@buffer = BufferedTokenizer.new
|
76
|
-
@block = block
|
77
|
-
end
|
78
|
-
|
79
|
-
def receive_data(data)
|
80
|
-
@buffer.extract(data).each { |line| @block.call(line) }
|
81
|
-
end
|
82
|
-
end
|
83
83
|
end
|
84
84
|
|
85
85
|
module ActionDispatch::Routing
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Apitest
|
2
|
+
module Error
|
3
|
+
def error(error_code = nil , data = nil,message = nil)
|
4
|
+
hash = {
|
5
|
+
status: 'error' ,
|
6
|
+
error_code: error_code ,
|
7
|
+
message: message.nil? ? self::ERROR[error_code] : message ,
|
8
|
+
data: data ,
|
9
|
+
}
|
10
|
+
raise "#{self.to_s}::Error".constantize.new hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def success(message = nil , data = nil)
|
14
|
+
hash = {}
|
15
|
+
hash[:status] = 'ok'
|
16
|
+
if message.is_a? Hash
|
17
|
+
hash[:message] = message[:message] ? message[:message] : ''
|
18
|
+
hash[:data] = message[:data] ? message[:data] : message
|
19
|
+
else
|
20
|
+
hash[:message] = message ? message : ''
|
21
|
+
hash[:data] = data ? data : {}
|
22
|
+
end
|
23
|
+
return hash
|
24
|
+
end
|
25
|
+
|
26
|
+
class Error < StandardError
|
27
|
+
def error
|
28
|
+
eval(message)
|
29
|
+
end
|
30
|
+
def error_code
|
31
|
+
error[:error_code]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Apitest
|
2
|
+
class Reader < EventMachine::FileTail
|
3
|
+
def initialize(path, startpos=-1, &block)
|
4
|
+
super(path, startpos)
|
5
|
+
@buffer = BufferedTokenizer.new
|
6
|
+
@block = block
|
7
|
+
end
|
8
|
+
|
9
|
+
def receive_data(data)
|
10
|
+
@buffer.extract(data).each { |line| @block.call(line) }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Apitest
|
2
|
+
module ServiceError
|
3
|
+
# include Apitest::Error
|
4
|
+
def self.include(klass)
|
5
|
+
klass.class_eval do
|
6
|
+
include ServiceError
|
7
|
+
extend ServiceError
|
8
|
+
end
|
9
|
+
end
|
10
|
+
def self.error(error_code = nil , data = nil,message = nil)
|
11
|
+
hash = {
|
12
|
+
status: 'error' ,
|
13
|
+
error_code: error_code ,
|
14
|
+
message: message.nil? ? self::ERROR[error_code] : message ,
|
15
|
+
data: data ,
|
16
|
+
}
|
17
|
+
raise "#{self.to_s}::Error".constantize.new hash
|
18
|
+
end
|
19
|
+
|
20
|
+
def success(message = nil , data = nil)
|
21
|
+
hash = {}
|
22
|
+
hash[:status] = 'ok'
|
23
|
+
if message.is_a? Hash
|
24
|
+
hash[:message] = message[:message] ? message[:message] : ''
|
25
|
+
hash[:data] = message[:data] ? message[:data] : message
|
26
|
+
else
|
27
|
+
hash[:message] = message ? message : ''
|
28
|
+
hash[:data] = data ? data : {}
|
29
|
+
end
|
30
|
+
return hash
|
31
|
+
end
|
32
|
+
class Error < StandardError
|
33
|
+
def error
|
34
|
+
eval(message)
|
35
|
+
end
|
36
|
+
def error_code
|
37
|
+
error[:error_code]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/apitest/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apitest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyuubi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: lodash-rails
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: eventmachine-tail
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -179,6 +193,10 @@ files:
|
|
179
193
|
- config/routes.rb
|
180
194
|
- lib/apitest.rb
|
181
195
|
- lib/apitest/engine.rb
|
196
|
+
- lib/apitest/error.rb
|
197
|
+
- lib/apitest/module_error.rb
|
198
|
+
- lib/apitest/reader.rb
|
199
|
+
- lib/apitest/service_error.rb
|
182
200
|
- lib/apitest/version.rb
|
183
201
|
- lib/tasks/apitest_tasks.rake
|
184
202
|
homepage: https://github.com/kyuubi9/apitest
|