diff --git a/README.md b/README.md index cfa43ca..af762fb 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > Self-sovereign **XR Experiences** for teams & organisations, powered by FOSS ♥ -![](https://i.imgur.com/0NA7MMg.png) +![](xrforge.jpg) * View [index.html](https://coderofsalvation.codeberg.page/xrforge) for the official docs * Click [here](manyfold/README.md) for backend-installation instructions. @@ -10,6 +10,7 @@ Powered by: * [NIX](https://nixos.org) for reproducibility and reliability +* [JanusWeb](https://github.com/jbaicoianu/janusweb) for browsing JML / JanusXR immersive web-layer * [XR Fragments](https://xrfragment.org) for interoperability between XR experiences * [Manyfold](https://manyfold.app) for curating & collaborating XR experiences * [Godot](https://godot.org) & [Blender](https://blender.org) for editing XR experiences diff --git a/manyfold/test/rclone.sh b/manyfold/test/10-rclone.sh similarity index 100% rename from manyfold/test/rclone.sh rename to manyfold/test/10-rclone.sh diff --git a/manyfold/root/hook.d/boot/runtests.sh b/manyfold/test/runtests.sh similarity index 100% rename from manyfold/root/hook.d/boot/runtests.sh rename to manyfold/test/runtests.sh diff --git a/manyfold/usr/src/app/controllers/cors_proxy.rb b/manyfold/usr/src/app/controllers/cors_proxy.rb deleted file mode 100644 index 735159d..0000000 --- a/manyfold/usr/src/app/controllers/cors_proxy.rb +++ /dev/null @@ -1,101 +0,0 @@ -require 'net/http' -require 'uri' - -# Defines the controller logic for the CORS proxy endpoint. -# It handles all HTTP methods and forwards the request to the target URL -# provided as a path segment (e.g., /cors/https://example.com/data?q=1). -class CorsProxyController < ApplicationController - # Skip CSRF protection for this action, as it's intended to handle external requests - # that might not have a valid CSRF token. - skip_before_action :verify_authenticity_token - - # The main proxy action. - def proxy - # Assuming the route is configured as: match '/cors/*target_url_segment', ... - target_url_segment = params[:target_url_segment] - - # Reconstruct the full target URL. The globbing parameter captures the base path - # (e.g., "https://example.com/data"), and we re-attach the raw query string - # (e.g., "?q=1¶m=2") that the Rails router parsed separately. - query_string = request.query_string.present? ? "?#{request.query_string}" : "" - target_url = target_url_segment.to_s + query_string - - # 1. Input Validation - unless target_url.present? - return render json: { error: 'Target URL is required as a path segment after /cors/.' }, status: :bad_request - end - - begin - uri = URI.parse(target_url) - # Security check: Only allow standard HTTP/HTTPS schemes. - unless ['http', 'https'].include?(uri.scheme&.downcase) - return render json: { error: 'Invalid URL scheme. Only http and https are supported.' }, status: :bad_request - end - rescue URI::InvalidURIError - return render json: { error: 'Invalid URL format.' }, status: :bad_request - end - - # 2. Determine the appropriate Net::HTTP request class based on the incoming method - request_class = case request.method - when 'GET' then Net::HTTP::Get - when 'POST' then Net::HTTP::Post - when 'PUT' then Net::HTTP::Put - when 'DELETE' then Net::HTTP::Delete - when 'PATCH' then Net::HTTP::Patch - when 'HEAD' then Net::HTTP::Head - else - return render json: { error: "Unsupported HTTP method: #{request.method}" }, status: :method_not_allowed - end - - # 3. Initialize the outgoing request - # Use uri.request_uri which includes the path and query parameters of the target - outgoing_request = request_class.new(uri.request_uri) - - # 4. Copy relevant headers from the incoming request to the outgoing request - # We explicitly skip certain headers that are managed by the HTTP client or should not be proxied. - request.headers.each do |key, value| - header_key = key.sub(/^HTTP_/, '').underscore.dasherize.split('-').map(&:capitalize).join('-') - - # Skip internal/sensitive/managed headers - next if ['Host', 'Content-Length', 'Connection', 'Transfer-Encoding', 'X-Request-Id', 'X-Forwarded-For'].include?(header_key) - next if header_key.start_with?('X-') # Generally skip custom Rails internal headers - - # Pass all other headers (including Authorization, Content-Type, etc.) - outgoing_request[header_key] = value - end - - # 5. Handle request body for methods that carry a payload - if request.body.present? && !['GET', 'HEAD'].include?(request.method) - request.body.rewind # Ensure we read from the beginning of the stream - outgoing_request.body = request.body.read - end - - # 6. Execute the request - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = (uri.scheme == 'https') - - # Set reasonable timeouts - http.read_timeout = 15 - http.open_timeout = 5 - - target_response = http.request(outgoing_request) - - # 7. Proxy the response back to the client - # Copy headers from the target response to the client response - target_response.each_header do |key, value| - # Skip internal headers but ensure CORS headers (Access-Control-*) are passed - next if ['Transfer-Encoding', 'Connection', 'Content-Length'].include?(key.downcase) - response.headers[key] = value - end - - # Set status and send back the body and content type - render plain: target_response.body, - status: target_response.code.to_i, - content_type: target_response['Content-Type'] || 'text/plain' - - rescue StandardError => e - # Catch network errors (DNS failures, timeouts, etc.) - Rails.logger.error "CORS Proxy Error: #{e.class}: #{e.message}" - render json: { error: "Proxy request failed due to a server error: #{e.message}" }, status: :internal_server_error - end -end diff --git a/xrforge.jpg b/xrforge.jpg new file mode 100644 index 0000000..1ae31f4 Binary files /dev/null and b/xrforge.jpg differ