PHP fsockopen POST request
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.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$rConnect = fsockopen($aUrl['host'],80,$iError,$sError,10);
$sData = urlencode($aUrl['query']);
$sOut = "POST ".$aUrl['path']." HTTP/1.1\r\n";
$sOut .= "Host: ".$aUrl['host']."\r\n";
$sOut .= "Content-Type: application/x-www-form-urlencoded\r\n";
$sOut .= "Content-Length: ".strlen($sData)."\r\n\r\n";
$sOut .= "Connection: Close\r\n\r\n";
// write to socket
fputs($rConnect,$sOut);
$sFileData = "";
// get response
while(!feof($rConnect)){
$sFileData .= stream_get_line($rConnect,1024,"\n");
}
fclose($rConnect);
$sData = urlencode($aUrl['query']);
$sOut = "POST ".$aUrl['path']." HTTP/1.1\r\n";
$sOut .= "Host: ".$aUrl['host']."\r\n";
$sOut .= "Content-Type: application/x-www-form-urlencoded\r\n";
$sOut .= "Content-Length: ".strlen($sData)."\r\n\r\n";
$sOut .= "Connection: Close\r\n\r\n";
// write to socket
fputs($rConnect,$sOut);
$sFileData = "";
// get response
while(!feof($rConnect)){
$sFileData .= stream_get_line($rConnect,1024,"\n");
}
fclose($rConnect);
Hoop dat iemand een oplossing heeft.
https://stackoverflow.com/questions/2138527/php-curl-http-post-sample-code
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
//
// A very simple PHP example that sends a HTTP POST to a remote site
//
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.example.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
"postvar1=value1&postvar2=value2&postvar3=value3");
// In real life you should use something like:
// curl_setopt($ch, CURLOPT_POSTFIELDS,
// http_build_query(array('postvar1' => 'value1')));
// Receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close ($ch);
// Further processing ...
if ($server_output == "OK") { ... } else { ... }
?>
//
// A very simple PHP example that sends a HTTP POST to a remote site
//
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.example.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
"postvar1=value1&postvar2=value2&postvar3=value3");
// In real life you should use something like:
// curl_setopt($ch, CURLOPT_POSTFIELDS,
// http_build_query(array('postvar1' => 'value1')));
// Receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close ($ch);
// Further processing ...
if ($server_output == "OK") { ... } else { ... }
?>
Gewijzigd op 07/03/2019 12:39:11 door - Ariën -
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?
Gewijzigd op 07/03/2019 14:44:22 door - Ariën -
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?
Omdat cURL behoorlijk flexibeler is, gebruik ik nu haast altijd cURL.
Gewijzigd op 07/03/2019 15:57:35 door - Ariën -
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.
Gewijzigd op 07/03/2019 18:59:59 door Thomas van den Heuvel
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fwrite($rConnect,"POST ".$aUrl['path']." HTTP/1.1\r\n");
fwrite($rConnect,"Host: ".$aUrl['host']."\r\n");
fwrite($rConnect,"Accept: */*\r\n");
fwrite($rConnect,"User-Agent: SomeTool/2.0\r\n");
fwrite($rConnect,"Content-type: application/x-www-form-urlencoded\r\n");
fwrite($rConnect,"Content-length: ".strlen($sData)."\r\n\r\n");
fwrite($rConnect,$sData."\r\n\r\n");
stream_set_timeout($rConnect,10);
$aInfo = stream_get_meta_data($rConnect);
$sFileData = "";
// get response
while(!feof($rConnect) && !$aInfo['timed_out']){
$sFileData .= fread($rConnect,4096);
$aInfo = stream_get_meta_data($rConnect);
}
fclose($rConnect);
fwrite($rConnect,"Host: ".$aUrl['host']."\r\n");
fwrite($rConnect,"Accept: */*\r\n");
fwrite($rConnect,"User-Agent: SomeTool/2.0\r\n");
fwrite($rConnect,"Content-type: application/x-www-form-urlencoded\r\n");
fwrite($rConnect,"Content-length: ".strlen($sData)."\r\n\r\n");
fwrite($rConnect,$sData."\r\n\r\n");
stream_set_timeout($rConnect,10);
$aInfo = stream_get_meta_data($rConnect);
$sFileData = "";
// get response
while(!feof($rConnect) && !$aInfo['timed_out']){
$sFileData .= fread($rConnect,4096);
$aInfo = stream_get_meta_data($rConnect);
}
fclose($rConnect);
Output nog steeds hetzelfde.
$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.
Gewijzigd op 07/03/2019 20:10:52 door Klaas Sjaak
Probeer het anders zo eens (wel even host en doelscript aanpassen):
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?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>';
?>
// 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:
Code (php)
Dit werkt bij mij prima, en produceert niet ongevraagd output.
Dit produceert bij mij het volgende:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
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"}
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"}
Gewijzigd op 08/03/2019 00:06:18 door Thomas van den Heuvel
Toevoeging op 08/03/2019 19:46:05:
Jammer dat er geen reputatie systeem op dit forum is, jullie verdienen een dikke pluim.
Problem solved!
Nogmaals bedankt. :)