inigorb 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|