# frozen_string_literal: true require "sinatra" require "puma" require "route_downcaser" # Server with endpoints generated based on Entities with CRUD operations for them class RestServer < Sinatra::Base set :server, :puma enable :logging if ENV["debug"] == "true" set :bind, "0.0.0.0" use RouteDowncaser::DowncaseRouteMiddleware SWAGGER_FILES = %w[index.css swagger.html swagger-initializer.js swagger-ui-bundle.js swagger-ui-standalone-preset.js swagger-ui.css] SWAGGER_FILES.each do |filename| get "/#{filename.gsub(".html", "")}" do response["Access-Control-Allow-Origin"] = "*" if filename.end_with? '.json' content_type :json elsif filename.end_with? '.css' content_type :css elsif filename.end_with? '.js' content_type :js end File.read("./lib/schemaless_rest_api/swagger/#{filename}") end end get "/swagger.json" do response["Access-Control-Allow-Origin"] = "*" content_type :json SwaggerBuilder.build_swagger_for(Entities.models, request.host_with_port) end def has_id?(model, id) Entities.models[model].key?(id) end def not_have(id) [404, JSON.generate({ error: "'#{id}' not found" })] end get "/" do summary = { models: Entities.models.keys.to_s, docs_url: "Swagger docs" } summary[:db] = MongoClient.client.summary.to_s if ENV["mongodb"] JSON.generate(summary) rescue StandardError => e [500, e.message] end Entities.models.each_key do |model| post "/#{model.downcase}" do response["Access-Control-Allow-Origin"] = "*" request_id = SecureRandom.uuid headers["X-Request-Id"] = request_id SchemalessRestApi.logger.info env SchemalessRestApi.logger.info "POST #{request.fullpath}, CorrelationId: #{request_id}" request_body = request.body.read data = {} data = JSON.parse(request_body) unless request_body.empty? id = "" if data["id"] id = data["id"].to_s else id = SecureRandom.uuid data["id"] = id end if ENV["mongodb"] MongoClient.insert(model, data, id) else Entities.models[model][id] = data end SchemalessRestApi.logger.info "Created #{id}, CorrelationId: #{request_id}" [201, JSON.generate({ id: id })] end options "/#{model.downcase}" do response["Allow"] = "*" response["Access-Control-Allow-Origin"] = "*" response["Access-Control-Allow-Methods"] = "*" response["Access-Control-Allow-Headers"] = "*" end get "/#{model.downcase}" do response["Access-Control-Allow-Origin"] = "*" SchemalessRestApi.logger.info "GET #{request.fullpath}" if ENV["mongodb"] if params == {} JSON.generate(MongoClient.get_all(model)) else [200, JSON.generate(MongoClient.find_all(model, params))] end else return JSON.generate(Entities.models[model].values) if params == {} matching_values = Entities.models[model].values.find_all do |val| val[params.keys[0]].to_s == params.values[0] end return JSON.generate(matching_values) end rescue StandardError => e [404, "Nothing found using #{params}. Only first param considered. #{e.message}"] end get "/#{model.downcase}/:id" do |id| response["Access-Control-Allow-Origin"] = "*" SchemalessRestApi.logger.info "GET #{request.fullpath}" if ENV["mongodb"] results = MongoClient.find(model, id) return not_have(id) unless results.first JSON.generate(results.first) else return not_have(id) unless has_id?(model, id) JSON.generate(Entities.models[model][id]) end end options "/#{model.downcase}/:id" do response["Allow"] = "*" response["Access-Control-Allow-Origin"] = "*" response["Access-Control-Allow-Methods"] = "*" response["Access-Control-Allow-Headers"] = "*" end put "/#{model.downcase}/:id" do |id| response["Access-Control-Allow-Origin"] = "*" SchemalessRestApi.logger.info "PUT #{request.fullpath}" data = JSON.parse(request.body.read) if ENV["mongodb"] results = MongoClient.find(model, id) return not_have(id) unless results.first MongoClient.update(model, id, data) else return not_have(id) unless has_id?(model, id) Entities.models[model][id] = data end 204 end delete "/#{model.downcase}/:id" do |id| response["Access-Control-Allow-Origin"] = "*" SchemalessRestApi.logger.info "DEL #{request.fullpath}" if ENV["mongodb"] results = MongoClient.find(model, id) return not_have(id) unless results.first MongoClient.delete(model, id) else return not_have(id) unless has_id?(model, id) Entities.models[model].delete(id) end 204 end end end