Ik probeer een POST request naar mijn web server te sturen vanuit een html formulier(ajax), als response zou deze de html bron van de pagina moeten opslaan in een buffer zodat ik deze verder kan bewerken. Op een 1 of andere manier wordt de content van de pagina echter gewoon naar de browser gestuurd ipv gebuffered.
Ik heb ook fgets() gebruikt, het aantal bytes om in te lezen aangepast, maar ook hierbij werd de pagina niet gebuffered.
Dank je voor je reactie, maar ik heb in de code al curl als fallback. Ik wil echter ook sockets implementeren. Code is deel van een module voor mijn cms, dus wordt door anderen ook gebruikt.
Ik heb meerdere scripts gemaakt met sockets en ik kan altijd de response van de server opslaan in een variabel, mijn vraag is dan ook waarom wordt de ouput niet opgeslagen in een variabel maar gewoon verstuurd naar de browser?
Het punt is meer dat het mogelijk is om een POST via sockets te doen, en het werkt ook, ik krijg de juiste bron..alleen waarom wordt deze direct naar de browser verstuurd en niet in een variabel opgeslagen?
Volgens mij is het standaard gedrag van fsockopen. In het verre verleden liep ik hier ook tegen aan. En toen heb ik dit ook met output-buffering opgelost. Vaak kan je, net als bij system() via een parameter kiezen of je het wilt bufferen of outputten. Maar bij fsockopen() lijkt dat niet te kunnen.
Omdat cURL behoorlijk flexibeler is, gebruik ik nu haast altijd cURL.
Het HTTP protocol is niet mijn sterkste punt, maar zorgt een witregel (dubbele regelovergang - \r\n\r\n) niet voor de scheiding tussen de headers en de body? Oftewel, jouw Connection: Close valt buiten de boot?
Daarnaast geef je aan dat het een POST request betreft, vertel je hoe lang de gePOSTe data is... maar je verzend vervolgens nergens de data zelf :p.
Na regel 9 moet er waarschijnlijk nog iets volgen als fputs($rConnect, $sData);.
Ook is het mogelijk verstandig als je iets anders doet dan/met die !feof(), met die constructie kan namelijk nogal wat misgaan.
Als dit alles op orde is en je ook een correct request doet zou je eens verder kunnen kijken naar wat er (dan nog) aan de hand is.
EDIT: hoe ziet $aUrl['query'] er uit? Zou het niet handiger zijn als dit een array is en dat je http_build_query() hierop toepast voor het bouwen van $sData?
EDIT: weet je ook zeker dat je nergens de inhoud van $sFileData weergeeft? Bij mij werkt het zonder enige problemen. Overigens, je bouwt dus een rauw HTTP request, dan is het dus ook niet zo verwonderlijk dat je een rauwe HTTP response krijgt - hier zitten headers dus ook bij. Ik weet niet waarom e.e.a. direct wordt weergegeven op je scherm. Ik had dit toen ik met jouw script startte ook, maar bij een aangepaste (en kloppende) versie werkte alles zoals je zou verwachten.
$aUrl['query'] is het query gedeelte van de url afkomstig van de functie parse_url()
EDIT: nope, geef nergens $sFileData weer, dat dacht ik in het begin ook, maar dat is niet het geval.
Oef, dat tweede fragment is echt heel erg traag en lijkt ook niet te doen wat je wilt. Ik weet ook niet of je echt (aparte?!) fwrites wilt doen? Resulteert dat niet in gefragmenteerde requests?
Probeer het anders zo eens (wel even host en doelscript aanpassen):
<?php
// for debugging
error_reporting(E_ALL);
ini_set('display_startup_errors', true);
ini_set('display_errors', 'stdout');
// REQUEST
$aUrl = array(
'host' => 'your.server.com',
'path' => '/path/to/post.test.php',
'query' => array('fish' => 'moo', 'test' => true),
);
$sData = http_build_query($aUrl['query']); // do not urlencode, http_build_query takes care of this
$iError = 0;
$sError = '';
define('LE', "\r\n"); // line ending, less typing :)
$rConnect = fsockopen($aUrl['host'], 80, $iError, $sError, 10);
if ($rConnect === false) {
die('connection failed'); // for testing purposes, you want better handling than this obviously
}
$headers = array();
$headers[] = 'POST '.$aUrl['path'].' HTTP/1.0'; // note: HTTP/1.0, so we do not get chunked garbage
$headers[] = 'Host: '.$aUrl['host'];
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
$headers[] = 'Content-Length: '.strlen($sData);
$headers[] = 'Connection: Close'; // immediately hang up after
$headers[] = LE; // blank line indicating end of headers
// write to socket
fputs($rConnect, implode(LE, $headers));
fputs($rConnect, $sData); // EDIT: make sure to actually write POST data :)
// get response
// note fgets() does not support chunked mode, which is part of HTTP 1.1
// if you are going to use fgets make sure to use HTTP 1.0
$sFileData = '';
// This is one way to do it...
/*
while (($line = fgets($rConnect, 1024)) !== false) {
$sFileData .= $line;
}
*/
// ... or use this
while (!feof($rConnect)) {
$sFileData .= stream_get_line($rConnect, 1024, "\n");
}
fclose($rConnect);
// RESPONSE
// for testing if everything came across ok
header('Content-Type: text/html; charset=UTF-8');
echo '<pre>'.htmlspecialchars($sFileData, ENT_QUOTES, 'UTF-8').'</pre>';
?>
En /path/to/post.test.php is bijvoorbeeld:
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (empty($_POST)) {
$response = 'empty POST';
} else {
// quick test, just bake a JSON response
$response = json_encode($_POST);
}
echo $response;
}
?>
Dit werkt bij mij prima, en produceert niet ongevraagd output.
Dit produceert bij mij het volgende:
HTTP/1.1 200 OK
Server: nginx/1.10.3
Date: Thu, 07 Mar 2019 23:03:25 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
{"fish":"moo","test":"1"}