apollo_fetch_upload_rails_middleware 0.2.0.alpha → 1.0.0.alpha
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
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '0742048ae5b92d8ac9f64f6ac57ea00fba3dcb92265c30e3acaa60f8d466524b'
|
4
|
+
data.tar.gz: 0bf560ea2ea86edc752ddf6431a30a5b9e5602503507a31e605e0dfab7b2548d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e48cd2fe15cb4782ff7f045ef4cea086731e2222c1e634646fe5cb3d0558d64f49dd8f8a56c1875bdbadfa56bfcfcc6b8baafde79e413b213a895a087c88951c
|
7
|
+
data.tar.gz: 4ec7740ee4f13872385f19d7f32d109bb3739718314e2c4d0375a77766a7298d0512fdd335822b0ab96c75d51eb7d20fcc07143c1eb27d0b970f2aac2717e126
|
@@ -6,68 +6,150 @@ module ApolloFetchUploadRailsMiddleware
|
|
6
6
|
|
7
7
|
def call(env)
|
8
8
|
request = Rack::Request.new(env)
|
9
|
-
|
9
|
+
|
10
|
+
if request.content_type.try(:start_with?, 'multipart/form-data') &&
|
11
|
+
request.params.key?('operations') &&
|
12
|
+
request.params.key?('map')
|
13
|
+
|
10
14
|
gql_operations = JSON.parse(request.params['operations'])
|
11
|
-
request.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
15
|
+
file_to_variables_map = JSON.parse(request.params['map'])
|
16
|
+
|
17
|
+
# Gather file data.
|
18
|
+
file_to_metadata_map = {}
|
19
|
+
file_to_variables_map.each_key do |file_index|
|
20
|
+
file_to_metadata_map[file_index] = validate_file_info(request.params[file_index.to_s])
|
21
|
+
end
|
22
|
+
|
23
|
+
if gql_operations.is_a?(Hash)
|
24
|
+
request.update_param('query', gql_operations['query'])
|
25
|
+
request.update_param('operationName', gql_operations['operationName'])
|
26
|
+
request.update_param(
|
27
|
+
'variables',
|
28
|
+
fill_in_gql_variables(
|
29
|
+
file_to_variables_map,
|
30
|
+
file_to_metadata_map,
|
31
|
+
gql_operations['variables'],
|
32
|
+
),
|
33
|
+
)
|
34
|
+
elsif gql_operations.is_a?(Array)
|
35
|
+
gql_operations.each_with_index do |gql_operation, idx|
|
36
|
+
gql_operation['variables'] = fill_in_gql_variables(
|
37
|
+
file_to_variables_map,
|
38
|
+
file_to_metadata_map,
|
39
|
+
gql_operation['variables'],
|
40
|
+
batch_index: idx,
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
# cf. https://github.com/rmosolgo/graphql-ruby/blob/master/
|
45
|
+
# guides/queries/multiplex.md#apollo-query-batching
|
46
|
+
# -> "Apollo sends the params in a _json variable when batching is enabled"
|
47
|
+
request.update_param('_json', gql_operations)
|
48
|
+
else
|
49
|
+
raise 'Invalid JSON in "operations" request param.'
|
26
50
|
end
|
51
|
+
end
|
52
|
+
|
53
|
+
@app.call(env)
|
54
|
+
end
|
55
|
+
|
56
|
+
def fill_in_gql_variables(
|
57
|
+
file_to_variables_map,
|
58
|
+
file_to_metadata_map,
|
59
|
+
variables_h,
|
60
|
+
batch_idx: nil
|
61
|
+
)
|
62
|
+
# file_to_variables_map is of type map<int, [string]>, mapping file indices to the GQL variables which
|
63
|
+
# use that file (the author of apollo-upload-client does it this way to support batching more efficiently).
|
64
|
+
#
|
65
|
+
# request.params should have keys of file indices (as strings) mapping to metadata about the file itself, e.g.
|
66
|
+
#
|
67
|
+
# "0"=> {
|
68
|
+
# :filename=>"f6765.pdf",
|
69
|
+
# :type=>"application/pdf",
|
70
|
+
# :name=>"0",
|
71
|
+
# :tempfile=>
|
72
|
+
# <File:/var/folders/cc/fwn8xb8s6jzdg672klspnvg40000gn/T/RackMultipart20180719-18089-y5qrhg.pdf>,
|
73
|
+
# :head=>
|
74
|
+
# "Content-Disposition: form-data; name=\"0\"; filename=\"f6765.pdf\"\r\n" +
|
75
|
+
# "Content-Type: application/pdf\r\n"
|
76
|
+
# }
|
77
|
+
#
|
78
|
+
# So, what we need to do is go through all of the files, and for each GQL variable which uses that file,
|
79
|
+
# set it (using pathset, set below) to have that File instance.
|
27
80
|
|
28
|
-
|
29
|
-
variables: gql_operations['variables'],
|
30
|
-
)
|
81
|
+
variables_wrapper = { variables: variables_h }.with_indifferent_access
|
31
82
|
|
32
|
-
|
33
|
-
|
83
|
+
file_to_variables_map.each do |file_index, variable_paths|
|
84
|
+
file_info = file_to_metadata_map[file_index]
|
34
85
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
86
|
+
variable_paths.each do |variable_path|
|
87
|
+
variable_path_components = variable_path.split('.')
|
88
|
+
|
89
|
+
unless batch_idx.nil?
|
90
|
+
# We only care about this variable path if it matches the given batch_idx.
|
91
|
+
# Otherwise, it doesn't apply to this operation.
|
92
|
+
variable_path_batch_idx = variable_path_components.shift
|
93
|
+
next unless batch_idx == variable_path_batch_idx
|
94
|
+
end
|
41
95
|
|
42
96
|
pathset(
|
43
97
|
variables_wrapper,
|
44
|
-
|
98
|
+
variable_path_components,
|
45
99
|
file_info,
|
46
100
|
)
|
47
101
|
end
|
48
|
-
|
49
|
-
request.update_param('variables', variables_wrapper[:variables])
|
50
102
|
end
|
51
103
|
|
52
|
-
|
104
|
+
variables_wrapper[:variables]
|
53
105
|
end
|
54
106
|
|
55
107
|
private
|
56
108
|
|
57
|
-
def pathset(
|
58
|
-
|
59
|
-
|
60
|
-
|
109
|
+
def pathset(variables_h, path_components, file_info)
|
110
|
+
# Find the immediate parent, and then set file info on parent's field
|
111
|
+
# named path_components.last.
|
112
|
+
|
113
|
+
raise 'Not deep enough' unless path_components.size >= 2
|
114
|
+
|
115
|
+
h_or_a = variables_h
|
116
|
+
while path_components.size > 1
|
117
|
+
path_component = path_components.shift
|
118
|
+
if h_or_a.is_a?(Array)
|
119
|
+
h_or_a = h_or_a[path_component.to_i]
|
120
|
+
elsif h_or_a.is_a?(Hash)
|
121
|
+
h_or_a = h_or_a[path_component]
|
122
|
+
else
|
123
|
+
raise 'Unexpected type in variables path.'
|
124
|
+
end
|
61
125
|
end
|
62
126
|
|
63
|
-
|
64
|
-
|
65
|
-
|
127
|
+
# Now the last path component is the field we want to set.
|
128
|
+
raise 'Bad path components.' unless path_components.size == 1
|
129
|
+
field_name = path_components.first
|
130
|
+
|
131
|
+
if h_or_a.is_a?(Hash)
|
132
|
+
h_or_a[field_name] = file_info
|
133
|
+
elsif h_or_a.is_a?(Array)
|
134
|
+
h_or_a[field_name.to_i] = file_info
|
66
135
|
else
|
67
|
-
|
136
|
+
raise 'Unexpected type in variables path.'
|
68
137
|
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def validate_file_info(file_data)
|
141
|
+
[:filename, :tempfile, :type].each do |k|
|
142
|
+
raise "Missing key '#{k.to_s}' in file data." unless file_data[k].present?
|
143
|
+
end
|
144
|
+
|
145
|
+
raise 'Expected Tempfile in file_data[:tempfile]' unless file_data[:tempfile].is_a?(Tempfile)
|
69
146
|
|
70
|
-
|
147
|
+
{
|
148
|
+
name: file_data[:filename],
|
149
|
+
path: file_data[:tempfile].path,
|
150
|
+
size: file_data[:tempfile].size,
|
151
|
+
type: file_data[:type],
|
152
|
+
}
|
71
153
|
end
|
72
154
|
end
|
73
155
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apollo_fetch_upload_rails_middleware
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abe Land
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -89,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
89
|
version: 1.3.1
|
90
90
|
requirements: []
|
91
91
|
rubyforge_project:
|
92
|
-
rubygems_version: 2.6
|
92
|
+
rubygems_version: 2.7.6
|
93
93
|
signing_key:
|
94
94
|
specification_version: 4
|
95
95
|
summary: Rails middleware for using the apollo-fetch-upload npm package on the client.
|