AJAX request na vzálený server

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Shampoo
Člen | 38
+
+1
-

Zdravím,

vytvářím html5 bannery, které budou získávat pomocí AJAXu data ze vzdáleného serveru.
Na serveru běží Nette aplikace.

Zatím jsem to měl vymyšleno tak, že v rámci presenteru vytvořím akci a ta mi vrátí nějaká data.
Nicméně AJAX má defaultně omezení, že AJAX požadavk musí být z localhostu.

Zjistili jsme, že když nastavím hlavičku následovně, tak by měl server normálně odpovědět:

header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');

Je Nette na tohle připraveno? Co musím v Nette udělat?

Díky moc
Adam

Shampoo
Člen | 38
+
0
-

Jo a ještě tohle:
Potřebuji aby jsem používal vanillaJS a tedy takto vypadá požadavek:

<script>
	var el = document.getElementById('headline').getElementsByTagName('h1')[0];
	var xhttp = new XMLHttpRequest();
	xhttp.onreadystatechange = function() {
		if (xhttp.readyState == 4 && xhttp.status == 200) {
	      el.innerHTML = xhttp.responseText;
	    }
	    else {
	    	el.innerHTML = 'Nějaký default text';
	    }
	}
	xhttp.open("GET", "http://mojeDomena/banner", true);
	xhttp.send();
</script>

A takto vypadá akce:

public function actionBanner() {

	if ($this->getText()) {
		$this->sendResponse(new TextResponse($this->getText()));
	}
	else {
		$this->sendResponse(new TextResponse('No text'));
	}
}

Jsem aspoň na správné cestě?

Shampoo
Člen | 38
+
0
-

Ok, takže jsem rozběhal Request.
XMLHttpRequestu jsem přidal hlavičku, aby byl ajax request detekován.

<script>
    var el = document.getElementById('headline').getElementsByTagName('h1')[0];
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
        if (xhttp.readyState == 4 && xhttp.status == 200) {
          el.innerHTML = xhttp.responseText;
        }
        else {
            el.innerHTML = 'Nějaký default text';
        }
    }
    xhttp.open("GET", "http://mojeDomena/banner", true);
	xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest"); //důležité

    xhttp.send();
</script>
public function actionBanner() {
	if ($this->isAjax()) {
    	if ($this->getText()) {
        	$this->sendResponse(new Nette\Application\Responses\TextResponse($this->getText()));
    	}
    	else {
        	$this->sendResponse(new Nette\Application\Responses\TextResponse('No text'));
    	}
	}
}

Teď ještě ty vzdálené požadavky…

Editoval Shampoo (27. 4. 2016 13:40)

Shampoo
Člen | 38
+
0
-

Ok, tak vyřešeno, prostě jsem si v akci přidal k odpovědi potřebné hlavičky.

$origin = $this->getHttpRequest()->getReferer()->scheme . '://' . $this->getHttpRequest()->getReferer()->host;

$response = $this->getHttpResponse();
$response->addHeader('Access-Control-Allow-Origin', $origin);
$response->addHeader('Access-Control-Allow-Methods', 'GET');
$response->addHeader('Access-Control-Allow-Headers', 'X-Requested-With');

if ($this->getText()) {
	$this->sendResponse(new Nette\Application\Responses\TextResponse($this->getText());
}
else {
	$this->sendResponse(new Nette\Application\Responses\TextResponse('error'));
}

Vše funguje, nicméně by mne zajímalo, jak jinak elegatně získat doménu ze které požadavek přichází, jelikož $_SERVER[‚HTTP_ORIGIN‘] nefunguje…

iguana007
Člen | 970
+
+3
-

Nedávno jsem to taky řešil. Správně se tomu říká CORS (https://cs.wikipedia.org/wiki/CORS) a dle toho co jsem si nastudoval na netu by to mělo probíhat následovně:

  1. Při prvním requestu browser pošle OPTIONS request na server, který mu odpoví hlavičkami bez dalšího contentu, jak si už ukázal
  2. Ihned následuje klasický request, který už odpoví contentem, který se po ajax volání očekává
  3. Každý další request se už posílá bez toho OPTIONS requestu

Já u těch CORS AJAX akcí vždý volám následující metodu:

	private function setCorsHeaders() {
		if (in_array($this->getHttpRequest()->getHeader('Origin'), $this->allowedOrigins)) {
			$this->getHttpResponse()->setHeader('Access-Control-Allow-Origin', $this->getHttpRequest()->getHeader('Origin'));
			$this->getHttpResponse()->setHeader('Access-Control-Allow-Credentials', 'true');
			$this->getHttpResponse()->setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
			$this->getHttpResponse()->setHeader('Access-Control-Allow-Headers', 'Accept, Overwrite, Destination, Content-Type, Depth, User-Agent, Translate, Range, Content-Range, Timeout, X-Requested-With, If-Modified-Since, Cache-Control, Location');
			$this->getHttpResponse()->setHeader('Access-Control-Max-Age', 1728000);
			if ($this->getHttpRequest()->getMethod() == 'OPTIONS') {
				$this->terminate();
			}
		}
	}

Také je třeba mít na paměti, že XMLHttpRequest nefunguje ve všech verzích IE ;)

Shampoo
Člen | 38
+
0
-

Supér a díky moc za info :)