inigorb 0.0.3

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8fd78ac0ebe0a29c918b14393b77a7f0e70fc2ac7784a1044ce1dc6aed24b3d1
4
+ data.tar.gz: d1456a17c854c33f1e503fcbf7f0dbcc777b3dbff66a71fee5bf0a185c78e3cc
5
+ SHA512:
6
+ metadata.gz: 2fc9a795e9d758776410c4636c8bb9f5e3727a57c748ab6d6106c84eb9fdf4f15af0b981b7560f7e6539bf3e5605f1455a02f681be804cd41a29eecd52bcac9f
7
+ data.tar.gz: e4cc38bf13719eaac2228980dd6ec029cf9f2c6b7e741ece04fc60fa65eefadf99f433225a749b02f1ceebedd77accc01283bdafc4a5af8e66216220d919ccee
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ <br />
2
+ <div align="center">
3
+ <img src="/assets/inigo.svg">
4
+ <img height="25" src="/assets/ruby.svg">
5
+
6
+ <p align="center">
7
+ GraphQL Middleware
8
+ <br />
9
+ <a href="https://docs.inigo.io"><strong>Explore the docs »</strong></a>
10
+ <br /> <br />
11
+ <a href="https://inigo.io">Homepage</a>
12
+ ·
13
+ <a href="https://github.com/inigolabs/inigo-ruby/tree/master/example-rails">View an example</a>
14
+ ·
15
+ <a href="https://github.com/inigolabs/inigo-ruby/issues">Report Bug</a>
16
+ </p>
17
+ </div>
18
+
19
+ ### Documentation
20
+
21
+ This package is the Inigo plugin for Ruby servers.
22
+
23
+ Documentation is available here: [docs.inigo.io](https://docs.inigo.io/docs/deployment)
24
+
25
+ ### Contributing
26
+
27
+ Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
28
+
29
+ ### License
30
+ Distributed under the MIT License.
data/lib/ffimod.rb ADDED
@@ -0,0 +1,86 @@
1
+ require 'ffi'
2
+
3
+ module Inigo
4
+ extend FFI::Library
5
+
6
+ def self.get_arch(system_name)
7
+ machine = RbConfig::CONFIG['target_cpu'].downcase
8
+ if system_name == 'darwin'
9
+ return 'amd64' if machine == 'x86_64'
10
+ return 'arm64' if machine == 'arm64'
11
+ end
12
+
13
+ if system_name == 'linux'
14
+ if machine == 'x86_64' && ['64bit', 'universal'].include?(RUBY_PLATFORM.match(/(\d+)/)[0])
15
+ return 'amd64'
16
+ elsif machine == 'aarch64'
17
+ return 'arm64'
18
+ elsif machine == 'x86_64' && RUBY_PLATFORM.match?(/(i\d86|x\d86)/)
19
+ return '386'
20
+ elsif machine.start_with?('arm') # armv7l
21
+ return 'arm'
22
+ end
23
+ end
24
+
25
+ if system_name == 'windows'
26
+ return 'amd64' if ['x86_64', 'universal'].include?(RbConfig::CONFIG['host_cpu'])
27
+ end
28
+
29
+ machine
30
+ end
31
+
32
+ def self.get_ext(system_name)
33
+ return '.dll' if system_name == 'windows'
34
+ return '.dylib' if system_name == 'darwin'
35
+
36
+ '.so'
37
+ end
38
+
39
+ system_name = RbConfig::CONFIG['host_os']
40
+
41
+ supported_systems = /(linux|darwin|mingw|mswin|cygwin)/
42
+
43
+ unless supported_systems.match?(system_name)
44
+ raise RuntimeError, "Only Windows, macOS (darwin), and Linux systems are supported. RUBY_PLATFORM: #{RUBY_PLATFORM}, RUBY_ENGINE: #{RUBY_ENGINE}, HOST_OS: #{system_name}"
45
+ end
46
+
47
+ system_name = 'windows' if system_name =~ /(mingw|mswin|cygwin)/
48
+ system_name = 'darwin' if system_name =~ /darwin/i
49
+ system_name = 'linux' if system_name =~ /linux/i
50
+
51
+ filename = "inigo-#{system_name}-#{get_arch(system_name)}#{get_ext(system_name)}"
52
+
53
+ begin
54
+ ffi_lib File.join(File.dirname(__FILE__), filename)
55
+
56
+ class Config < FFI::Struct
57
+ layout :debug, :bool,
58
+ :ingest, :pointer,
59
+ :service, :pointer,
60
+ :token, :pointer,
61
+ :schema, :pointer,
62
+ :introspection, :pointer
63
+ end
64
+
65
+ attach_function :create, [:u_int64_t], :u_int64_t
66
+ attach_function :process_request, [
67
+ :u_int64_t, # instance
68
+ :pointer, :int, # header
69
+ :pointer, :int, # input
70
+ :pointer, :pointer, # output
71
+ :pointer, :pointer # status
72
+ ], :u_int64_t
73
+ attach_function :process_response, [
74
+ :u_int64_t, # instance
75
+ :u_int64_t, # request handler
76
+ :pointer, :int, # input
77
+ :pointer, :pointer # output
78
+ ], :void
79
+ attach_function :get_version, [], :string
80
+ attach_function :disposeHandle, [:u_int64_t], :void
81
+ attach_function :disposeMemory, [:pointer], :void
82
+ attach_function :check_lasterror, [], :string
83
+ rescue LoadError => e
84
+ raise ::RuntimeError, "Unable to open Inigo shared library.\n\nPlease get in touch with us for support:\nemail: support@inigo.io\nslack: https://slack.inigo.io\n\nPlease share the below info with us:\nerror: #{e.to_s}\nuname: #{RbConfig::CONFIG['host_os']}\narch: #{RbConfig::CONFIG['host_cpu']}"
85
+ end
86
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
data/lib/inigorb.rb ADDED
@@ -0,0 +1,204 @@
1
+ require 'json'
2
+ require 'ffi'
3
+ require_relative 'ffimod'
4
+ require_relative 'query'
5
+
6
+ module Inigo
7
+ class Middleware
8
+ @@instance = 0
9
+ @@initialized = false
10
+ @@path = ''
11
+ @@schema = ''
12
+
13
+ def self.instance
14
+ @@instance
15
+ end
16
+
17
+ def self.instance=(value)
18
+ @@instance = value
19
+ end
20
+
21
+ def self.initialized
22
+ @@initialized
23
+ end
24
+
25
+ def self.initialized=(value)
26
+ @@initialized = value
27
+ end
28
+
29
+ def self.path
30
+ @@path
31
+ end
32
+
33
+ def self.path=(value)
34
+ @@path = value
35
+ end
36
+
37
+ def self.schema
38
+ @@schema
39
+ end
40
+
41
+ def self.schema=(value)
42
+ @@schema = value
43
+ end
44
+
45
+ def initialize(app)
46
+ @app = app
47
+ end
48
+
49
+ def call(env)
50
+ # Ignore execution if Inigo is not initialized
51
+ if self.class.instance == 0
52
+ return @app.call(env)
53
+ end
54
+
55
+ request = Rack::Request.new(env)
56
+
57
+ # 'path' guard -> /graphql
58
+ if request.path != self.class.path
59
+ return @app.call(env)
60
+ end
61
+
62
+ # GraphiQL request
63
+ if request.get? && request.accept.include?('text/html')
64
+ return @app.call(env)
65
+ end
66
+
67
+ # Support only POST and GET requests
68
+ if !request.post? && !request.get?
69
+ return @app.call(env)
70
+ end
71
+
72
+ # Parse request
73
+ gReq = ''
74
+ if request.post?
75
+ # Read request from body
76
+ request.body.each { |chunk| gReq += chunk }
77
+ request.body.rewind
78
+ elsif request.get?
79
+ # Read request from query param
80
+ gReq = JSON.dump({ 'query' => request.params['query'] })
81
+ end
82
+
83
+ q = Query.new(self.class.instance, gReq)
84
+
85
+ # Inigo: process request
86
+ resp, req = q.process_request(headers(request))
87
+
88
+ # Introspection query
89
+ if resp.any?
90
+ return respond(resp)
91
+ end
92
+
93
+ # Modify query if required
94
+ if req.any?
95
+ if request.post?
96
+ body = JSON.parse(request.body.read)
97
+ body.merge!(
98
+ 'query' => req['query'],
99
+ 'operationName' => req['operationName'],
100
+ 'variables' => req['variables']
101
+ )
102
+ request.body = Rack::Utils.build_nested_query(body)
103
+ elsif request.get?
104
+ params = request.params
105
+ params['query'] = req['query']
106
+ request.update_param(params)
107
+ end
108
+ end
109
+
110
+ # Forward to request handler
111
+ response = @app.call(env)
112
+
113
+ # Inigo: process response
114
+ processed_response = q.process_response(response[2].body.to_s)
115
+ if processed_response
116
+ return respond(processed_response)
117
+ end
118
+
119
+ response
120
+ end
121
+
122
+ private
123
+
124
+ def self.initialize_middleware(schema = nil)
125
+ return if @@initialized
126
+
127
+ if schema
128
+ @@schema = schema
129
+ end
130
+ # get all the inigo settings from env
131
+ settings = ENV.select { |k, v| k.start_with?('INIGO') }
132
+
133
+ if settings.fetch("INIGO_ENABLE", "").to_s.downcase == "false"
134
+ @@initialized = true #not to get to this method ever again
135
+ puts 'Inigo is disabled. Skipping middleware.'
136
+ return
137
+ end
138
+
139
+ config = Inigo::Config.new
140
+
141
+ if settings.fetch("INIGO_DEBUG", "false").to_s.downcase == "true"
142
+ config[:debug] = true
143
+ else
144
+ config[:debug] = false
145
+ end
146
+
147
+ config[:token] = FFI::MemoryPointer.from_string(settings.fetch('INIGO_SERVICE_TOKEN', '').to_s.encode('UTF-8'))
148
+
149
+ schema = nil
150
+ if @@schema
151
+ schema = @@schema
152
+ elsif settings.fetch('INIGO_SCHEMA_PATH', '') != ''
153
+ path = settings.fetch('INIGO_SCHEMA_PATH')
154
+ if File.exist?(path)
155
+ schema = File.read(path)
156
+ end
157
+ end
158
+
159
+ config[:schema] = FFI::MemoryPointer.from_string(schema.to_s.encode('UTF-8')) if schema
160
+
161
+ @@path = settings.fetch('INIGO_PATH', '/query')
162
+
163
+ # Create Inigo instance
164
+ @@instance = Inigo.create(config.pointer.address)
165
+
166
+ error = Inigo.check_lasterror
167
+ if error.length != 0
168
+ puts "INIGO: #{error.read_string}"
169
+ end
170
+
171
+ if @@instance == 0
172
+ puts 'INIGO: error, instance cannot be created'
173
+ end
174
+
175
+ @@initialized = true
176
+ end
177
+
178
+ def headers(request)
179
+ headers = {}
180
+
181
+ request.env.each do |key, value|
182
+ if key.start_with?('HTTP_')
183
+ header_name = key[5..].split('_').map(&:capitalize).join('-')
184
+ headers[header_name] = value.split(',').map(&:strip)
185
+ elsif key == 'CONTENT_TYPE' || key == 'REMOTE_ADDR'
186
+ headers[key] = value.split(',').map(&:strip)
187
+ end
188
+ end
189
+
190
+ JSON.dump(headers)
191
+ end
192
+
193
+ def respond(data)
194
+ response = Rack::Response.new
195
+ response_hash = {}
196
+ response_hash['data'] = data['data'] if data['data']
197
+ response_hash['errors'] = data['errors'] if data['errors']
198
+ response_hash['extensions'] = data['extensions'] if data['extensions']
199
+ response.write(JSON.dump(response_hash))
200
+ response.finish
201
+ end
202
+
203
+ end
204
+ end
data/lib/query.rb ADDED
@@ -0,0 +1,80 @@
1
+ require 'json'
2
+ require_relative 'ffimod'
3
+
4
+ module Inigo
5
+ class Query
6
+ def initialize(instance, request)
7
+ @handle = 0
8
+ @instance = instance
9
+ @request = request
10
+ end
11
+
12
+ def process_request(headers)
13
+ resp_input = FFI::MemoryPointer.from_string(@request)
14
+
15
+ output_ptr = FFI::MemoryPointer.new(:pointer)
16
+ output_len = FFI::MemoryPointer.new(:int)
17
+
18
+ status_ptr = FFI::MemoryPointer.new(:pointer)
19
+ status_len = FFI::MemoryPointer.new(:int)
20
+
21
+ headers_ptr = FFI::MemoryPointer.from_string(headers.to_s)
22
+ headers_len = headers.to_s.length
23
+
24
+ @handle = Inigo.process_request(
25
+ @instance,
26
+ headers_ptr, headers_len,
27
+ resp_input, @request.length,
28
+ output_ptr, output_len,
29
+ status_ptr, status_len
30
+ )
31
+
32
+ resp_dict = {}
33
+ req_dict = {}
34
+
35
+ output_len_value = output_len.read_int
36
+ if output_len_value > 0
37
+ output_data = output_ptr.read_pointer.read_string(output_len_value)
38
+ resp_dict = JSON.parse(output_data)
39
+ end
40
+
41
+ status_len_value = status_len.read_int
42
+ if status_len_value > 0
43
+ status_data = status_ptr.read_pointer.read_string(status_len_value)
44
+ req_dict = JSON.parse(status_data)
45
+ end
46
+
47
+ Inigo.disposeMemory(output_ptr.read_pointer)
48
+ Inigo.disposeMemory(status_ptr.read_pointer)
49
+
50
+ [resp_dict, req_dict]
51
+ end
52
+
53
+ def process_response(resp_body)
54
+ return nil if @handle.zero?
55
+
56
+ output_ptr = FFI::MemoryPointer.new(:pointer)
57
+ output_len = FFI::MemoryPointer.new(:int)
58
+
59
+ Inigo.process_response(
60
+ @instance,
61
+ @handle,
62
+ FFI::MemoryPointer.from_string(resp_body), resp_body.length,
63
+ output_ptr, output_len
64
+ )
65
+
66
+ output_dict = {}
67
+
68
+ output_len_value = output_len.read_int
69
+ if output_len_value > 0
70
+ output_data = output_ptr.read_pointer.read_string(output_len_value)
71
+ output_dict = JSON.parse(output_data)
72
+ end
73
+
74
+ Inigo.disposeMemory(output_ptr.read_pointer)
75
+ Inigo.disposeHandle(@handle)
76
+
77
+ output_dict
78
+ end
79
+ end
80
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inigorb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Inigo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-07-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jwt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.7.1
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.7.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 2.7.1
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.7.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: ffi
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 1.15.5
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.15.5
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: 1.15.5
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.15.5
53
+ description:
54
+ email: eitan@inigo.io
55
+ executables: []
56
+ extensions: []
57
+ extra_rdoc_files: []
58
+ files:
59
+ - README.md
60
+ - lib/ffimod.rb
61
+ - lib/inigo-darwin-amd64.dylib
62
+ - lib/inigo-darwin-arm64.dylib
63
+ - lib/inigo-linux-amd64.so
64
+ - lib/inigo-linux-arm64.so
65
+ - lib/inigo-windows-amd64.dll
66
+ - lib/inigo-windows-arm64.dll
67
+ - lib/inigorb.rb
68
+ - lib/query.rb
69
+ homepage: https://inigo.io
70
+ licenses:
71
+ - MIT
72
+ metadata:
73
+ documentation_uri: https://docs.inigo.io
74
+ homepage_uri: https://inigo.io
75
+ source_code_uri: https://github.com/inigolabs/inigo-rb/blob/master
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 3.1.0
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 3.3.26
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Inigo GraphQL plugin for Ruby
95
+ test_files: []