Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Absolute (root relative) paths do not resolve to www folder, instead point to C:\... #398

Closed
3 tasks done
FEA5T opened this issue Oct 25, 2021 · 3 comments
Closed
3 tasks done

Comments

@FEA5T
Copy link

FEA5T commented Oct 25, 2021

Bug Report

Absolute (root relative) paths do not resolve to www folder, instead point to C:... causing failed requests in the webapp.

Problem

Webapps that run normally on a webserver cannot be ported over to cordova because all absolute (root relative) paths fail.

What is expected to happen?

Absolute (root relative) paths should resolve to www folder which is consistent across iOS, android, windows, etc rather than pointing to an inconsistent drive root where the path differs.

What does actually happen?

Absolute (root relative) paths in your web app resolve to the drive root causing requests to fail that would succeed in any other server environment.

Information

Cordova behaves inconsistently and breaks a core principle of its own product: that you should be able to package and run a web app without rewriting it natively.

Command or Code

All absolute (root relative) paths in html and JS UI code should resolve to the www folder. At a bare minimum there should be a configuration as to where these paths point, so that the www folder can be targeted. There are many reasons for this:

  1. Consistency: an app that runs in browser off a webserver should be portable to cordova with minimal changes.
  2. Sandboxing: a web UI should not be concerned with, or be knowledgeable of a devices root drives and folder structure, instead it should only be knowledgeable of it's own root application folder.
  3. SPA necessity: Relative paths do not work in a modern web UI with a router (take for example react or a vue app with vue-router): often times the route that the application is at will change, invalidating relative paths inside reusable component code. If a component relies on path "components/tabs.vue" and the browser is at path "www.mydomain.com/" the component will load, but if the browser is at "www.mydomain.com/movies/1234" then it will try to load "www.mydomain.com/movies/1234/components/tabs.vue" which will fail. Absolute (root relative) paths are necessary to prevent these errors and cordova should respect standards and point absolute paths at the www root folder.

Environment, Platform, Device

On all environments/devices.

There are many questions/complaints about this behavior and there is no known workaround, only suggestions to use relative paths (which do not work/are not compatible with SPA routers).

Version information

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above
@breautek
Copy link
Contributor

Cordova is just a packaging tool, it doesn't really implement any URL loading scheme, or the browser view itself. It's standard browser behaviour (including in traditional web server apps) that if you have a url prefixed with with a forward slash (/) then the URL should be treated as an absolute URL. We cannot change what the "root" directory is. However if you control the machines that you're deploying the cordova apps too, you might be able to chroot the process.

If you want relative URLs, then you should not prefix with a forward slash. The urls will then be relative to the document itself, generally the path of where the HTML file resides. e.g. use <script src="app.js" /> instead of <script src="/app.js">. It's recommended to use relative paths anyway to remain cross-platform as the paths for each platform is different.

that you should be able to package and run a web app without rewriting it natively.

I don't think Cordova claims at any point that you can package up any web app without rewriting it. Cordova does claim that you can package up web apps so that you can deploy native apps with the majority of your app code being ran in the system provided webview, then deploy it via different platforms using largely the same codebase. It does not mean you can take any traditional web application hosted on a web server and package it up and it will work as is. There are differences between traditional web hosted environments and native apps with embedded web content.

SPA does work in Cordova environments. but for routing you can't use "clean urls" which is often sought after in traditional web development for the purposes of clean looking URLS in the address bar and/or SEO purposes. In Cordova environments you have to use hash-based routing, because there is no intermediate web server that sits between your web app your source files that can be used to manipulate the routing.

I'm closing this because changing what the root directory is - is not something Cordova can feasibly do.

@FEA5T
Copy link
Author

FEA5T commented Oct 26, 2021

First of all thank you for such a detailed response. It does however leave me with even more questions:

Cordova is just a packaging tool, it doesn't really implement any URL loading scheme

Relative url's are translated to reference the 'www' folder, the path "/" is translated to return '/index.html', 'http://' is translated to 'file://' schema, and absolute url's do prefix a drive letter...so from this I assume there is some url translation going on somewhere by something, so I am wondering: 1) is it cordova that is handling this transformation, or some dependency, and if so, where is it happening, and is this code cross-platform or unique code to each platform? It seems to me this is the point where I would need to make necessary modifications so that cordova can behave consistently with a webserver.

It's standard browser behaviour (including in traditional web server apps) that if you have a url prefixed with with a forward slash (/) then the URL should be treated as an absolute URL. We cannot change what the "root" directory is.

While this is true, my point is that:
Absolute URL's typically point towards: the application root (not the devices root) - (as all webservers do)
Relative URL's typically point towards: the application root (with the browser path appended).
I am not suggesting to change the root directory of the process, simply translate absolute URL's the way relative URL's are translated today (without appending browser path): to reference the 'www' folder. This circles back to my question above, how/who/where is the translation happening?

I don't think Cordova claims at any point that you can package up any web app without rewriting it. Cordova does claim that you can package up web apps so that you can deploy native apps with the majority of your app code being ran in the system provided webview, then deploy it via different platforms using largely the same codebase. It does not mean you can take any traditional web application hosted on a web server and package it up and it will work as is. There are differences between traditional web hosted environments and native apps with embedded web content.

I am a bit puzzled by this. I don't mean to come off as rude, I do appreciate your perspective, however, cordova's main use case is packaging web apps into cross platform native apps. It seems to me the core functionality here is loading html/js/css from a device directly and rendering it in a webview. Obviously there are environmental differences such as how api calls are made or advanced browser api's that may differ, but (ignoring routing) why is the most core functionality (loading an html file with 1 image) not consistent with the browser and the way web apps are served? When I drop my codebase into cordova, basic file references break because they are absolute (which half the internet is built on). I am truly baffled because this is the most basic functionality cordova offers, and honestly, maybe I am naïve here, but this seems like a major oversight in design/principles (not valuing consistency and simplicity). It is not a good look for cordova when I drop in a basic app and it wont run because of file references that do work in every major browser (without routing). Is there a valid use case for accessing the device root when the folder structure isn't consistent cross-platform?

SPA does work in Cordova environments. but for routing you can't use "clean urls" which is often sought after in traditional web development for the purposes of clean looking URLS in the address bar and/or SEO purposes. In Cordova environments you have to use hash-based routing, because there is no intermediate web server that sits between your web app your source files that can be used to manipulate the routing.

I also ran into this issue. This is another area where route translation and file response handling would allow clean URL routing, and again just comes down to what layer of the code is handling routes and performing file reads and returning files to the webview. Is there a cross platform piece of code on the device side that is handling url requests and determining which file to load (or ask the device api to read the file)? If so, what is that entry point?

Lastly, do you know of any plugins/competing technologies that may handle route translation on the device side? Seems to me this would easily enable absolute refs + clean urls + possibly api proxying as well.

@breautek
Copy link
Contributor

breautek commented Oct 26, 2021

why is the most core functionality (loading an html file with 1 image) not consistent with the browser and the way web apps are served?

It is consistent. Cordova doesn't handle file paths, it just tells the underlying webview what file path to load. If you're loading a filepath from the file:// protocol then the "root" directory is always relative to the filesystem, which in windows case, it's the drive's root. If you wanted to load an image file, you'd either need the full absolute path to that image, or a relative path relative to the HTML document.

maybe I am naïve here, but this seems like a major oversight in design/principles

I'll admit that I'm not all that familiar with the windows platform specifically. iOS platform implements an iOS-specific API called WKURLSchemeHandler, and our android platform implements something called WebViewAssetLoader, which essentially makes the web app origin app://localhost and https://localhost respectfully, which is sounds like what you're asking for the windows platform (because the absolute paths will be relative to the origin https://localhost), but afaik Windows underlying webview does not provide any equivalent API.

I actually had a brief discussion on routing when talking about the Android platform when the WebViewAssetLoader was implemented but it was decided that URL rewriting/routing is an application detail and not something Cordova should be responsible for.

cordova's main use case is packaging web apps into cross platform native apps.

Yes, meaning that you can use web technologies to write a functional application and for it to be deployed through the native app stores. It doesn't mean an app can simply be copied from a hosted web server into a cordova container and for it to work out the box. For simple applications this may work, but for most applications this you probably won't get very far without writing many cordova-app specific code.

Lastly, do you know of any plugins/competing technologies that may handle route translation on the device side?

No I'm not aware of any plugins. if you use the History API to fake the url path for a particular route, if the webview tries to reload that page it will fail. That's why hash-bash routing is recommended for Cordova apps, so the filepath can remain as your main/physical index.html file. There is no "server side logic" when it comes to serving HTML in cordova apps.

Last tid bit of insider knowledge... it hasn't been announced on our blog yet, but the Windows platform (as well as OSX) are both going to become deprecated with the electron platform as it's replacement -- but I don't think electron platform has a solution that you're looking for either unfortunately.

Edit: I guess the electron platform does have scheme support provided in apache/cordova-electron#154

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants