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 +7 -0
- data/README.md +30 -0
- data/lib/ffimod.rb +86 -0
- data/lib/inigo-darwin-amd64.dylib +0 -0
- data/lib/inigo-darwin-arm64.dylib +0 -0
- data/lib/inigo-linux-amd64.so +0 -0
- data/lib/inigo-linux-arm64.so +0 -0
- data/lib/inigo-windows-amd64.dll +0 -0
- data/lib/inigo-windows-arm64.dll +0 -0
- data/lib/inigorb.rb +204 -0
- data/lib/query.rb +80 -0
- metadata +95 -0
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: []
|