Skip to content

Conversation

@DougReeder
Copy link
Member

@DougReeder DougReeder commented Dec 9, 2025

What?

Adds support for open-source Icosa Gallery, including redirects for CORS requests

Cleaned-up version of #723

Why?

Google Poly was shut down years ago, but Icosa Gallery makes the models there available via the Internet Archive. Unfortunately, one or more HTTP redirects is required to access the models on archive.org, and the existing reticulum code to make CORS requests for the Hubs client did not support that. Efforts to change parameters to enable support for redirects using the existing code were not successful, so LLM-generated code was added to manually follow redirects. That code is used by all CORS requests.

Icosa Gallery also allows new model submissions, which work without support for redirects.

Examples

image

How to test

  1. Install this and Replacing google poly integration with Icosa integration Spoke#1301
  2. Edit a scene, adding a model stored on backblaze.com, such as "Mr. Froggie" by Gregor Pfingstl. Observe that the model is loaded into Spoke and can be moved and resized.
  3. Add a model stored on archive.org, such as "Knife" or "Cat" by Google. Observe that the model is loaded into Spoke and can be moved and resized.
  4. Publish the scene
  5. Navigate to and join a room using the scene
  6. Observe that the two models from Icosa are properly loaded and displayed

Documentation of functionality

Should be functional identical to Sketchfab.

Hubs-Foundation/hubs-docs#235 will contain actual hubs-docs changes

Limitations

Presumably does not support pasting an Icosa Gallery page into Hubs.
When the Hubs client is updated to support Icosa Gallery, a separate reticulum PR will be required to support that.

Alternatives considered

It's likely a skilled Elixir programmer could implement redirects using less code.

Open questions

Additional details or related context

This PR is needed by the Spoke commit: Hubs-Foundation/Spoke#1301

andybak and others added 30 commits August 30, 2024 10:30
Note: The code for this commit was generated by one or more AI tools: probably Github Copilot (GPT-5 Mini?) and potentially also Claude Code CLI (Sonnet 4.5?).
By @DougReeder
Why: Icosa doesn't have the rate limits that YouTube has.
The original comment contained useful context.
Why: to match pretty-printing standard
# Conflicts:
#	lib/ret/media_search.ex
#	lib/ret_web/controllers/page_controller.ex
…atted'

Why: Ensures dependencies are up-to-date, which the caching cannot.
Why: to eliminate code smell and ease debugging
@DougReeder
Copy link
Member Author

DougReeder commented Dec 9, 2025

We'd like to fix the "Server authenticity is not verified since certificate path validation is not enabled" in the reticulum log, but we don't yet know how. The preserve_host_header option is definitely not needed — the Host: header points to the Hubs instance, and the CORS-requiring request is going to the upstream server. The following config

          ReverseProxyPlug.init(
            upstream: url,
            allowed_origins: allowed_origins,
            proxy_url: "#{cors_scheme}://#{cors_host}:#{cors_port}",
            # We need to force the host
            # used for ssl verification here so that the connection isn't rejected.
            # Note that we have to convert the authority to a charlist, since this uses Erlang's `ssl` module
            # internally, which expects a charlist.
            client_options: [
              ssl: [
                {:server_name_indication, to_charlist(authority)},
                {:versions, [:"tlsv1.2", :"tlsv1.3"]},
                {:verify, :verify_peer},
#                {:partial_chain, :auto},   # not available in our old version
#                {:log_level, :debug},   # breaks
                {:cacertfile, :certifi.cacertfile()},
                {:verify_fun, &:ssl_verify_hostname.verify_fun/3},
                {:customize_hostname_check, [
                  match_fun: :public_key.pkix_verify_hostname_match_fun(:https)]}
              ]
            ],
            error_callback: fn error -> Logger.error("CORS-proxy error: #{inspect(error)}") end
          )

... appears to cover all the requirements to authenticate the host, but the message still appears. It's not impossible that the old version of certifi used doesn't have recent enough certificates. certifi can't be updated until related packages are updated.

Changing {:cacertfile, :certifi.cacertfile()}, to {:cacerts, :public_key.cacerts_get()}, likewise fails. My research appeared to indicate the the system certs were present in the reticulum container, but it's not impossible that they aren't, or cacerts_get() can't access them for some reason.

However, the error_callback does work, and gives additional info on failures, so we'll add that in.

An image you can install on your instance is available from https://hub.docker.com/ : dougreeder/reticulum:icosa-cleanup-2-2025-12-10-20-15

Why: returns potentially useful info on failures
Copy link
Member

@Exairnous Exairnous left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The merge/cleanup seems good and everything appears functional. As to the server authenticity issue, it feels to me like the path validation stuff isn't being applied to the right place, but I tried putting it in HTTPoison.head and retry_get_until_success in resolve_non_video but that didn't change the warning either.

While adding a new warning isn't ideal, since it appears everything works, and otherwise the code seems fine, I'm okay with merging this.

@Exairnous Exairnous merged commit 38858cc into master Dec 17, 2025
5 of 19 checks passed
@Exairnous Exairnous deleted the icosa-cleanup-2 branch December 17, 2025 04:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants