openapi_first 1.0.0.beta5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -1
  3. data/CHANGELOG.md +23 -2
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +16 -18
  6. data/Gemfile.rack2 +15 -0
  7. data/Gemfile.rack2.lock +99 -0
  8. data/README.md +99 -130
  9. data/lib/openapi_first/body_parser.rb +29 -0
  10. data/lib/openapi_first/configuration.rb +20 -0
  11. data/lib/openapi_first/definition/cookie_parameters.rb +12 -0
  12. data/lib/openapi_first/definition/header_parameters.rb +12 -0
  13. data/lib/openapi_first/definition/operation.rb +116 -0
  14. data/lib/openapi_first/definition/parameters.rb +47 -0
  15. data/lib/openapi_first/definition/path_item.rb +32 -0
  16. data/lib/openapi_first/definition/path_parameters.rb +12 -0
  17. data/lib/openapi_first/definition/query_parameters.rb +12 -0
  18. data/lib/openapi_first/definition/request_body.rb +43 -0
  19. data/lib/openapi_first/definition/response.rb +25 -0
  20. data/lib/openapi_first/definition/responses.rb +83 -0
  21. data/lib/openapi_first/definition.rb +61 -8
  22. data/lib/openapi_first/error_response.rb +22 -27
  23. data/lib/openapi_first/errors.rb +2 -14
  24. data/lib/openapi_first/failure.rb +55 -0
  25. data/lib/openapi_first/middlewares/request_validation.rb +52 -0
  26. data/lib/openapi_first/middlewares/response_validation.rb +35 -0
  27. data/lib/openapi_first/plugins/default/error_response.rb +74 -0
  28. data/lib/openapi_first/plugins/default.rb +11 -0
  29. data/lib/openapi_first/plugins/jsonapi/error_response.rb +58 -0
  30. data/lib/openapi_first/plugins/jsonapi.rb +11 -0
  31. data/lib/openapi_first/plugins.rb +9 -7
  32. data/lib/openapi_first/request_validation/request_body_validator.rb +41 -0
  33. data/lib/openapi_first/request_validation/validator.rb +81 -0
  34. data/lib/openapi_first/response_validation/validator.rb +101 -0
  35. data/lib/openapi_first/runtime_request.rb +84 -0
  36. data/lib/openapi_first/runtime_response.rb +31 -0
  37. data/lib/openapi_first/schema/validation_error.rb +18 -0
  38. data/lib/openapi_first/schema/validation_result.rb +32 -0
  39. data/lib/openapi_first/{json_schema.rb → schema.rb} +9 -5
  40. data/lib/openapi_first/version.rb +1 -1
  41. data/lib/openapi_first.rb +32 -28
  42. data/openapi_first.gemspec +10 -9
  43. metadata +55 -67
  44. data/.rspec +0 -3
  45. data/.rubocop.yml +0 -14
  46. data/Rakefile +0 -15
  47. data/benchmarks/Gemfile +0 -16
  48. data/benchmarks/Gemfile.lock +0 -142
  49. data/benchmarks/README.md +0 -29
  50. data/benchmarks/apps/committee_with_hanami_api.ru +0 -26
  51. data/benchmarks/apps/committee_with_response_validation.ru +0 -29
  52. data/benchmarks/apps/committee_with_sinatra.ru +0 -31
  53. data/benchmarks/apps/grape.ru +0 -21
  54. data/benchmarks/apps/hanami_api.ru +0 -21
  55. data/benchmarks/apps/hanami_router.ru +0 -14
  56. data/benchmarks/apps/openapi.yaml +0 -268
  57. data/benchmarks/apps/openapi_first_with_hanami_api.ru +0 -24
  58. data/benchmarks/apps/openapi_first_with_plain_rack.ru +0 -32
  59. data/benchmarks/apps/openapi_first_with_response_validation.ru +0 -25
  60. data/benchmarks/apps/openapi_first_with_sinatra.ru +0 -29
  61. data/benchmarks/apps/roda.ru +0 -27
  62. data/benchmarks/apps/sinatra.ru +0 -26
  63. data/benchmarks/apps/syro.ru +0 -25
  64. data/benchmarks/benchmark-wrk.sh +0 -3
  65. data/benchmarks/benchmarks.rb +0 -48
  66. data/benchmarks/post.lua +0 -3
  67. data/bin/console +0 -15
  68. data/bin/setup +0 -8
  69. data/examples/README.md +0 -13
  70. data/examples/app.rb +0 -18
  71. data/examples/config.ru +0 -7
  72. data/examples/openapi.yaml +0 -29
  73. data/lib/openapi_first/body_parser_middleware.rb +0 -40
  74. data/lib/openapi_first/config.rb +0 -20
  75. data/lib/openapi_first/error_responses/default.rb +0 -58
  76. data/lib/openapi_first/error_responses/json_api.rb +0 -58
  77. data/lib/openapi_first/json_schema/result.rb +0 -17
  78. data/lib/openapi_first/operation.rb +0 -170
  79. data/lib/openapi_first/request_body_validator.rb +0 -41
  80. data/lib/openapi_first/request_validation.rb +0 -118
  81. data/lib/openapi_first/request_validation_error.rb +0 -31
  82. data/lib/openapi_first/response_validation.rb +0 -93
  83. data/lib/openapi_first/response_validator.rb +0 -21
  84. data/lib/openapi_first/router.rb +0 -102
  85. data/lib/openapi_first/string_keyed_hash.rb +0 -20
  86. data/lib/openapi_first/use_router.rb +0 -18
@@ -1,102 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rack'
4
- require 'multi_json'
5
- require 'hanami/router'
6
- require_relative 'body_parser_middleware'
7
-
8
- module OpenapiFirst
9
- class Router
10
- # The unconverted path parameters before they are converted to the types defined in the API description
11
- RAW_PATH_PARAMS = 'openapi.raw_path_params'
12
-
13
- def initialize(
14
- app,
15
- options
16
- )
17
- @app = app
18
- @raise = options.fetch(:raise_error, false)
19
- @not_found = options.fetch(:not_found, :halt)
20
- @error_response_class = options.fetch(:error_response, Config.default_options.error_response)
21
- spec = options.fetch(:spec)
22
- raise "You have to pass spec: when initializing #{self.class}" unless spec
23
-
24
- spec = OpenapiFirst.load(spec) unless spec.is_a?(Definition)
25
-
26
- @filepath = spec.filepath
27
- @router = build_router(spec.operations)
28
- end
29
-
30
- def call(env)
31
- env[OPERATION] = nil
32
- response = call_router(env)
33
- if env[OPERATION].nil?
34
- raise_error(env) if @raise
35
-
36
- return @app.call(env) if @not_found == :continue
37
- end
38
-
39
- response
40
- end
41
-
42
- ORIGINAL_PATH = 'openapi_first.path_info'
43
- private_constant :ORIGINAL_PATH
44
-
45
- ROUTER_PARSED_BODY = 'router.parsed_body'
46
- private_constant :ROUTER_PARSED_BODY
47
-
48
- private
49
-
50
- def raise_error(env)
51
- req = Rack::Request.new(env)
52
- msg =
53
- "Could not find definition for #{req.request_method} '#{
54
- req.path
55
- }' in API description #{@filepath}"
56
- raise NotFoundError, msg
57
- end
58
-
59
- def call_router(env)
60
- # Changing and restoring PATH_INFO is needed, because Hanami::Router does not respect existing script_path
61
- env[ORIGINAL_PATH] = env[Rack::PATH_INFO]
62
- env[Rack::PATH_INFO] = Rack::Request.new(env).path
63
- @router.call(env)
64
- rescue BodyParsingError => e
65
- message = e.message
66
- raise RequestInvalidError, message if @raise
67
-
68
- error = RequestValidationError.new(status: 400, location: :body, message:)
69
- @error_response_class.new(env, error).render
70
- ensure
71
- env[Rack::PATH_INFO] = env.delete(ORIGINAL_PATH) if env[ORIGINAL_PATH]
72
- end
73
-
74
- def build_router(operations)
75
- router = Hanami::Router.new.tap do |r|
76
- operations.each do |operation|
77
- normalized_path = operation.path.gsub('{', ':').gsub('}', '')
78
- r.public_send(
79
- operation.method,
80
- normalized_path,
81
- to: build_route(operation)
82
- )
83
- end
84
- end
85
- Rack::Builder.app do
86
- use(BodyParserMiddleware)
87
- run router
88
- end
89
- end
90
-
91
- def build_route(operation)
92
- lambda do |env|
93
- env[OPERATION] = operation
94
- path_info = env.delete(ORIGINAL_PATH)
95
- env[REQUEST_BODY] = env.delete(ROUTER_PARSED_BODY) if env.key?(ROUTER_PARSED_BODY)
96
- env[RAW_PATH_PARAMS] = env['router.params']
97
- env[Rack::PATH_INFO] = path_info
98
- @app.call(env)
99
- end
100
- end
101
- end
102
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenapiFirst
4
- class StringKeyedHash
5
- extend Forwardable
6
- def_delegators :@orig, :empty?
7
-
8
- def initialize(original)
9
- @orig = original
10
- end
11
-
12
- def key?(key)
13
- @orig.key?(key.to_sym)
14
- end
15
-
16
- def [](key)
17
- @orig[key.to_sym]
18
- end
19
- end
20
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenapiFirst
4
- module UseRouter
5
- def initialize(app, options = {})
6
- @app = app
7
- @options = options
8
- super
9
- end
10
-
11
- def call(env)
12
- return super if env.key?(OPERATION)
13
-
14
- @router ||= Router.new(->(e) { super(e) }, @options)
15
- @router.call(env)
16
- end
17
- end
18
- end