embed-page icon indicating copy to clipboard operation
embed-page copied to clipboard

Diary - ways for fetching 3rd party scripts

Open sashafirsov opened this issue 7 years ago • 14 comments

In order to make the EPA component alive its JS need to be run in insulated context and with insulated browser APIs. It is possible via

  • IFRAME , but it will need a layer to run EPA integration API within embedded page
  • closure with wrapped window, document and other browser APIs to insulate related data layers from page itself and other EPA instances.

The thread bellow reflects the evolution of thinking around subject and ways to implement.

sashafirsov avatar Jan 30 '18 04:01 sashafirsov

IFRAME needs the EPA API implementation on container embeddable side along with host-child frame communication.

  • same-origin gives direct messaging API
  • cross-domain The frame security restrictions prevent direct messaging leaving just a
    • server side peering
    • WebSockets/WebRTC broadcasting promise peer-to-peer model. Complains are on complexity side.

Disregarding of cross-frame communication layer there is need for JS injection within component content - add a single script (perhaps hosted on APE CDN). For generic 3rd party use it would be possible via EPA API injection proxy.

EPA API injection proxy is relatively simple. All it requires is to add a single script into app html taken from 3rd party site.

IFRAME in comparison with closure insulation seems to be stronger. But would it survive the IFRAME UX limitations? Resizing of container, zoom and scroll inside, etc. Dom embedding does not have UX side effects, but needs closure insulation developed to the level of all APIs used by app.

sashafirsov avatar Jan 30 '18 05:01 sashafirsov

closure insulation.

The biggest challenge resides on 3rd party JS retrieval and running in APE component closure scope.

CORS restrictions

are not applicable if script is included via SCRIPT tag, but it prevents to use a custom scope for container objects insulation. In order to retrieve script via ajax the app should enable

Access-Control-Allow-Origin:* Access-Control-Allow-Methods:GET HTTPS hosted page would restrict the contained apps to use HTTPS scripts.

The absence or CORS headers or serving the app from HTTP would break ajax. The way around would be the proxy which will elevate http to https and inject CORS headers.

fetch() and service workers

unfortunately could be used only when container and apps are within same-origin. The service worker from 3rd party domain, scope to 3rd party domain unfortunately prohibited by current implementations. The fetch(... { mode: 'no-cors'}) does not help with another domain.

sashafirsov avatar Jan 30 '18 06:01 sashafirsov

The first part of EPA API appear to be about JS URLs substitution rules. The embedded content JS needs to be served with CORS. If those are not given the proxy on host page will give such ability.

The array of RegEx with replacement expression or function would do the job.

sashafirsov avatar Jan 30 '18 15:01 sashafirsov

'redirects' URLs mapping

For sites which having the trouble with setting CORS headers on SCRIPT urls the proxy which will inject CORS headers will be the solution.

`<embed-page src="page-with-js.html" redirects=' [ { "from": "https://www.cahousefinder.com/listings-search/", "to":"/listings-search/"} , { "from": "https://www.cahousefinder.com/wp-includes/", "to":"/wp-includes/"} , { "from": "https://www.cahousefinder.com/wp-content/", "to":"/wp-content/"} ]'

`

The redirects attribute/property with JSON array of URL prefix from and to With a thought to be in line with current URL mapping proposals on WHATWG. Those are quite popular in AMD and other module loaders.

While at the moment mapping works just by prefix substitution, in the future it could be upgraded with RegEx or function for URL recognition and replacement.

Security considerations.

The JS insulation EPA module is using redirects mapping when loading scripts. Scripts do not meant to be altered and passed via proxy only to inject the CORS headers. To assure the JS integrity even passed via proxy, the SCRIPT in host page could use integrity arrtibute. EPA should validate the attribute if available.

In the sample above the https absolute URL is replaces with relative to host page URL. Which means the owner of page is responsible for altering the JS content. Should substitution to relative URL be enforced pattern or it is OK to replace one host with another? The CDN or sub-domain of same owner are quite valid cases, meaning the restriction could be harmful for valid use.

sashafirsov avatar Feb 02 '18 05:02 sashafirsov

Samples of embedded content

For now two extreme cases:

  • included into demo page. As served from same server, no issues on cross-origin, https, cors. It uses just one method of document as JS insulation show case.
  • real-estate site. Most complex case with multiple 3rd party scripts, served over HTTPS from own domain.

Of course the 100% coverage of most complex case most likely will not be reached. Perhaps the clean sample of EPA-compliant site should be the 3rd option.

  • ApiFusion.com could be the one.

sashafirsov avatar Feb 02 '18 06:02 sashafirsov

Server-side vs client side injection

Even the IFRAME approach still would need the JS injection for embedded page. Which could be achieved by altering the html header

sashafirsov avatar Feb 04 '18 00:02 sashafirsov

Copyright vs embedding customization conflict

From very beginning of EPA idea the legal conflict of interests between container and embedded application has bothered me. To present the microapp coherently with page content EPA Container would need to modify UX including UI and behavior. Of course, it goes against interest of EPA microapp vendor: giving extra burden on support, reusing and altering the copyrighted content from legal side, etc. Since the EPA Microapp by definition hoses own content into 3rd party app and serves same content as microservice the legal scope should not be much different and already accepted on industry level (refs TBD). The embedding protocol should give to Microapp vendor a set of flags that instructs:

  • The content will be embedded into EPA Container
  • API rev.#
  • Microapp authorization (API Key, etc.)
  • CMS Embedding mode ( as icon, tile, list element, list, preview, full page, full screen, site-page-instance config)

The first flag along with EPA API version serves as agreement to provide the content for embedding. API version states the protocol; authorization will make sure the content is served under signed contract enforced by Microapp vendor; CMS embedding mode is necessary for unification of embedding and keeping the compatibility across multiple EPA Container vendors. The unification in general is essential part of EPA idea as it solves the current development support burden for multiple content vendors.

sashafirsov avatar Feb 04 '18 17:02 sashafirsov

responsive IFRAME

As an option for embedding EPA. search

The postMessage method safely enables cross-origin communication between component and container. The EPA should define the protocol of identifying the instances and their relations. As postMessage is URL-based (targetOrigin), that should be addressed in unified URL '*' is not acceptable.

sashafirsov avatar Feb 04 '18 19:02 sashafirsov

While the demo page has necessary code for proof concept, it should be visually presented.

  • include the code sniplet and links to source where the code is used

sashafirsov avatar Feb 10 '18 19:02 sashafirsov

The demo should highlight the insulation aspect. Hence provide

  • demo of multiple instances using the same code which do not affect each other
  • demo of same code not affecting the host page, use same elements in host page
  • demo of host code not affecting the APE components

For clarity include the demo page in IFRAME next to its sources.

sashafirsov avatar Feb 10 '18 19:02 sashafirsov

TBD iron-ajax as request API.

PROS: no need to implement complex API and binding

CONS: bring Polymer API dependency

The <iron-ajax last-response="{{variable}}"> bounds response to variable and the content could be delivered as <embed-page>[[variable]]<embed-page>

sashafirsov avatar Feb 19 '18 03:02 sashafirsov

browsingContext is the main subject to substitute in embed-page. Figuring out the available via JS capabilities.

Use of plugin could be the next step for in-browser implementation acceptance.

sashafirsov avatar Feb 25 '18 16:02 sashafirsov

seamless iframe attribute from one side is not considered for browser implementation anymore, and from another keeps links/form targets in parent browsing context which goes against the micro application needs.

sashafirsov avatar Feb 26 '18 07:02 sashafirsov

One of ways to handle browsing context change: use hidden iframe as a target for all A links and forms. On loaded or changed(?) event get its URL, and set embed-page src attribute to this url. IFRAME should be removed once URL is acquired.

The IFRAME content could have beforeunload handler to detect the intent and prevent URL load.

Q. How to get URL from beforeunload handler ?

  • setup click/tap/beforesubmit handlers and preserve url
  • magic to get URL from iframe attribute

Tricks to be evaluated:

  • on activation capturing phase prefix the URL with hash '#'. Which will

    • trigger the iframe url but its content could post the URL back to container, or
    • onload event on container itself.
  • is there "beforeload" event on iframe?

sashafirsov avatar Feb 26 '18 08:02 sashafirsov