apollo_fetch_upload_rails_middleware 0.2.0.alpha → 1.0.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
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.
|