outpunch-rails 0.1.2

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: a26df1916a7b588561507c63bf92ff1a37f5514177cc5f20b5b452dfce87dff1
4
+ data.tar.gz: c5938d675495f16c91141723d47307dc5f15929c467bd2a1ca3aa29cf12a76aa
5
+ SHA512:
6
+ metadata.gz: f92c995d5c61514dfba82aea81282e54af8fbbe92a4e218247b43673413b6dc85387317019ff2bc8e0d2271f041ba1b0f3c0eb9864b25c210755530e54342b2e
7
+ data.tar.gz: e81584f3cf84df13e5f5bf4b3bc166ca30e6a21251631f1aaf9920bff8c80cc910bdb87212abf5a50d8721fed37b9b586f0a230b1af2d6bc2c83afedda3f74fb
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Outpunch::TunnelController < OutpunchRails.configuration.base_controller.constantize
4
+ skip_before_action :verify_authenticity_token, raise: false
5
+
6
+ def proxy
7
+ service_name = params[:service_name]
8
+ service_path = params[:service_path] || ""
9
+
10
+ return render_error(400, "Service name required") if service_name.blank?
11
+
12
+ if (auth = OutpunchRails.configuration.authorize_service)
13
+ unless auth.call(service_name, request)
14
+ return render_error(403, "Service '#{service_name}' not allowed for this product")
15
+ end
16
+ end
17
+
18
+ unless OutpunchRails.connected?(service_name)
19
+ return render_error(502, "Service '#{service_name}' offline")
20
+ end
21
+
22
+ request_id = SecureRandom.uuid
23
+ payload = {
24
+ request_id: request_id,
25
+ method: request.method,
26
+ path: service_path,
27
+ query: request.query_parameters,
28
+ headers: OutpunchRails.extract_proxy_headers(request.headers),
29
+ body: request.body&.read || ""
30
+ }
31
+
32
+ run_hook(:before_proxy, service_name, service_path, payload)
33
+
34
+ response_data = OutpunchRails.handle_request(
35
+ service: service_name,
36
+ method: payload[:method],
37
+ path: payload[:path],
38
+ query: payload[:query],
39
+ headers: payload[:headers],
40
+ body: payload[:body]
41
+ )
42
+ result = OutpunchRails.success_response(response_data)
43
+
44
+ run_hook(:after_proxy, service_name, service_path, payload, result: result)
45
+
46
+ render_tunnel_result(result)
47
+ rescue Timeout::Error
48
+ render_error(504, "Tunnel timeout for service '#{params[:service_name]}'")
49
+ rescue => e
50
+ render_error(502, e.message)
51
+ end
52
+
53
+ private
54
+
55
+ def run_hook(type, service_name, path, payload, extra = {})
56
+ hooks = OutpunchRails.configuration.hooks
57
+ return unless hooks
58
+
59
+ case type
60
+ when :before_proxy
61
+ hooks.before_proxy(service_name: service_name, path: path, payload: payload, request: request)
62
+ when :after_proxy
63
+ hooks.after_proxy(service_name: service_name, path: path, payload: payload, request: request, **extra)
64
+ end
65
+ end
66
+
67
+ def render_tunnel_result(result)
68
+ if result[:body_encoding] == "base64"
69
+ content_disposition = result[:headers]["content-disposition"] || "attachment"
70
+ disposition = content_disposition.start_with?("attachment") ? "attachment" : "inline"
71
+ filename = content_disposition[/filename="?([^";]+)"?/, 1]
72
+
73
+ send_data result[:body],
74
+ type: result[:headers]["content-type"] || "application/octet-stream",
75
+ disposition: disposition,
76
+ filename: filename,
77
+ status: result[:status]
78
+ else
79
+ result[:headers]&.each { |key, value| response.set_header(key, value) }
80
+ render body: result[:body], status: result[:status]
81
+ end
82
+ end
83
+
84
+ def render_error(status, message)
85
+ result = OutpunchRails.error_response(status, message)
86
+ render json: JSON.parse(result[:body]), status: result[:status]
87
+ end
88
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Outpunch
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ initializer "outpunch_rails.insert_middleware" do |app|
7
+ app.middleware.insert_before 0, Outpunch::Rack::Middleware
8
+ end
9
+
10
+ initializer "outpunch_rails.routes" do
11
+ prefix = OutpunchRails.configuration.route_prefix
12
+ ::Rails.application.routes.prepend do
13
+ match "#{prefix}/:service_name/*service_path", to: "outpunch/tunnel#proxy", via: :all
14
+ match "#{prefix}/:service_name", to: "outpunch/tunnel#proxy", via: :all
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Outpunch
4
+ module Rails
5
+ VERSION = "0.1.2"
6
+ end
7
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "outpunch/rack"
4
+ require "outpunch/rails/version"
5
+ require "outpunch/rails/engine"
6
+
7
+ # OutpunchRails — thin Rails wrapper around OutpunchRack.
8
+ #
9
+ # Usage in config/initializers/outpunch.rb:
10
+ #
11
+ # OutpunchRails.configure do |config|
12
+ # config.secret = ENV['MORDOR_TUNNEL_SECRET']
13
+ # config.timeout = 60
14
+ # end
15
+ #
16
+ module OutpunchRails
17
+ class << self
18
+ def configure(&block)
19
+ Outpunch::Rack.configure(&block)
20
+ end
21
+
22
+ def configuration
23
+ Outpunch::Rack.configuration
24
+ end
25
+
26
+ def hooks
27
+ Outpunch::Rack.configuration.hooks
28
+ end
29
+
30
+ def server
31
+ Outpunch::Rack.server
32
+ end
33
+
34
+ # Convenience delegates so application code only needs to reference OutpunchRails.
35
+
36
+ def connected?(service_name)
37
+ Outpunch::Rack.connected?(service_name)
38
+ end
39
+
40
+ def handle_request(**kwargs)
41
+ Outpunch::Rack.handle_request(**kwargs)
42
+ end
43
+
44
+ def success_response(data)
45
+ Outpunch::Rack.success_response(data)
46
+ end
47
+
48
+ def error_response(status, message)
49
+ Outpunch::Rack.error_response(status, message)
50
+ end
51
+
52
+ def extract_proxy_headers(headers)
53
+ Outpunch::Rack.extract_proxy_headers(headers)
54
+ end
55
+ end
56
+ end
data/lib/outpunch.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "outpunch/rails"
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: outpunch-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - TechyCorp
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-04-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: outpunch-rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: railties
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '7.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '7.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '6.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '6.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '7.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '7.0'
69
+ description:
70
+ email:
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - app/controllers/outpunch/tunnel_controller.rb
76
+ - lib/outpunch.rb
77
+ - lib/outpunch/rails.rb
78
+ - lib/outpunch/rails/engine.rb
79
+ - lib/outpunch/rails/version.rb
80
+ homepage:
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '3.1'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubygems_version: 3.5.22
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Rails Engine adapter for the outpunch reverse WebSocket tunnel
103
+ test_files: []