I am trying to make an asynchronous request with POST method from a web worker used in my extension. The thing is that it does not work for me.
On the server side I have PHP script listening for data in $_POST variable. Although I am able to establish connection to the server, and even pass some data in URL (GET), the $_POST is always empty.
Here is the latest code I'm using in the web worker:
var serviceUrl = "http://localhost/pfm/service/index.php";
var invocation = new XMLHttpRequest();
if(invocation){
invocation.open('POST', serviceUrl, true);
invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
invocation.setRequestHeader('Content-Type', 'text/plain');
invocation.onreadystatechange = function(){processResponse(invocation);};
invocation.send("action=init");
}
(borrowed from MDN web site when I got an idea that the issue was the same origin policy)
Prior to this I was using a rather obvious and ridiculously simple:
var serviceUrl = "http://localhost/pfm/service/index.php";
var xhr = new XMLHttpRequest();
xhr.open("POST", serviceUrl, true);
xhr.onreadystatechange = function(){processResponse(receiptStoreRequest);};
xhr.send("action=init");
In this case the request also passed, but the $_POST was still empty.
Is it possible that POST-requests are not allowed on web workers?
Right now everything is being tested on localhost.
Don't set the content type text/plain but
invocation.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
In case you're developing for Firefox 4+ you might also be interested in FormData objects
Related
A task:
The user, by clicking on the button, should be able to download and save the file.
The file is creating on another service. It can be obtained by post-request with body and headers.
I am using wordpress and my plugin. I can call a php function using form or jquery.
//Accept: application/pdf
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
$res = curl_exec($ch);
This returns the headers and response body as a string.
(My asp .Net 6 external service returns FileStreamResult from method)
I don't know how to implement saving a file on the user's PC.
As far as I understand, I have two ways:
Download the file using curl on the server side. Then somehow transfer the ready file to the user for saving.
But then there will be an extra load on the backend.
I can create request body and headers on backend. Then execute this post request on the client side.
I am weak in web development...
I think the right way is to make a function on the backend that will return a json with the request body and headers.
I can create a separate php page (I think it's redundant) that will call this function. Or I can call this function from javascript or jquery, but I don't know how to initialize post request to save the file.
Maybe someone has already implemented this behavior and can tell me?
Thanks.
upd. #1
I found this solution:
var request = new XMLHttpRequest();
request.responseType = "blob";
request.open("POST", url, true);
request.setRequestHeader("Content-Type", "application/json");
request.onload = function() {
var url = window.URL.createObjectURL(this.response);
var a = document.createElement("a");
document.body.appendChild(a);
a.href = url;
a.download = this.response.name || "filename"
a.click();
}
request.send(json);
But it looks like a dirty hack.
And it does not work as it should (the file is first downloaded before saving).
upd. #2
I'm willing to change the method from POST to GET, but I still need to pass the ApiKey in the header.
I think my issue is discussed here: https://github.com/whatwg/html/issues/7810
So far, I have not found a way that implements both points:
Adding custom headers to the request.
Showing the file save dialog before it is downloaded.
OK the title doesn't give much a way so let me explain my very strange set-up.
Two servers are involved:
website: remote
localhost: local machine
The workflow is as follows:
The site calls localhost via cross-domain AJAX
In response localhost dynamically creates a ZIP file via PHP's ZipArchive lib
localhost conveys the raw data that comprises the archive as the AJAX response
The request is made and the archive is made - all good. The archive is openable, all good. What I'm stuck on now is how to convey that archive as the AJAX response, such that it can be "put together again" (à la Humpty Dumpty). When I do this currently (via file_put_contents()) it errors on opening, saying it's invalid. Currently I'm just outputting the archive's raw data:
echo file_get_contents('path/to/archive.zip');
This is fine, but sends garbled characters in the response. I don't know much about encoding and headers, so apologise if this seems obvious.
For the response, should I be looking to convert it to binary, or sending certain headers etc? I tried sending the multipart/form-data header, but no dice. Headers aren't my strong point.
Please note cURL is not an option in this scenario, else I'd be laughing.
You have to read the zip file as a binary data with Blob javascript class.
This is a code snippet from Mozilla documentation
var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "arraybuffer";
oReq.onload = function(oEvent) {
var blob = new Blob([oReq.response], {type: "application/octet-stream"}); //
// you have nothing to do with the blob...
// ...
};
oReq.send();
Then send this file (blob) with POST method to your destination
var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.onload = function (oEvent) {
// Uploaded.
};
oReq.send(blob); //the blob that you loaded
you can read more in the documentation by Mozilla :https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The same origin policy
I wanted to make a community wiki regarding HTML/JS same-origin policies to hopefully help anyone searching for this topic. This is one of the most searched-for topics on SO and there is no consolidated wiki for it so here I go :)
The same origin policy prevents a
document or script loaded from one
origin from getting or setting
properties of a document from another
origin. This policy dates all the way
back to Netscape Navigator 2.0.
What are some of your favorite ways to go around same-origin policies?
Please keep examples verbose and preferably also link your sources.
The document.domain method
Method type: iframe.
Note that this is an iframe method that sets the value of document.domain to a suffix of the current domain. If it does so, the shorter domain is used for subsequent origin checks. For example, assume a script in the document at http://store.company.com/dir/other.html executes the following statement:
document.domain = "company.com";
After that statement executes, the page would pass the origin check with http://company.com/dir/page.html. However, by the same reasoning, company.com could not set document.domain to othercompany.com.
With this method, you would be allowed to exectue javascript from an iframe sourced on a subdomain on a page sourced on the main domain. This method is not suited for cross-domain resources as browsers like Firefox will not allow you to change the document.domain to a completely alien domain.
Source: https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript
The Cross-Origin Resource Sharing method
Method type: AJAX.
Cross-Origin Resource Sharing (CORS) is a W3C Working Draft that defines how the browser and server must communicate when accessing sources across origins. The basic idea behind CORS is to use custom HTTP headers to allow both the browser and the server to know enough about each other to determine if the request or response should succeed or fail.
For a simple request, one that uses either GET or POST with no custom headers and whose body is text/plain, the request is sent with an extra header called Origin. The Origin header contains the origin (protocol, domain name, and port) of the requesting page so that the server can easily determine whether or not it should serve a response. An example Origin header might look like this:
Origin: http://www.stackoverflow.com
If the server decides that the request should be allowed, it sends a Access-Control-Allow-Origin header echoing back the same origin that was sent or * if it’s a public resource. For example:
Access-Control-Allow-Origin: http://www.stackoverflow.com
If this header is missing, or the origins don’t match, then the browser disallows the request. If all is well, then the browser processes the request. Note that neither the requests nor responses include cookie information.
The Mozilla team suggests in their post about CORS that you should check for the existence of the withCredentials property to determine if the browser supports CORS via XHR. You can then couple with the existence of the XDomainRequest object to cover all browsers:
function createCORSRequest(method, url){
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr){
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined"){
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
}
var request = createCORSRequest("get", "http://www.stackoverflow.com/");
if (request){
request.onload = function() {
// ...
};
request.onreadystatechange = handler;
request.send();
}
Note that for the CORS method to work, you need to have access to any type of server header mechanic and can't simply access any third-party resource.
Source: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
The window.postMessage method
Method type: iframe.
window.postMessage, when called, causes a MessageEvent to be dispatched at the target window when any pending script that must be executed completes (e.g. remaining event handlers if window.postMessage is called from an event handler, previously-set pending timeouts, etc.). The MessageEvent has the type message, a data property which is set to the string value of the first argument provided to window.postMessage, an origin property corresponding to the origin of the main document in the window calling window.postMessage at the time window.postMessage was called, and a source property which is the window from which window.postMessage is called.
To use window.postMessage, an event listener must be attached:
// Internet Explorer
window.attachEvent('onmessage',receiveMessage);
// Opera/Mozilla/Webkit
window.addEventListener("message", receiveMessage, false);
And a receiveMessage function must be declared:
function receiveMessage(event)
{
// do something with event.data;
}
The off-site iframe must also send events properly via postMessage:
<script>window.parent.postMessage('foo','*')</script>
Any window may access this method on any other window, at any time, regardless of the location of the document in the window, to send it a message. Consequently, any event listener used to receive messages must first check the identity of the sender of the message, using the origin and possibly source properties. This cannot be understated: Failure to check the origin and possibly source properties enables cross-site scripting attacks.
Source: https://developer.mozilla.org/en/DOM/window.postMessage
The Reverse Proxy method
Method type: Ajax
Setting up a simple reverse proxy on the server, will allow the browser to use relative paths for the Ajax requests, while the server would be acting as a proxy to any remote location.
If using mod_proxy in Apache, the fundamental configuration directive to set up a reverse proxy is the ProxyPass. It is typically used as follows:
ProxyPass /ajax/ http://other-domain.com/ajax/
In this case, the browser would be able to request /ajax/web_service.xml as a relative URL, but the server would serve this by acting as a proxy to http://other-domain.com/ajax/web_service.xml.
One interesting feature of the this method is that the reverse proxy can easily distribute requests towards multiple back-ends, thus acting as a load balancer.
I use JSONP.
Basically, you add
<script src="http://..../someData.js?callback=some_func"/>
on your page.
some_func() should get called so that you are notified that the data is in.
AnyOrigin didn't function well with some https sites, so I just wrote an open source alternative called whateverorigin.org that seems to work well with https.
Code on github.
The most recent way of overcoming the same-origin policy that I've found is http://anyorigin.com/
The site's made so that you just give it any url and it generates javascript/jquery code for you that lets you get the html/data, regardless of it's origin. In other words, it makes any url or webpage a JSONP request.
I've found it pretty useful :)
Here's some example javascript code from anyorigin:
$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
$('#output').html(data.contents);
});
The JSONP comes to mind:
JSONP or "JSON with padding" is a
complement to the base JSON data
format, a usage pattern that allows a
page to request and more meaningfully
use JSON from a server other than the
primary server. JSONP is an
alternative to a more recent method
called Cross-Origin Resource Sharing.
Personally, window.postMessage is the most reliable way that I've found for modern browsers. You do have to do a slight bit more work to make sure you're not leaving yourself open to XSS attacks, but it's a reasonable tradeoff.
There are also several plugins for the popular Javascript toolkits out there that wrap window.postMessage that provide similar functionality to older browsers using the other methods discussed above.
Well, I used curl in PHP to circumvent this. I have a webservice running in port 82.
<?php
$curl = curl_init();
$timeout = 30;
$ret = "";
$url="http://localhost:82/put_val?val=".$_GET["val"];
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($curl, CURLOPT_MAXREDIRS, 20);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5");
curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
$text = curl_exec($curl);
echo $text;
?>
Here is the javascript that makes the call to the PHP file
function getdata(obj1, obj2) {
var xmlhttp;
if (window.XMLHttpRequest)
xmlhttp=new XMLHttpRequest();
else
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","phpURLFile.php?eqp="+obj1+"&val="+obj2,true);
xmlhttp.send();
}
My HTML runs on WAMP in port 80. So there we go, same origin policy has been circumvented :-)
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The same origin policy
I wanted to make a community wiki regarding HTML/JS same-origin policies to hopefully help anyone searching for this topic. This is one of the most searched-for topics on SO and there is no consolidated wiki for it so here I go :)
The same origin policy prevents a
document or script loaded from one
origin from getting or setting
properties of a document from another
origin. This policy dates all the way
back to Netscape Navigator 2.0.
What are some of your favorite ways to go around same-origin policies?
Please keep examples verbose and preferably also link your sources.
The document.domain method
Method type: iframe.
Note that this is an iframe method that sets the value of document.domain to a suffix of the current domain. If it does so, the shorter domain is used for subsequent origin checks. For example, assume a script in the document at http://store.company.com/dir/other.html executes the following statement:
document.domain = "company.com";
After that statement executes, the page would pass the origin check with http://company.com/dir/page.html. However, by the same reasoning, company.com could not set document.domain to othercompany.com.
With this method, you would be allowed to exectue javascript from an iframe sourced on a subdomain on a page sourced on the main domain. This method is not suited for cross-domain resources as browsers like Firefox will not allow you to change the document.domain to a completely alien domain.
Source: https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript
The Cross-Origin Resource Sharing method
Method type: AJAX.
Cross-Origin Resource Sharing (CORS) is a W3C Working Draft that defines how the browser and server must communicate when accessing sources across origins. The basic idea behind CORS is to use custom HTTP headers to allow both the browser and the server to know enough about each other to determine if the request or response should succeed or fail.
For a simple request, one that uses either GET or POST with no custom headers and whose body is text/plain, the request is sent with an extra header called Origin. The Origin header contains the origin (protocol, domain name, and port) of the requesting page so that the server can easily determine whether or not it should serve a response. An example Origin header might look like this:
Origin: http://www.stackoverflow.com
If the server decides that the request should be allowed, it sends a Access-Control-Allow-Origin header echoing back the same origin that was sent or * if it’s a public resource. For example:
Access-Control-Allow-Origin: http://www.stackoverflow.com
If this header is missing, or the origins don’t match, then the browser disallows the request. If all is well, then the browser processes the request. Note that neither the requests nor responses include cookie information.
The Mozilla team suggests in their post about CORS that you should check for the existence of the withCredentials property to determine if the browser supports CORS via XHR. You can then couple with the existence of the XDomainRequest object to cover all browsers:
function createCORSRequest(method, url){
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr){
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined"){
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
}
var request = createCORSRequest("get", "http://www.stackoverflow.com/");
if (request){
request.onload = function() {
// ...
};
request.onreadystatechange = handler;
request.send();
}
Note that for the CORS method to work, you need to have access to any type of server header mechanic and can't simply access any third-party resource.
Source: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
The window.postMessage method
Method type: iframe.
window.postMessage, when called, causes a MessageEvent to be dispatched at the target window when any pending script that must be executed completes (e.g. remaining event handlers if window.postMessage is called from an event handler, previously-set pending timeouts, etc.). The MessageEvent has the type message, a data property which is set to the string value of the first argument provided to window.postMessage, an origin property corresponding to the origin of the main document in the window calling window.postMessage at the time window.postMessage was called, and a source property which is the window from which window.postMessage is called.
To use window.postMessage, an event listener must be attached:
// Internet Explorer
window.attachEvent('onmessage',receiveMessage);
// Opera/Mozilla/Webkit
window.addEventListener("message", receiveMessage, false);
And a receiveMessage function must be declared:
function receiveMessage(event)
{
// do something with event.data;
}
The off-site iframe must also send events properly via postMessage:
<script>window.parent.postMessage('foo','*')</script>
Any window may access this method on any other window, at any time, regardless of the location of the document in the window, to send it a message. Consequently, any event listener used to receive messages must first check the identity of the sender of the message, using the origin and possibly source properties. This cannot be understated: Failure to check the origin and possibly source properties enables cross-site scripting attacks.
Source: https://developer.mozilla.org/en/DOM/window.postMessage
The Reverse Proxy method
Method type: Ajax
Setting up a simple reverse proxy on the server, will allow the browser to use relative paths for the Ajax requests, while the server would be acting as a proxy to any remote location.
If using mod_proxy in Apache, the fundamental configuration directive to set up a reverse proxy is the ProxyPass. It is typically used as follows:
ProxyPass /ajax/ http://other-domain.com/ajax/
In this case, the browser would be able to request /ajax/web_service.xml as a relative URL, but the server would serve this by acting as a proxy to http://other-domain.com/ajax/web_service.xml.
One interesting feature of the this method is that the reverse proxy can easily distribute requests towards multiple back-ends, thus acting as a load balancer.
I use JSONP.
Basically, you add
<script src="http://..../someData.js?callback=some_func"/>
on your page.
some_func() should get called so that you are notified that the data is in.
AnyOrigin didn't function well with some https sites, so I just wrote an open source alternative called whateverorigin.org that seems to work well with https.
Code on github.
The most recent way of overcoming the same-origin policy that I've found is http://anyorigin.com/
The site's made so that you just give it any url and it generates javascript/jquery code for you that lets you get the html/data, regardless of it's origin. In other words, it makes any url or webpage a JSONP request.
I've found it pretty useful :)
Here's some example javascript code from anyorigin:
$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
$('#output').html(data.contents);
});
The JSONP comes to mind:
JSONP or "JSON with padding" is a
complement to the base JSON data
format, a usage pattern that allows a
page to request and more meaningfully
use JSON from a server other than the
primary server. JSONP is an
alternative to a more recent method
called Cross-Origin Resource Sharing.
Personally, window.postMessage is the most reliable way that I've found for modern browsers. You do have to do a slight bit more work to make sure you're not leaving yourself open to XSS attacks, but it's a reasonable tradeoff.
There are also several plugins for the popular Javascript toolkits out there that wrap window.postMessage that provide similar functionality to older browsers using the other methods discussed above.
Well, I used curl in PHP to circumvent this. I have a webservice running in port 82.
<?php
$curl = curl_init();
$timeout = 30;
$ret = "";
$url="http://localhost:82/put_val?val=".$_GET["val"];
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($curl, CURLOPT_MAXREDIRS, 20);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5");
curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
$text = curl_exec($curl);
echo $text;
?>
Here is the javascript that makes the call to the PHP file
function getdata(obj1, obj2) {
var xmlhttp;
if (window.XMLHttpRequest)
xmlhttp=new XMLHttpRequest();
else
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","phpURLFile.php?eqp="+obj1+"&val="+obj2,true);
xmlhttp.send();
}
My HTML runs on WAMP in port 80. So there we go, same origin policy has been circumvented :-)
I want to send the canvas data to the server side as image. I have been making an HTTP post request, but i am not able to get the data at server side. $_POST is empty but when i console the same object at JS side i get the image data.
this is the JS side
var XHR = new XMLHttpRequest();
var vvFD="image=" + JSON.stringify(document.getElementById('canvas').toDataURL("image/png"));
console.log(vvFD);
XHR.upload.addEventListener('progress', uploadProgress, false);
XHR.addEventListener('load', uploadFinish, false);
XHR.addEventListener('error', uploadError, false);
XHR.addEventListener('abort', uploadAbort, false);
XHR.open('POST', 'example_upload/upload1.php');
XHR.send(vvFD);
and the PHP side is...
if(!empty($_POST))
{
//do stuff
}
else
{
echo "_POST is empty";
}
I am getting the message _POST is empty.
Any one can here help
Thanks in advance
I'm not entirely sure how your JS works, but I have a feeling it's sending the image in the body section of the HTTP request. $_POST won't pick that up on the server side.
Try:
$GLOBALS["HTTP_RAW_POST_DATA"];
There is an example in the manual which will output the headers from your HTTP request.
apache_request_headers()
Between these two, you should be able to capture everything coming into your php script.