praxis 2.0.pre.25 → 2.0.pre.26

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d73908c503a31cf0df282dac909e0ef1e0275177214a024af13080176bbcfc3
4
- data.tar.gz: 365e044a88823e1f4941e9393bec2ac76612359c2e53cdf4e496bfc006384502
3
+ metadata.gz: dcecd5fd9fb69d436e75297f383ffeaa63373caf8ddfbefdb7361230c981ffc8
4
+ data.tar.gz: a5e00599183864a2fec4a3f197accaa8c8724fdd40400d91917a460bbd72f8aa
5
5
  SHA512:
6
- metadata.gz: efedee79c593c8ce8c16ec16133ebe3433801dbffa07266f8ae163febc231db5bd1cb362cb0670509af37642114f298b988b163100492037ce8a84309bb22992
7
- data.tar.gz: 344040ab4d645a405ca9552ed3375c42163e600584bb339f9e593257ac24869685e4ae7205ce0a4ca9560cd5e7b9fb12ff2080f2b4163daae59ee713fb21e536
6
+ metadata.gz: cf23dd0e2cd395df1a956216987023b1427e50268a964a770d2b1649206a115ae345a91adefaf067d612c64f04b312f1e508e1dc8f56dfa1157a395c038ac31f
7
+ data.tar.gz: fd01611ba7921490e8fdfee9073ab83fab85130e4428271e1d0f448cde5afd844da6a2a930bbff206f6b9832589bc425d5fc15231eb44a7c47842942305e4b40
data/CHANGELOG.md CHANGED
@@ -2,9 +2,12 @@
2
2
 
3
3
  ## next
4
4
 
5
+ ## 2.0.pre.26
6
+ * Make POST action forwarding more robust against technically malformed GET requests with no body but passing `Content-Type`. This could cause issues when using the `enable_large_params_proxy_action` DSL.
7
+
5
8
  ## 2.0.pre.25
6
9
  * Improve surfacing of requirement attributes in Structs for OpenApi generated documentation
7
- * Introduction of a new `dsl enable_large_params_proxy_action` for GET verb action definitions. When used, two things will happen:
10
+ * Introduction of a new dsl `enable_large_params_proxy_action` for GET verb action definitions. When used, two things will happen:
8
11
  * A new POST verb equivalent action will be defined:
9
12
  * It will have a `payload` matching the shape of the original GET's params (with the exception of any param that was originally in the URL)
10
13
  * By default, the route for this new POST request is gonna have the same URL as the original GET action, but appending `/actions/<action_name>` to it. This can be customized by passing the path with the `at:` parameter of the DSL. I.e., `enable_large_params_proxy_action at: /actions/myspecialname` will change the generated path (can use the `//...` syntax to not include the prefix defined for the endpoint). NOTE: this route needs to be compatible with any params that might be defined for the URL (i.e., `:id` and such).
@@ -14,8 +14,14 @@ module Praxis
14
14
 
15
15
  def call(request)
16
16
  dispatcher = Dispatcher.current(application: @application)
17
- # Switch to the sister get action if configured that way
18
- action = @action.sister_get_action || @action
17
+ # Switch to the sister get action if configured that way (and mark the request as forwarded)
18
+ action = \
19
+ if @action.sister_get_action
20
+ request.forwarded_from_action = @action
21
+ @action.sister_get_action
22
+ else
23
+ @action
24
+ end
19
25
  dispatcher.dispatch(@controller, action, request)
20
26
  end
21
27
  end
@@ -3,7 +3,7 @@
3
3
  module Praxis
4
4
  class Request < Praxis.request_superclass
5
5
  attr_reader :env, :query
6
- attr_accessor :route_params, :action, :headers, :params, :payload
6
+ attr_accessor :route_params, :action, :headers, :params, :payload, :forwarded_from_action
7
7
 
8
8
  PATH_VERSION_PREFIX = '/v'
9
9
  CONTENT_TYPE_NAME = 'CONTENT_TYPE'
@@ -123,15 +123,16 @@ module Praxis
123
123
  return unless action.params
124
124
 
125
125
  self.params = action.params.load(raw_params, context)
126
- return unless action.sister_post_action && content_type
126
+ return unless forwarded_from_action && content_type
127
127
 
128
+ # If it is coming from a forwarded action, and has a content type, let's parse it, and merge it to the params as well
128
129
  raw = if (handler = Praxis::Application.instance.handlers[content_type.handler_name])
129
130
  handler.parse(raw_payload)
130
131
  else
131
132
  # TODO: is this a good default?
132
133
  raw_payload
133
134
  end
134
- loaded_payload = action.sister_post_action.payload.load(raw, context, content_type: content_type.to_s)
135
+ loaded_payload = forwarded_from_action.payload.load(raw, context, content_type: content_type.to_s)
135
136
  self.params = params.merge(loaded_payload)
136
137
  end
137
138
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Praxis
4
- VERSION = '2.0.pre.25'
4
+ VERSION = '2.0.pre.26'
5
5
  end
@@ -111,8 +111,30 @@ describe 'Functional specs' do
111
111
  end
112
112
  end
113
113
  end
114
+ context 'with a valid request but misusing request content-type' do
115
+ it 'is still successful and does not get confused about the sister post action' do
116
+ the_body = StringIO.new('') # This is a GET request passing a body
117
+ get '/api/clouds/1/instances?api_version=1.0', nil, 'rack.input' => the_body, 'CONTENT_TYPE' => 'application/json', 'global_session' => session
118
+ expect(last_response.status).to eq(200)
119
+ expect(last_response.headers['Content-Type']).to(
120
+ eq('application/vnd.acme.instance;type=collection')
121
+ )
122
+ end
123
+ end
114
124
  end
115
125
 
126
+ context 'index using POST sister action' do
127
+ context 'with a valid request' do
128
+ it 'is successful and round trips the content type we pass in the body' do
129
+ payload = { response_content_type: 'application/vnd.acme.instance; type=collection; other=thing' }
130
+ post '/api/clouds/1/instances/actions/index_using_post?api_version=1.0', JSON.dump(payload), 'CONTENT_TYPE' => 'application/json', 'global_session' => session
131
+ expect(last_response.status).to eq(200)
132
+ expect(last_response.headers['Content-Type']).to(
133
+ eq(payload[:response_content_type])
134
+ )
135
+ end
136
+ end
137
+ end
116
138
  it 'works' do
117
139
  the_body = StringIO.new('{}') # This is a funny, GET request expecting a body
118
140
  get '/api/clouds/1/instances/2?junk=foo&api_version=1.0', nil, 'rack.input' => the_body, 'CONTENT_TYPE' => 'application/json', 'global_session' => session
@@ -24,6 +24,8 @@ module ApiResources
24
24
  end
25
25
 
26
26
  action :index do
27
+ enable_large_params_proxy_action at: '/actions/index_using_post'
28
+
27
29
  routing do
28
30
  get ''
29
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: praxis
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.pre.25
4
+ version: 2.0.pre.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josep M. Blanquer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-10-26 00:00:00.000000000 Z
12
+ date: 2022-11-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -676,7 +676,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
676
676
  - !ruby/object:Gem::Version
677
677
  version: 1.3.1
678
678
  requirements: []
679
- rubygems_version: 3.1.2
679
+ rubygems_version: 3.3.7
680
680
  signing_key:
681
681
  specification_version: 4
682
682
  summary: Building APIs the way you want it.