|
47 | 47 |
|
48 | 48 | # Keep path keys relative to /api/v1 because servers include the versioned base path. |
49 | 49 | RSpec::OpenAPI.post_process_hook = lambda do |_path, _records, spec| |
| 50 | + token_feed_error_statuses = %w[401 403 500].freeze |
| 51 | + |
50 | 52 | stringify = lambda do |value| |
51 | 53 | case value |
52 | 54 | when Hash |
|
69 | 71 | end |
70 | 72 | end |
71 | 73 |
|
| 74 | + merge_responses = lambda do |existing_responses, new_responses| |
| 75 | + statuses = existing_responses.keys | new_responses.keys |
| 76 | + |
| 77 | + statuses.each_with_object({}) do |status, merged_responses| |
| 78 | + current = existing_responses[status] || {} |
| 79 | + incoming = new_responses[status] || {} |
| 80 | + merged_response = current.merge(incoming) |
| 81 | + |
| 82 | + current_content = current['content'] || {} |
| 83 | + incoming_content = incoming['content'] || {} |
| 84 | + if current_content.any? || incoming_content.any? |
| 85 | + content_types = current_content.keys | incoming_content.keys |
| 86 | + merged_response['content'] = content_types.to_h do |content_type| |
| 87 | + current_entry = current_content[content_type] || {} |
| 88 | + incoming_entry = incoming_content[content_type] || {} |
| 89 | + [content_type, current_entry.merge(incoming_entry)] |
| 90 | + end |
| 91 | + end |
| 92 | + |
| 93 | + current_headers = current['headers'] || {} |
| 94 | + incoming_headers = incoming['headers'] || {} |
| 95 | + if current_headers.any? || incoming_headers.any? |
| 96 | + merged_response['headers'] = current_headers.merge(incoming_headers) |
| 97 | + end |
| 98 | + |
| 99 | + merged_response['description'] ||= current['description'] || incoming['description'] |
| 100 | + merged_responses[status] = merged_response |
| 101 | + end |
| 102 | + end |
| 103 | + |
| 104 | + token_feed_error_examples = { |
| 105 | + 'application/xml' => { |
| 106 | + 'example' => <<~XML.strip |
| 107 | + <?xml version="1.0" encoding="UTF-8"?> |
| 108 | + <rss version="2.0"><channel><title>Error</title><description>Internal Server Error</description></channel></rss> |
| 109 | + XML |
| 110 | + }, |
| 111 | + 'application/feed+json' => { |
| 112 | + 'example' => { |
| 113 | + 'version' => 'https://jsonfeed.org/version/1.1', |
| 114 | + 'title' => 'Error' |
| 115 | + } |
| 116 | + } |
| 117 | + } |
| 118 | + |
72 | 119 | path_map = spec['paths'] || spec[:paths] |
73 | 120 | next unless path_map.is_a?(Hash) |
74 | 121 |
|
|
90 | 137 |
|
91 | 138 | if existing |
92 | 139 | merged = existing.merge(operation_doc) |
93 | | - merged['responses'] = (existing['responses'] || {}).merge(operation_doc['responses'] || {}) |
| 140 | + merged['responses'] = merge_responses.call(existing['responses'] || {}, operation_doc['responses'] || {}) |
94 | 141 | merged['parameters'] = [*(existing['parameters'] || []), *(operation_doc['parameters'] || [])] |
95 | 142 | merged['parameters'].uniq! { |parameter| [parameter['name'], parameter['in']] } |
96 | 143 | normalized_paths[normalized][verb] = deep_sort.call(merged) |
|
106 | 153 | has_token_param = normalized_paths[normalized][verb]['parameters'].any? do |parameter| |
107 | 154 | parameter['name'] == 'token' && parameter['in'] == 'path' |
108 | 155 | end |
109 | | - next if has_token_param |
| 156 | + unless has_token_param |
| 157 | + normalized_paths[normalized][verb]['parameters'] << { |
| 158 | + 'name' => 'token', |
| 159 | + 'in' => 'path', |
| 160 | + 'required' => true, |
| 161 | + 'schema' => { 'type' => 'string' } |
| 162 | + } |
| 163 | + end |
110 | 164 |
|
111 | | - normalized_paths[normalized][verb]['parameters'] << { |
112 | | - 'name' => 'token', |
113 | | - 'in' => 'path', |
114 | | - 'required' => true, |
115 | | - 'schema' => { 'type' => 'string' } |
116 | | - } |
| 165 | + token_feed_error_statuses.each do |status| |
| 166 | + response = normalized_paths[normalized][verb].dig('responses', status) |
| 167 | + next unless response |
| 168 | + |
| 169 | + response['content'] ||= {} |
| 170 | + token_feed_error_examples.each do |content_type, example| |
| 171 | + response['content'][content_type] ||= { 'schema' => { 'type' => 'string' } } |
| 172 | + response['content'][content_type].merge!(example) |
| 173 | + end |
| 174 | + end |
117 | 175 | end |
118 | 176 | end |
119 | 177 |
|
|
0 commit comments