3

What I'm trying to do

Post from a local html/javascript website to an online PHP file.

Problem

When I attempt to utilise my below code, I keep receiving the below mentioned error.

Background:

This website is intended to run locally. As it's each user's choice which browser they use, I'm looking to discover an approach which could solve the above, without forcing browser policy modification onto each user.

Is this possible, if so how?

Javascript code:

$.ajax({
    type: 'POST',
    url: 'http://example.com/test.php',
    crossDomain: true,
    data: "my_request_is=foo",
    dataType: 'json',
    success: function(responseData, textStatus, jqXHR) 
    {
        console.log(responseData);
    },
    error: function (responseData, textStatus, errorThrown) 
    {
        console.warn(responseData, textStatus, errorThrown);
        alert('CORS failed - ' + textStatus);
    }
});

Php code (test.php):

<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Content-Type');
echo json_encode(array("your_request_was" => $_POST['my_request_is']));
?>

Error:

Error Image

user7631121
  • 125
  • 7
  • Is browser chrome or chromium? – guest271314 Mar 04 '17 at 00:33
  • Latest version of Chrome – user7631121 Mar 04 '17 at 00:34
  • Why is `POST` request necessary? – guest271314 Mar 04 '17 at 01:29
  • The post was necessary, as I was intending to utilise PHP to insert data from the local html/javascript website to an online MYSQL database. – user7631121 Mar 04 '17 at 01:32
  • _"The post was necessary, as I was intending to utilise PHP to insert data from the local html/javascript website to an online MYSQL database."_ ? The premise of the Question is offline usage of website, no? Why do you not provide a `
    ` for user to submit online, at the same host where `mysql` database resides? Respond with `JSON` as a file offer for download?
    – guest271314 Mar 04 '17 at 01:34
  • @guest271314 could this approach be utilised to solve my query at - http://stackoverflow.com/questions/42591287/inserting-into-an-mysql-database-from-a-local-html-javascript-website?noredirect=1&lq=1 if so how can I go about accomplishing this, as I haven't utilised an approach like this before ? – user7631121 Mar 05 '17 at 04:21

2 Answers2

1

Due to chrome security settings, to make an XMLHttpRequest you need a valid origin and a valid destination.
The destination is a valid domain, and because you have Access-Control-Allow-Origin enabled, you can make a request from different origin.
But the origin is not a valid domain, because you are doing a request from a local page.
The origin must be a valid host/identifier (domain for a website, identifier for a browser extension, application id for a webview embedded into an application).

You have these option to solve the issue:

  • Store your page on an host, that's fine localhost too, you can create a setup to automatically deploy the host and webpage to your customers
  • disable browser security settings: sample for chrome:

    chromium-browser --disable-web-security --user-data-dir

    check this answer, for how to use: https://stackoverflow.com/a/3177718/5081328

  • embed your page into an application and use a webview

  • Create a browser extension to load your page

Community
  • 1
  • 1
Stefano Balzarotti
  • 1,542
  • 1
  • 11
  • 29
  • 1
    Note, if an instance of chrome, chromium is open while a second instance is launched, the flag will not have the expected effect. That is purpose for setting `--user-data-dir` flag. – guest271314 Mar 04 '17 at 00:43
  • As I would like to store this website locally on a series of machines without posting it online to the web, is there an approach which could accomplish what I need to do, whilst not requiring me to modify the policies of local web-browsers? – user7631121 Mar 04 '17 at 00:45
  • @user7631121 there are no other options, if you don't want to publish a locally websites to a series of machines you can publish online. You can even create a setup that automatically instantiate a webserver.... – Stefano Balzarotti Mar 04 '17 at 00:49
  • 1
    @user7631121 I suggest to create a seup that automatically install a local webserver and deploy your webpage. Your customer simply need to install the application from setup and open link to the page. Another option is to embed the page into an application and use a webview, in fact if you launch a page embedded into an application you always have a valid origin (The pakegeId/namespace of app). – Stefano Balzarotti Mar 04 '17 at 01:26
  • Other alternative as suggested by @guest271314 is to create a browser extension. With a browser extension, the Origin will be the extension name identifier. – Stefano Balzarotti Mar 04 '17 at 01:31
1

By default cross-origin requests are not allowed at chrome, chromium from file: protocol. You can close open instances of chrome, chromium and launch with --disable-web-security flag

google-chrome --disabled-web-security

or launch with existing instances open by setting a different user-data-dir

google-chrome --disable-web-security --user-data-dir="~/.config/google-chrome-temp"

is there an approach which could accomplish what I need to do, whilst not requiring me to modify the policies of local web-browsers?

Not at chrome, chromium without modifying default settings; or creating an chromium extension or app to perform network requests - where too, proper permissions need to be set.

The restriction is there for a purpose. One of the several security issues is that user at a local computer could, possibly unknowingly, upload a listing of all of the files in one or more directories on their computer, and potentially the directories themselves, without necessarily being aware of that fact, see

How FileReader.readAsText in HTML5 File API works?

which; note, could also occur without flags being set. Or, a requested script could perform actions to read or write to local filesystem without user necessarily being aware of their local filesystem being accessed by an external script.

Though, with restrictions in place, the user has to perform an affirmative action to disable default settings restricting access to local file system from file: protocol, and restricting local file system to fetch resources from null origin to a different origin.

As noted by @StefanoBalzarotti

sorry if I am fussy, but this limitation is not related to the 'file:' protocol, even with 'data:', 'about:' etc... you can't make a cross origin request. The requirement to make a cross origin request is to have an host for origin

which should be taken into consideration as to the reasons why browser developers would implement such a default limitation on cross origin request.

Used sparingly, and with awareness of the significance of the flags, the flags --disable-web-security and --allow-file-access-from-files, see

are designed for local web development, not as a workaround for a local application which requires resources from a web application.

--disable-web-security Don't enforce the same-origin policy. (Used by people testing their sites.)

--allow-file-access-from-files By default, file:// URIs cannot read other file:// URIs. This is an override for developers who need the old behavior for testing.

"testing" term in description of flags should provide emphasis of the usage of the flags. The flags are not designed for production usage.


Alternatives,

  • Create a chromium extension to perform network tasks;

  • Create a chrome app to perform network tasks

where either requires proper permissions settings at manifest.json.

Community
  • 1
  • 1
guest271314
  • 1
  • 10
  • 82
  • 156
  • cross-origin requests are allowed with Access-Control-Allow-Origin, the issue is that the origin is not valid, because the request are made from a local file. But if you disable the security with disabled-web-security, they works. – Stefano Balzarotti Mar 04 '17 at 00:41
  • 1
    @StefanoBalzarotti Yes. Omitted including distinction of `file:` protocol as OP clearly describes requesting from `file:` protocol. Updated Answer for clarity. – guest271314 Mar 04 '17 at 00:42
  • As I would like to store this website locally on a series of machines without posting it online to the web, is there an approach which could accomplish what I need to do, whilst not requiring me to modify the policies of local web-browsers? – user7631121 Mar 04 '17 at 00:45
  • @user7631121 _"store this website locally on a series of machines without posting it online to the web"_ Not sure what you mean? _"whilst not requiring me to modify the policies of local web-browsers?"_ Not from `file:` protocol at default chrome, chromium browser. firefox may allow that behaviour; have not checked in a while. – guest271314 Mar 04 '17 at 00:47
  • 1
    The website is intended to be run locally. Also as it's the user's choice which browser they use, I'd much rather discover an approach which could solve the above, without forcing browser modification onto each user. – user7631121 Mar 04 '17 at 00:51
  • 1
    @guest271314 sorry if I am fussy, but this limitation is not related to the 'file:' protocol, even with 'data:', 'about:' etc... you can't make a cross origin request. The requirement to make a cross origin request is to have an host for origin. – Stefano Balzarotti Mar 04 '17 at 00:55
  • @StefanoBalzarotti Yes. You are correct. Is that not clear at Answer? – guest271314 Mar 04 '17 at 01:08
  • @user7631121 _"The website is intended to be run locally."_ Then why does application perform `POST` request to an external site? How is a cross domain `POST` request "local"? – guest271314 Mar 04 '17 at 01:10
  • @guest271314 Yes it's clear, I only wanted to specify because it can be useful to other users. In fact I've upvoted your answer. – Stefano Balzarotti Mar 04 '17 at 01:10