Skip to main content

Using SCORM modules in multi-server deployments offer a number of challenges. A full list of scenarios and solutions can be found in this document.

Basically a SCORM component is a set of files packed in a zip file that includes all assets to display and control its behaviour. This file is uploaded in Studio, stored and unpacked in the default file storage and displayed in the LMS from there.

SCORM components are inserted in the LMS as an iframe by the SCORM Xblock plugin. When the SCORM XBlock is configured as graded, it will call an API located at the parent window to communicate the result of the activity to the LMS. When the SCORM assets are served from an origin different than the url of the LMS, this will usually fail due to cross-origin restrictions imposed by the browser.

Scalable LMS implementations require that the file storage is located outside of the LMS and CMS workloads, typically in an object storage service like AWS S3. In this scenario the standard configuration may allow SCORM blocks to be displayed, but the grading function will certainly fail.

This plugin addresses this issue to make graded SCORM XBlocks work.

https://img.shields.io/badge/linting-pylint-yellowgreen

How it works

This plugin will add a reverse proxy statement to the lms matcher in the Caddyfile, so that requests to LMS_BASE/scorm/ will be proxied to the S3 endpoint corresponding to the bucket. This will cause that all SCORM assets will be served from the same origin url as the LMS. The effect is that the scorm components will be able to access the api located at the parent window.

To have the

Installation

pip install tutor-contrib-s3scorm

This release targets Tutor 21 / Open edX Ulmo.

Configuration

This plugin integrates with tutor-contrib-s3. By default, S3SCORM_BUCKET inherits the value of S3_STORAGE_BUCKET if that setting is defined. You only need to set S3SCORM_BUCKET explicitly when SCORM files live in a different bucket.

These parameters are used by the plugin:

  • S3SCORM_BUCKET (optional): name of the bucket (e.g., openedx-my-file-bucket). Defaults to S3_STORAGE_BUCKET if that variable is defined.

  • S3SCORM_ENDPOINT (optional): S3 endpoint. E.g., s3.us-east-1.amazonaws.com. If unset, the plugin falls back to S3_HOST and S3_PORT, then s3.<S3_REGION>.amazonaws.com.

  • S3SCORM_PATH (optional): Path inside the bucket where the ‘scorm’ directory is located. Include a leading slash and no trailing slash (e.g. “/openedx/media”). Defaults to empty path (root of the bucket).

  • S3SCORM_URL_STYLE (optional): How the upstream bucket is addressed. Use virtual for <bucket>.<endpoint> and path for <endpoint>/<bucket>. Defaults to virtual.

Optional parameters:

  • S3SCORM_USE_SSL: Default true.

When S3SCORM_PATH is set, the proxy preserves the public /scorm/... URL and rewrites the upstream request to <S3SCORM_PATH>/scorm/... inside the bucket. The upstream endpoint is resolved in this order: S3SCORM_ENDPOINT, S3_HOST plus S3_PORT if set, and finally s3.<S3_REGION>.amazonaws.com. When S3SCORM_URL_STYLE is set to path, the bucket is placed in the upstream URI path instead of the hostname.

Performance: caching, compression and CDN

By default, the SCORM XBlock itself never generates /scorm/... URLs at all: it links to its own .../handler/assets_proxy/... endpoint, which streams every asset through the LMS/ CMS Django process regardless of storage backend. That means the /scorm/* Caddy route this plugin installs sits unused until the xblock is told to link to storage URLs directly instead — which only happens once S3SCORM_CLOUDFRONT_DOMAIN is set (see below). Once that switch is flipped, every SCORM asset request is proxied by Caddy straight to S3 (or the CDN in front of it) on each and every request, with no caching or compression unless configured. For courses with SCORM packages containing video, audio or many images this adds up: assets are re-fetched in full on every page load, and text assets (JS/HTML/JSON) are sent uncompressed. The following settings address this without changing how access is controlled — the LMS/CMS still decide who ever reaches a page that embeds the SCORM block in the first place, since these XBlocks are only rendered on pages already gated by the standard enrollment/authentication checks.

  • S3SCORM_CACHE_MAX_AGE (optional, default 86400): adds a Cache-Control: public, max-age=<value>, immutable header to SCORM asset responses so browsers stop re-downloading unchanged assets on every visit. Set to 0 to disable the header entirely (previous behavior). Because SCORM asset paths are keyed by block usage id and are typically overwritten in place when a course team re-uploads a package, keep this conservative unless your asset paths are otherwise versioned; raise it (e.g. to 31536000 for a year) once you’re confident republishing isn’t a concern, or your pipeline invalidates/versions asset paths on republish.

  • S3SCORM_COMPRESS (optional, default true): has Caddy transparently compress (zstd/gzip) text-based SCORM assets (the SCORM package’s own JS/HTML/CSS/JSON) on the fly. Binary assets such as video and images are left as-is. Set to false to disable.

  • S3SCORM_CLOUDFRONT_DOMAIN (optional, default empty): the domain name of a CDN distribution (e.g. a CloudFront distribution) that has the SCORM bucket configured as its origin. When set, Caddy proxies /scorm/* to this domain instead of talking to S3 directly, so requests benefit from edge caching, edge compression and reduced load on the origin bucket — while assets are still served from the same origin as the LMS/CMS, so the SCORM grading postMessage API continues to work exactly as described above. When this is set, S3SCORM_ENDPOINT/S3SCORM_URL_STYLE/bucket-address settings are ignored for upstream addressing (S3SCORM_PATH still applies if your distribution’s origin path mirrors the bucket layout).

    Setting S3SCORM_CLOUDFRONT_DOMAIN also switches XBLOCK_SETTINGS["ScormXBlock"] ["PROXY_ASSETS_LMS"] to False, which is what actually makes the xblock link to /scorm/... storage URLs instead of its built-in assets_proxy handler in the first place — without a CDN configured, this plugin leaves PROXY_ASSETS_LMS untouched (its default, True) and assets keep flowing through Django as before. In other words, the caching/compression settings above only take effect once a CDN domain is set here.

Example, adding a CDN and a one-year cache lifetime on top of the base configuration:

tutor config save \
    --set S3SCORM_CLOUDFRONT_DOMAIN=d123456abcdef8.cloudfront.net \
    --set S3SCORM_CACHE_MAX_AGE=31536000

Usage

tutor plugins enable s3scorm

License

This software is licensed under the terms of the AGPLv3.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tutor_contrib_s3scorm-21.2.0.tar.gz (7.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tutor_contrib_s3scorm-21.2.0-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file tutor_contrib_s3scorm-21.2.0.tar.gz.

File metadata

  • Download URL: tutor_contrib_s3scorm-21.2.0.tar.gz
  • Upload date:
  • Size: 7.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for tutor_contrib_s3scorm-21.2.0.tar.gz
Algorithm Hash digest
SHA256 cd0995f3bc81238a2ce34f961afc832adfa1ae17cfa8ddb3ebe3ea136ade6c8f
MD5 c87696d8d8cee259ff4c2b963c67fed6
BLAKE2b-256 28512c0b6c363a0692f08dea618b42feff40e21935f5ff8abc7cd6c23a4d2a44

See more details on using hashes here.

Provenance

The following attestation bundles were made for tutor_contrib_s3scorm-21.2.0.tar.gz:

Publisher: publish.yml on aulasneo/tutor-contrib-s3scorm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tutor_contrib_s3scorm-21.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for tutor_contrib_s3scorm-21.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 76d8d792dd44c8fc57a48407a51a59df773ec9dd7ec9873717f8d195bf1d7674
MD5 db4c32beb6ace19e52615bb816cc868d
BLAKE2b-256 b376be300fe3c1acfb28cf4b6e70e51db49c528a02cf9d1946c6f77b657d47d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for tutor_contrib_s3scorm-21.2.0-py3-none-any.whl:

Publisher: publish.yml on aulasneo/tutor-contrib-s3scorm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

21.2.0 This release

2 files

21.1.1

2 files

21.1.0

2 files

21.0.0

2 files

20.0.0

2 files

19.0.0

2 files

18.0.0

2 files

17.0.0

2 files

16.1.1

2 files

16.1.0

2 files

16.0.0

2 files

15.1.1

2 files

15.1.0

2 files

15.0.1

2 files

14.1.1

2 files

14.1.0

2 files

14.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page