Class: GraphQL::Stitching::HttpExecutable
- Inherits:
-
Object
- Object
- GraphQL::Stitching::HttpExecutable
- Defined in:
- lib/graphql/stitching/http_executable.rb
Overview
HttpExecutable provides an out-of-the-box convenience for sending HTTP post requests to a remote location, or a base class for other implementations with GraphQL multipart uploads.
Instance Method Summary collapse
- #call(request, document, variables) ⇒ Object
-
#extract_multipart_form(request, document, variables) ⇒ Object
Extracts multipart upload forms per the spec: https://github.com/jaydenseric/graphql-multipart-request-spec.
-
#initialize(url:, headers: {}, upload_types: nil) ⇒ HttpExecutable
constructor
Builds a new executable for proxying subgraph requests via HTTP.
-
#send(_request, document, variables) ⇒ Object
Sends a POST request to the remote location.
-
#send_multipart_form(_request, form_data) ⇒ Object
Sends a POST request to the remote location with multipart form data.
Constructor Details
#initialize(url:, headers: {}, upload_types: nil) ⇒ HttpExecutable
Builds a new executable for proxying subgraph requests via HTTP.
17 18 19 20 21 |
# File 'lib/graphql/stitching/http_executable.rb', line 17 def initialize(url:, headers: {}, upload_types: nil) @url = url @headers = { "Content-Type" => "application/json" }.merge!(headers) @upload_types = upload_types end |
Instance Method Details
#call(request, document, variables) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/graphql/stitching/http_executable.rb', line 23 def call(request, document, variables) form_data = extract_multipart_form(request, document, variables) response = if form_data send_multipart_form(request, form_data) else send(request, document, variables) end JSON.parse(response.body) end |
#extract_multipart_form(request, document, variables) ⇒ Object
Extracts multipart upload forms per the spec: https://github.com/jaydenseric/graphql-multipart-request-spec
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/graphql/stitching/http_executable.rb', line 68 def extract_multipart_form(request, document, variables) return unless @upload_types && request.variable_definitions.any? && variables&.any? files_by_path = {} # extract all upload scalar values mapped by their input path variables.each_with_object([]) do |(key, value), path| ast_node = request.variable_definitions[key] path << key extract_ast_node(ast_node, value, files_by_path, path, request) if ast_node path.pop end return if files_by_path.none? map = {} files = files_by_path.values.tap(&:uniq!) variables_copy = variables.dup files_by_path.each_key do |path| orig = variables copy = variables_copy path.each_with_index do |key, i| if i == path.length - 1 file_index = files.index(copy[key]).to_s map[file_index] ||= [] map[file_index] << "variables.#{path.join(".")}" copy[key] = nil elsif orig[key].object_id == copy[key].object_id copy[key] = copy[key].dup end orig = orig[key] copy = copy[key] end end form = { "operations" => JSON.generate({ "query" => document, "variables" => variables_copy, }), "map" => JSON.generate(map), } files.each_with_object(form).with_index do |(file, memo), index| memo[index.to_s] = file.respond_to?(:tempfile) ? file.tempfile : file end end |
#send(_request, document, variables) ⇒ Object
Sends a POST request to the remote location.
39 40 41 42 43 44 45 |
# File 'lib/graphql/stitching/http_executable.rb', line 39 def send(_request, document, variables) Net::HTTP.post( URI(@url), JSON.generate({ "query" => document, "variables" => variables }), @headers, ) end |
#send_multipart_form(_request, form_data) ⇒ Object
Sends a POST request to the remote location with multipart form data.
50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/graphql/stitching/http_executable.rb', line 50 def send_multipart_form(_request, form_data) uri = URI(@url) req = Net::HTTP::Post.new(uri) @headers.each_pair do |key, value| req[key] = value end req.set_form(form_data.to_a, "multipart/form-data") Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http| http.request(req) end end |