schemaless_rest_api 0.3.4 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c6884db983603d3fe99853d2daf2448c5a112535d427c4dcf93085c03d0d572
4
- data.tar.gz: 233cf6a115128268144a612ff02e5de53c32b4f1dc0cb3e46a53f15ebc776e9d
3
+ metadata.gz: 3ab21f348c0122fbfa54365f8f1ed20c80bcf2f110e522bf8e782315414419e9
4
+ data.tar.gz: a5ac30ed8f1efe06561474fed073f9e270788b74502e85dfcf8e61b11131a21d
5
5
  SHA512:
6
- metadata.gz: 6fddf98f70498d9efee708f86ba28a3ddc4da8b53c029886c964ba8be2078d8bc459d025c50236bb11c9992a8a4ef5edd62d3a05491d8686ac481c2d6a61238a
7
- data.tar.gz: ad73ffe9c66723853b0e0a9dc6ecaeb30371b7b12ceb33267715de10dcac052bb3d2107ad3fd4d93bff978239077d2a9434e526b8a32dc550676145b4d0b7db9
6
+ metadata.gz: a63738895a1ae2c01ecf3a0d81d70978231f3c92493a13f9a72cb111d1b41a6f90fde28f9dddd2de662c9fe7d3e270bdd1f7462870c02516e1a042957f950169
7
+ data.tar.gz: aa2e4411f2aace139b6b9d40edb672e32513d6dcc07a4e6359b2338191dd3bf583f433d9d239f3d7263fde38eb169990290d73e31aa2d2df51b9e7074f55480e
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "sinatra"
4
- require "docdsl"
5
4
  require "puma"
6
5
  require "route_downcaser"
6
+ require_relative "server_utils"
7
7
 
8
8
  # Server with endpoints generated based on Entities with CRUD operations for them
9
9
  class RestServer < Sinatra::Base
@@ -11,17 +11,39 @@ class RestServer < Sinatra::Base
11
11
  enable :logging if ENV["debug"] == "true"
12
12
  set :bind, "0.0.0.0"
13
13
  use RouteDowncaser::DowncaseRouteMiddleware
14
+ helpers ServerUtils
14
15
 
15
- register Sinatra::DocDsl
16
+ before do
17
+ @request_id = SecureRandom.uuid
18
+ headers["X-Request-Id"] = @request_id
19
+ headers["Access-Control-Allow-Origin"] = "*"
20
+ log({ msg: "Request"}) if (request.fullpath != "")
21
+ end
16
22
 
17
- page do
18
- title "Schmaless REST API"
19
- header "REST API using models #{Entities.models.keys}"
20
- introduction "REST APIs allowing CRUD on:
21
- #{Entities.models.keys.join("\n")}"
23
+ after do
24
+ log({ msg: "Response", status: response.status }) if (request.fullpath != "")
22
25
  end
23
26
 
24
- doc_endpoint "/docs"
27
+ SWAGGER_FILES = %w[index.css swagger.html swagger-initializer.js swagger-ui-bundle.js swagger-ui-standalone-preset.js swagger-ui.css]
28
+
29
+ SWAGGER_FILES.each do |filename|
30
+ get "/#{filename.gsub(".html", "")}" do
31
+ if filename.end_with? '.json'
32
+ content_type :json
33
+ elsif filename.end_with? '.css'
34
+ content_type :css
35
+ elsif filename.end_with? '.js'
36
+ content_type :js
37
+ end
38
+
39
+ File.read("./lib/schemaless_rest_api/swagger/#{filename}")
40
+ end
41
+ end
42
+
43
+ get "/swagger.json" do
44
+ content_type :json
45
+ SwaggerBuilder.build_swagger_for(Entities.models, request.host_with_port)
46
+ end
25
47
 
26
48
  def has_id?(model, id)
27
49
  Entities.models[model].key?(id)
@@ -31,28 +53,20 @@ class RestServer < Sinatra::Base
31
53
  [404, JSON.generate({ error: "'#{id}' not found" })]
32
54
  end
33
55
 
34
- documentation "Get summary" do
35
- response "Basic basic summary of API"
36
- end
37
56
  get "/" do
38
57
  summary = { models: Entities.models.keys.to_s,
39
- docs_url: "<a href=/docs>/docs</a>" }
58
+ docs_url: "<a href=/swagger>Swagger docs</a>" }
40
59
  summary[:db] = MongoClient.client.summary.to_s if ENV["mongodb"]
41
60
  JSON.generate(summary)
42
- rescue Exception => e
61
+ rescue StandardError => e
43
62
  [500, e.message]
44
63
  end
45
64
 
46
65
  Entities.models.each_key do |model|
47
- documentation "Create instance of #{model}" do
48
- payload "Whatever JSON you want. Needs to be valid JSON"
49
- response "Id of created #{model}"
50
- status 201
51
- end
52
66
  post "/#{model.downcase}" do
53
- response["Access-Control-Allow-Origin"] = "*"
54
- SchemalessRestApi.logger.info "POST #{request.fullpath}"
55
- data = JSON.parse(request.body.read)
67
+ request_body = request.body.read
68
+ data = {}
69
+ data = JSON.parse(request_body) unless request_body.empty?
56
70
  id = ""
57
71
  if data["id"]
58
72
  id = data["id"].to_s
@@ -65,24 +79,17 @@ class RestServer < Sinatra::Base
65
79
  else
66
80
  Entities.models[model][id] = data
67
81
  end
82
+ log "Created #{id}"
68
83
  [201, JSON.generate({ id: id })]
69
84
  end
70
85
 
71
86
  options "/#{model.downcase}" do
72
87
  response["Allow"] = "*"
73
- response["Access-Control-Allow-Origin"] = "*"
74
88
  response["Access-Control-Allow-Methods"] = "*"
75
89
  response["Access-Control-Allow-Headers"] = "*"
76
90
  end
77
91
 
78
- documentation "Retrieve all instances of #{model} or filtered by query param" do
79
- response "Data in #{model}"
80
- query_param :key_to_search_in_data, "Value of key"
81
- status 200
82
- end
83
92
  get "/#{model.downcase}" do
84
- response["Access-Control-Allow-Origin"] = "*"
85
- SchemalessRestApi.logger.info "GET #{request.fullpath}"
86
93
  if ENV["mongodb"]
87
94
  if params == {}
88
95
  JSON.generate(MongoClient.get_all(model))
@@ -97,18 +104,11 @@ class RestServer < Sinatra::Base
97
104
  end
98
105
  return JSON.generate(matching_values)
99
106
  end
100
- rescue Exception => e
107
+ rescue StandardError => e
101
108
  [404, "Nothing found using #{params}. Only first param considered. #{e.message}"]
102
109
  end
103
110
 
104
- documentation "Retrieve specific instance of #{model} by id" do
105
- response "Data in #{model}"
106
- status 200
107
- status 404
108
- end
109
111
  get "/#{model.downcase}/:id" do |id|
110
- response["Access-Control-Allow-Origin"] = "*"
111
- SchemalessRestApi.logger.info "GET #{request.fullpath}"
112
112
  if ENV["mongodb"]
113
113
  results = MongoClient.find(model, id)
114
114
  return not_have(id) unless results.first
@@ -128,15 +128,7 @@ class RestServer < Sinatra::Base
128
128
  response["Access-Control-Allow-Headers"] = "*"
129
129
  end
130
130
 
131
- documentation "Update id of #{model} to be provided data" do
132
- payload "Whatever JSON you want updated to be. Needs to be valid JSON"
133
- response "Data in #{model}"
134
- status 204
135
- status 404
136
- end
137
131
  put "/#{model.downcase}/:id" do |id|
138
- response["Access-Control-Allow-Origin"] = "*"
139
- SchemalessRestApi.logger.info "PUT #{request.fullpath}"
140
132
  data = JSON.parse(request.body.read)
141
133
  if ENV["mongodb"]
142
134
  results = MongoClient.find(model, id)
@@ -151,13 +143,7 @@ class RestServer < Sinatra::Base
151
143
  204
152
144
  end
153
145
 
154
- documentation "Update id of #{model} to be deleted" do
155
- response "Empty"
156
- status 204
157
- end
158
146
  delete "/#{model.downcase}/:id" do |id|
159
- response["Access-Control-Allow-Origin"] = "*"
160
- SchemalessRestApi.logger.info "DEL #{request.fullpath}"
161
147
  if ENV["mongodb"]
162
148
  results = MongoClient.find(model, id)
163
149
  return not_have(id) unless results.first
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # typed: true
4
+
5
+ module ServerUtils
6
+ def log(messages)
7
+ if SchemalessRestApi.log_type == :ougai
8
+ log_msg = {
9
+ method: request.request_method,
10
+ path: request.fullpath,
11
+ correlationId: @request_id
12
+ }
13
+ messages.each do |key, value|
14
+ log_msg[key] = value
15
+ end
16
+ SchemalessRestApi.logger.info(log_msg)
17
+ else
18
+ message = messages.values.join(", ")
19
+ SchemalessRestApi.logger.info "#{message}, #{request.request_method} #{request.fullpath}, CorrelationId: #{@request_id}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ html {
2
+ box-sizing: border-box;
3
+ overflow: -moz-scrollbars-vertical;
4
+ overflow-y: scroll;
5
+ }
6
+
7
+ *,
8
+ *:before,
9
+ *:after {
10
+ box-sizing: inherit;
11
+ }
12
+
13
+ body {
14
+ margin: 0;
15
+ background: #fafafa;
16
+ }
@@ -0,0 +1,19 @@
1
+ window.onload = function() {
2
+ //<editor-fold desc="Changeable Configuration Block">
3
+
4
+ window.ui = SwaggerUIBundle({
5
+ url: "./swagger.json",
6
+ dom_id: '#swagger-ui',
7
+ deepLinking: true,
8
+ presets: [
9
+ SwaggerUIBundle.presets.apis,
10
+ SwaggerUIStandalonePreset
11
+ ],
12
+ plugins: [
13
+ SwaggerUIBundle.plugins.DownloadUrl
14
+ ],
15
+ layout: "StandaloneLayout"
16
+ });
17
+
18
+ //</editor-fold>
19
+ };