TS: HTTP und Seiten-Lade-Funktion

0 49

HTTP und Seiten-Lade-Funktion

TS
  • https
  • php
  1. 0

    HTTP und Seiten-Lade-Funktion, Nachtrag

    TS
    1. 0

      HTTP und Seiten-Lade-Funktion, chunked

      TS
      1. 0
        dedlfix
        1. 0
          TS
          1. 0
            dedlfix
            1. 0
              TS
            2. 0
              Jörg Reinholz
          2. 0
            Der Martin
            • https
            1. 0
              Jörg Reinholz
              1. 0
                TS
                • https
                • php
                • webserver
                1. 0
                  Jörg Reinholz
          3. 0
            woodfighter
            1. 0
              TS
              1. 0
                Jörg Reinholz
                1. 0
                  TS
                  1. 0
                    Der Martin
                    1. 0

                      HTTP und Seiten-Lade-Funktion, Unterschiede?

                      TS
                  2. 0
                    Jörg Reinholz
                    1. 0

                      HTTP und Seiten-Lade-Funktion, Blinker

                      TS
  2. 0
    Jörg Reinholz
    1. 0
      TS
      1. 0
        Jörg Reinholz
        1. 0
          TS
          1. 0
            Jörg Reinholz
  3. 0

    Billige Teillösung - typisch PHP

    TS
    1. 0
      dedlfix
      1. 0
        Tabellenkalk
        • meinung
        1. 0
          Der Martin
          1. 0

            [LÖSUNG], wie immer ein PHP-Bug/Unsinnigkeit

            TS
            • php
            • zur info
            1. 0
              Jörg Reinholz
              1. 0
                TS
                1. 0
                  Jörg Reinholz
                  1. 0
                    TS
                    1. 0
                      Jörg Reinholz
            2. 0
              dedlfix
        2. 0
          TS
          1. 0
            TS
            1. 0
              Jörg Reinholz
              1. 0
                TS
                • php
                • zur info
                1. 0
                  Jörg Reinholz
                  1. 0
                    TS
                    1. 0
                      Jörg Reinholz
                      1. 0

                        Encoding, htmlspecialchars()

                        TS
                        1. 0
                          Jörg Reinholz
                          1. 0
                            Tabellenkalk
                            • zur info
                            1. 0
                              Tabellenkalk
  4. 0

    Bei welchen HTTP Status Codes muss Body gelesen werden?

    TS
    1. 0
      dedlfix

Hallo und guten Morgen,

ich habe mir da eine Requestfunktion zusammengebastelt, die leider nicht bei allen Seiten funktioniert. Es gibt welche, da kommen nur die Header und kein Content.

Bei http://forum.selfhtml.org steht über dem Content "1c82" und darunter eine "0".

Leider finde ich den Fehler nicht, bzw. verstehe die Logik nicht, nach der bei manchen Requests eben nur die Header kommen.

<?php  ### get_page.php 

#==================================================================================================
function get_page($url, $format=0) 
{
    $url = parse_url($url);
    $host = isset($url['host']) ? $url['host'] : '';
    $port = isset($url['port']) ? $url['port'] : 80;
    $path = (isset($url['path']) ? $url['path'] : '/') . (isset($url['query']) ? '?' . $url['query'] : '');

    $fp = fsockopen($host, $port, $errno, $errstr, 3);
    if ($fp)
    {
        $hdr = "GET $path HTTP/1.1\r\n";
        $hdr .= "Host: $host \r\n";
#        $hdr .= "Cookie: PHPSESSID=9d97b2ff179ed2e6897a197a2c6a0785"; 
        $hdr .= "Connection: Keep-Alive\r\n\r\n";
        fwrite($fp, $hdr);

		$headerflag = true;	
        $body = '';
        $_headers = array();
        
        while (!feof($fp) && (false !== ($line = fgets($fp, 1024))))
        {
			if ($headerflag)
			{
				if ($line == "\r\n") 
                {    
                    $headerflag = false;
                    continue;
                }
                
                $line = trim($line);
				$_headerline = explode(': ', $line, 2);

				if ($format)
				{
					if (isset($_headerline[1]))
					{
						$_headers[$_headerline[0]] = $_headerline[1];
					}	
					elseif (strpos(strtoupper($_headerline[0]), 'HTTP') === 0 )
					{
                        $_http = explode(' ', $_headerline[0]);
                        $_headers['version'] = $_http[0];
                        $_headers['status']  = (isset($_http[1])?$_http[1]:'900');
                        $_headers['message'] = (isset($_http[2])?$_http[2]:'');
                    }
                    else
                    {    
                        $_headers[] = $_headerline[0];
					}
				}	
				else 
				{
					$_headers[] = $line;
				}	
            }    
			else
			{
				$body .= $line;
			}	
        }

        fclose($fp);
        return array('headers' => $_headers, 'body' => $body);
    }

    return false;
}

#==================================================================================================

$_page = get_page('http://forum.selfhtml.org', 1);

echo "<pre>\r\n";
echo htmlspecialchars(print_r($_page['headers'], 1)) . "\r\n";
echo "<hr>\r\n";
echo htmlspecialchars($_page['body']);
echo "</pre>\r\n";

?>

Grüße
TS

akzeptierte Antworten

  1. Hallo und guten Morgen,

    Hallo und guten Morgen,

    ich habe mir da eine Requestfunktion zusammengebastelt, die leider nicht bei allen Seiten funktioniert. Es gibt welche, da kommen nur die Header und kein Content.

    Bei http://forum.selfhtml.org steht über dem Content "1c82" und darunter eine "0".

    Leider finde ich den Fehler nicht, bzw. verstehe die Logik nicht, nach der bei manchen Requests eben nur die Header kommen.

    <?php  ### get_page.php 
    
    #==================================================================================================
    function get_page($url, $format=0) 
    {
        $url = parse_url($url);
        $host = isset($url['host']) ? $url['host'] : '';
        $port = isset($url['port']) ? $url['port'] : 80;
        $path = (isset($url['path']) ? $url['path'] : '/') . (isset($url['query']) ? '?' . $url['query'] : '');
    
        $fp = fsockopen($host, $port, $errno, $errstr, 3);
        if ($fp)
        {
            $hdr = "GET $path HTTP/1.1\r\n";
            $hdr .= "Host: $host \r\n";
    #        $hdr .= "Cookie: PHPSESSID=9d97b2ff179ed2e6897a197a2c6a0785"; 
            $hdr .= "Connection: Keep-Alive\r\n\r\n";
            fwrite($fp, $hdr);
    
    		$headerflag = true;	
            $body = '';
            $_headers = array();
            
            while (!feof($fp) && (false !== ($line = fgets($fp, 1024))))
            {
    			if ($headerflag)
    			{
    				if ($line == "\r\n") 
                    {    
                        $headerflag = false;
                        continue;
                    }
                    
                    $line = trim($line);
    				$_headerline = explode(': ', $line, 2);
    
    				if ($format)
    				{
    					if (isset($_headerline[1]))
    					{
    						$_headers[$_headerline[0]] = $_headerline[1];
    					}	
    					elseif (strpos(strtoupper($_headerline[0]), 'HTTP') === 0 )
    					{
                            $_http = explode(' ', $_headerline[0]);
                            $_headers['version'] = $_http[0];
                            $_headers['status']  = (isset($_http[1])?$_http[1]:'900');
                            $_headers['message'] = (isset($_http[2])?$_http[2]:'');
                        }
                        else
                        {    
                            $_headers[] = $_headerline[0];
    					}
    				}	
    				else 
    				{
    					$_headers[] = $line;
    				}	
                }    
    			else
    			{
    				$body .= $line;
    			}	
            }
    
            fclose($fp);
            return array('headers' => $_headers, 'body' => $body);
        }
    
        return false;
    }
    
    #==================================================================================================
    
    $_page = get_page('http://forum.selfhtml.org', 1);
    
    echo "<pre>\r\n";
    echo htmlspecialchars(print_r($_page['headers'], 1)) . "\r\n";
    echo "<hr>\r\n";
    echo htmlspecialchars($_page['body']);
    echo "</pre>\r\n";
    
    ?>
    
    

    mit dem Simpelscript bekomme ich bei den Requests allerdings Antwort:

    <?php
    
    echo  file_get_contents('http://example.org');
    
    ?>
    

    Was macht denn file_get_contents da anders?

    Grüße
    TS

    1. Hallo und guten Morgen,

      ich habe mir da eine Requestfunktion zusammengebastelt, die leider nicht bei allen Seiten funktioniert. Es gibt welche, da kommen nur die Header und kein Content.

      Bei http://forum.selfhtml.org steht über dem Content "1c82" und darunter eine "0".

      Ok, so weit bin ich inzwischen: die Zahlen stehen für die Chunks.
      Wie muss ich die in die Funktion einbauen?
      Also wenn der Header "transfer-encoding: chunked" vorhanden ist, muss das berücksichtigt werden.

      Leider habe ich immer noch keine Idee, wieso einige Seiten überhaupt keinen Content-Body liefern.

      Grüße
      TS

      1. Tach!

        Bei http://forum.selfhtml.org steht über dem Content "1c82" und darunter eine "0".

        Ok, so weit bin ich inzwischen: die Zahlen stehen für die Chunks.

        Willkommen bei HTTP 1.1. Die Version 1.0 war wenigstens noch ungechunkt. Wenn du das Protokoll wirklich selbst sprechen willst, musst du es ordentlich implementieren.

        Leider habe ich immer noch keine Idee, wieso einige Seiten überhaupt keinen Content-Body liefern.

        Was für einen Statuscode liefern die denn?

        dedlfix.

        1. Hallo und guten Morgen,

          Bei http://forum.selfhtml.org steht über dem Content "1c82" und darunter eine "0".

          Ok, so weit bin ich inzwischen: die Zahlen stehen für die Chunks.

          Willkommen bei HTTP 1.1. Die Version 1.0 war wenigstens noch ungechunkt. Wenn du das Protokoll wirklich selbst sprechen willst, musst du es ordentlich implementieren.

          Leider habe ich immer noch keine Idee, wieso einige Seiten überhaupt keinen Content-Body liefern.

          Was für einen Statuscode liefern die denn?

          200 OK
          Das ist ja das Ulkige.

          Array
          (
              [version] => HTTP/1.1
              [status] => 200
              [message] => OK
              [date] => tue, 16 jun 2015 12:43:16 gmt
              [server] => apache
              [x-powered-by] => php/4.4.9
              [expires] => thu, 19 nov 1981 08:52:00 gmt
              [cache-control] => no-store, no-cache, must-revalidate, post-check=0, pre-check=0
              [pragma] => no-cache
              [set-cookie] => phpsessid=3040775efe7be894b7915216a5625e49; path=/
              [vary] => user-agent,accept-encoding
              [connection] => close
              [content-type] => text/html
          )
          

          Das wäre allerdings auch eine Lösung. Einfach nur HTTP/1.0 zu requesten. Was handele ich mir denn damit ggf. an anderen Problemen ein?

          Geht aber auch nicht. Der Server antwortet trotzdem mit HTTP/1.1

          Grüße
          TS

          1. Tach!

            Leider habe ich immer noch keine Idee, wieso einige Seiten überhaupt keinen Content-Body liefern.

            Was für einen Statuscode liefern die denn?

            200 OK

            Vielleicht hat da das PHP einfach nur seine Arbeit vorzeitig eingestellt.

            [x-powered-by] => php/4.4.9
            

            Das ist ja auch schon recht betagt. Ein Wunder, dass es überhaupt noch lebt.

            dedlfix.

            1. Hallo und guten Morgen,

              Leider habe ich immer noch keine Idee, wieso einige Seiten überhaupt keinen Content-Body liefern.

              Was für einen Statuscode liefern die denn?

              200 OK

              Vielleicht hat da das PHP einfach nur seine Arbeit vorzeitig eingestellt.

              [x-powered-by] => php/4.4.9
              

              Das ist ja auch schon recht betagt. Ein Wunder, dass es überhaupt noch lebt.

              Hab ich auch schon drüber gegrinst.
              Aber mit der Simpellösung mit file_get_contents( ... ) kommt ja der erwartete Content.

              Grüße
              TS

            2. Moin!

              Das ist ja auch schon recht betagt. Ein Wunder, dass es überhaupt noch lebt.

              Dann schau mal zu den "selbst ernannten europäischen Marktführen"

              Jörg Reinholz

          2. Hallo,

            Was für einen Statuscode liefern die denn?

            200 OK
            Das ist ja das Ulkige.

            Array
            (
                [version] => HTTP/1.1
                [status] => 200
                [message] => OK
                [date] => tue, 16 jun 2015 12:43:16 gmt
                [server] => apache
                [x-powered-by] => php/4.4.9
                [expires] => thu, 19 nov 1981 08:52:00 gmt
                [cache-control] => no-store, no-cache, must-revalidate, post-check=0, pre-check=0
                [pragma] => no-cache
                [set-cookie] => phpsessid=3040775efe7be894b7915216a5625e49; path=/
                [vary] => user-agent,accept-encoding
                [connection] => close
                [content-type] => text/html
            )
            

            und kein Content-Length. Das finde ich eigenartig.

            Das wäre allerdings auch eine Lösung. Einfach nur HTTP/1.0 zu requesten. Was handele ich mir denn damit ggf. an anderen Problemen ein?

            AFAIS keine. HTTP/1.1 hat ein paar Erweiterungen (Chunking ist eine davon), aber mir fällt keine ein, die man im Alltag unbedingt bräuchte, gerade wenn man das System einfach haben möchte.

            Geht aber auch nicht. Der Server antwortet trotzdem mit HTTP/1.1

            Das darf er aber nicht. Er kann nicht einfach von sich aus eine höhere Protokoll-Version nutzen als der Client zu sprechen und zu verstehen behauptet.

            So long,
             Martin

            1. Moin!

              Geht aber auch nicht. Der Server antwortet trotzdem mit HTTP/1.1

              Das darf er aber nicht. Er kann nicht einfach von sich aus eine höhere Protokoll-Version nutzen als der Client zu sprechen und zu verstehen behauptet.

              Scheint den Apache und den Ngnix nicht zu interssieren:

              fastix@trainer:~$ nc -C localhost 80
              GET /test/ HTTP/1.0
              
              HTTP/1.1 200 OK
              Date: Tue, 16 Jun 2015 18:37:52 GMT
              Server: Apache/2.4.7 (Ubuntu)
              …
              

              Er sendet 1.1 - ob er es benutzt? Keine Ahnung.

              Jörg Reinholz

              1. Hallo und guten Abend,

                Geht aber auch nicht. Der Server antwortet trotzdem mit HTTP/1.1

                Das darf er aber nicht. Er kann nicht einfach von sich aus eine höhere Protokoll-Version nutzen als der Client zu sprechen und zu verstehen behauptet.

                Scheint den Apache und den Ngnix nicht zu interssieren:

                Sieht so aus. Die antworten alle mit HTTP/1.1, verzichten aber trotzdem auf die Zusatzoptionen, also z.B. auf das Chunked.

                Ich bekomme einfach nicht raus, was file_get_contents() und mein get_page() noch anders machen im Request. File_get_contents() bekommt eine Antwort, meine Funktion aber nicht, auch wenn ich alles rausschmeiße, was noch Verdächtig sein könnte.

                Grüße
                TS

                1. Moin!

                  Ich bekomme einfach nicht raus, was file_get_contents() und mein get_page() noch anders machen im Request. File_get_contents() bekommt eine Antwort, meine Funktion aber nicht, auch wenn ich alles rausschmeiße, was noch Verdächtig sein könnte.

                  Es gibt gute Gründe, warum man die fertigen Funktionen benutzen soll. Macht schon mal weniger Arbeit ... und dann wäre noch der, dass man nicht in irgendwelchen Foren irgendwelchen Heinis die Frage nach der betroffenen URL beantworten muss :)

                  Jörg Reinholz

          3. Tach,

            Was für einen Statuscode liefern die denn?

            200 OK
            Das ist ja das Ulkige.

            was schickst du denn an Headern? Vielleicht missfällt den Seiten z.B. dein User Agent. Über die 200 im Fehlerfall würde ich mich nicht übermäßig wundern, Randfälle wie Fehler werden häufig beim Entwickeln vergessen und gerade bei PHP hat man häufig schon einen 200er Header geschickt bevor die eigentliche Bearbeitung begonnen hat.

            Das wäre allerdings auch eine Lösung. Einfach nur HTTP/1.0 zu requesten. Was handele ich mir denn damit ggf. an anderen Problemen ein?

            Der wesentlichste Unterschied dürfte der keep-alive sein, aber den hast du eh nicht implemntiert, wie es aussieht.

            Geht aber auch nicht. Der Server antwortet trotzdem mit HTTP/1.1

            Vielleicht kann der Server kein HTTP 1.0, aber prüft das beim Request nicht ab? Ich kann in der HTTP 1.0 RFC zumindest nichts sehen, dass es verbietet mit einer anderen Version zu antworten, auf HTTP 0.9 wird sogar extra Rücksicht genommen. Die HTTP 1.0 Spec verbietet es mit einem 1.0 Header zu antworten, wenn die Nachricht HTTP 1.1 Features benötigt.

            mfg
            Woodfighter

            1. Hallo und guten Abend,

              Was für einen Statuscode liefern die denn?

              200 OK
              Das ist ja das Ulkige.

              was schickst du denn an Headern? Vielleicht missfällt den Seiten z.B. dein User Agent.

              Ich habe meine Funktionnu nd file_get_contents() jetzt mehrfach verglichen mittels Darstellung von $_SERVER und $_COOKIE. Da ist kein Unterschied mehr zu sehen.

              Allerdings weiß ich nicht, wie ich an die echten Request-Header rankomme. getallheaders() liefert nur den HOST, was aber bei Vergleich mit dem $_SERVER-Array sogar zu stimmen scheint.

              Ein User-Agent-Header war gar nicht vorhanden. Wenn ich einen setze, z.B.

              User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
              

              interessiert das die betroffenen Seiten auch nicht.

              Über die 200 im Fehlerfall würde ich mich nicht übermäßig wundern, Randfälle wie Fehler werden häufig beim Entwickeln vergessen und gerade bei PHP hat man häufig schon einen 200er Header geschickt bevor die eigentliche Bearbeitung begonnen hat.

              Es kommt aber auch für den Socket eine Error-Nummer 0 zurück. Da bricht also nichts einfach ab. Es kommt nur kein Content.

              Grüße
              TS

              1. Moin!

                Es kommt aber auch für den Socket eine Error-Nummer 0 zurück. Da bricht also nichts einfach ab. Es kommt nur kein Content.

                Ja. Solche Fehler kann man ganz schnell machen.

                Jörg Reinholz

                1. Hallo und guten Abend,

                  Es kommt aber auch für den Socket eine Error-Nummer 0 zurück. Da bricht also nichts einfach ab. Es kommt nur kein Content.

                  Ja. Solche Fehler kann man ganz schnell machen.

                  Verstehe ich jetzt nicht.
                  Error-Nummer 0 bedeutet: kein Fehler.
                  Und wenn fsockopen nicht arbeiten würde, würden auch keine HTTP-Header mehr angezeigt werden.

                  Grüße
                  TS

                  1. Hallo,

                    Solche Fehler kann man ganz schnell machen.

                    Verstehe ich jetzt nicht.
                    Error-Nummer 0 bedeutet: kein Fehler.

                    genauer: Kein Fehler an deinem Ende der Verbindung. Es kann aber durchaus sein, dass auf der Serverseite irgendein logischer Fehler auftritt, vielleicht weil der Programmierer des Scripts bestimmte Header erwartet hat, die du nicht sendest (z.B. ein User-Agent oder ein Referer), den Fehler nicht ordnungsgemäß abfängt und stattdessen einfachsein Script sterben lässt. Ergebnis könnte ein Schließen der Verbindung ohne Fehler sein, wenn du es noch nicht erwartest.

                    Und wenn fsockopen nicht arbeiten würde, würden auch keine HTTP-Header mehr angezeigt werden.

                    Richtig. Also kommt eine Socket-Verbindung zustande, und das Script am anderen Ende der Verbindung tut auch irgendwas. Nur wird es damit möglicherweise nicht fertig.

                    So long,
                     Martin

                    1. Hallo und guten Morgen Martin,

                      Verstehe ich jetzt nicht.
                      Error-Nummer 0 bedeutet: kein Fehler.

                      genauer: Kein Fehler an deinem Ende der Verbindung. Es kann aber durchaus sein, dass auf der Serverseite irgendein logischer Fehler auftritt, vielleicht weil der Programmierer des Scripts bestimmte Header erwartet hat, die du nicht sendest (z.B. ein User-Agent oder ein Referer), den Fehler nicht ordnungsgemäß abfängt und stattdessen einfachsein Script sterben lässt. Ergebnis könnte ein Schließen der Verbindung ohne Fehler sein, wenn du es noch nicht erwartest.

                      Und wenn fsockopen nicht arbeiten würde, würden auch keine HTTP-Header mehr angezeigt werden.

                      Richtig. Also kommt eine Socket-Verbindung zustande, und das Script am anderen Ende der Verbindung tut auch irgendwas. Nur wird es damit möglicherweise nicht fertig.

                      Und warum kann der Server dann auf file_get_contents() eine Antwort liefern?

                      Ich habe die Funktion soweit kastriert, dass sie nur noch den HOST-Header sendet, genauso, wie das file_get_contents() bei mir tut. Das habe ich mir mit den Mitteln von PHP und meinen eigenen Server-Log (externer Server, also gleiche Voraussetzungen, wie beim fremden befragten Server) angesehen.

                      Woraus der Programmierer des Scriptes am besagten fremden Server nun noch erkennen will, ob ich mittels file_get_contents(), oder mittels meines get_page() zugreife, kann ich einfach nicht herausfinden.

                      Grüße
                      TS

                  2. Moin!

                    Es kommt aber auch für den Socket eine Error-Nummer 0 zurück. Da bricht also nichts einfach ab. Es kommt nur kein Content.

                    Ja. Solche Fehler kann man ganz schnell machen.

                    Verstehe ich jetzt nicht.

                    Es ging nicht um Dich sondern um den Betreiber des Servers, bei Du grabben willst.

                    Jörg Reinholz

                    1. Hallo und guten Morgen,

                      Es kommt aber auch für den Socket eine Error-Nummer 0 zurück. Da bricht also nichts einfach ab. Es kommt nur kein Content.

                      Ja. Solche Fehler kann man ganz schnell machen.

                      Verstehe ich jetzt nicht.

                      Es ging nicht um Dich sondern um den Betreiber des Servers, bei Du grabben willst.

                      Aaaach so!

                      Jetzt verstehe ich auch den Blinker. Aber dann müsste der ja auch "blinken", wenn ich beliebig oft mit file_get_contents() die Inhalte abhole.

                      Da gibts noch einen Trick, den ich noch nicht kenne und mir auch nicht vorstellen kann :-O

                      Grüße
                      TS

  2. Moin!

    Zu erst habe ich das mal sauber eingerückt ...

    <?php  ### get_page.php
    
    #==================================================================================================
    function get_page($url, $format=0) {
        $url = parse_url($url);
        $host = isset($url['host']) ? $url['host'] : '';
        $port = isset($url['port']) ? $url['port'] : 80;
        $path = (isset($url['path']) ? $url['path'] : '/') . (isset($url['query']) ? '?' . $url['query'] : '');
    
        $fp = fsockopen($host, $port, $errno, $errstr, 3);
        if ($fp) {
            $hdr = "GET $path HTTP/1.1\r\n";
            $hdr .= "Host: $host \r\n";
    #        $hdr .= "Cookie: PHPSESSID=9d97b2ff179ed2e6897a197a2c6a0785";
            $hdr .= "Connection: Keep-Alive\r\n\r\n";
            fwrite($fp, $hdr);
            $headerflag = true;
            $body = array();
            $_headers = array();
    
            while (!feof($fp) && (false !== ($line = fgets($fp, 1024))))  {
                if ($headerflag)  {
                    if ($line == "\r\n") {
                        $headerflag = false;
                    } else {
                        $line = trim($line);
                        $_headerline = explode(': ', $line, 2);
                        if ($format)  {
                            if (isset($_headerline[1]))  {
                                $_headers[$_headerline[0]] = $_headerline[1];
                            } elseif (strpos(strtoupper($_headerline[0]), 'HTTP') === 0 )  {
                                $_http = explode(' ', $_headerline[0]);
                                $_headers['version'] = $_http[0];
                                $_headers['status']  = (isset($_http[1])?$_http[1]:'900');
                                $_headers['message'] = (isset($_http[2])?$_http[2]:'');
                            } else {
                                $_headers[] = $_headerline[0];
                            }
                        }  else   {
                            $_headers[] = $line;
                        }
                    }
                } else {
                    $body[] = $line;
                }
            }
    
            fclose($fp);
            return array('headers' => $_headers, 'body' => $body);
        }
    
        return false;
    }
    
    #================================================================================================
    
    $_page = get_page('http://forum.selfhtml.org', 1);
    
    var_dump($_page['headers']);
    
    array_shift($_page['body']);
    array_pop($_page['body']);
    array_pop($_page['body']);
    
    echo implode('', $_page['body']);
    

    ein wenig bereinigt und manches auch so verrückt ... und dann gesehen: geht doch. Warum jetzt manchmal nur ein header kommt und kein Inhalt? Was steht denn dann in den headern?

    Jörg Reinholz

    1. Hallo und guten Abend,

      Zu erst habe ich das mal sauber eingerückt ...

      und Fehler reingebaut... :-O Das continue stand da z.B. nicht sinnlos.

      und dann gesehen: geht doch. Warum jetzt manchmal nur ein header kommt und kein Inhalt? Was steht denn dann in den headern?

      Klar, bei allen Seiten geht es, nur nicht bei denen, bei denen es drauf ankommt (URL kann ich hier nicht posten).

      Um das nochmal klar zu schreiben: wenn cih die betroffeneen Seiten mit file_get_contents() abfrage, bekomme ich die Antwort. Das nützt mir aber nichts, weil ich auch die Header benötige und das Spiel erst anfängt, wenn ich den Fehler*) gefunden habe.

      *) der Fehler ist wohl eher ein Trick der abfragten Seiten, die Auslieferung zu vermeiden.

      Ich bekomme die Response-Header:

      Array
      (
          [version] => HTTP/1.1
          [status] => 200
          [message] => OK
          [date] => Tue, 16 Jun 2015 18:58:13 GMT
          [server] => Apache
          [x-powered-by] => PHP/4.4.9
          [expires] => Thu, 19 Nov 1981 08:52:00 GMT
          [cache-control] => no-store, no-cache, must-revalidate, post-check=0, pre-check=0
          [pragma] => no-cache
          [set-cookie] => PHPSESSID=***; path=/
          [vary] => User-Agent,Accept-Encoding
          [connection] => close
          [content-type] => text/html
      )
      

      Session-ID habe ich jetzt mal rausgenommen

      Grüße
      TS

      1. Moin!

        Ach so. Ja klar. Es kann natürlich sein, dass die die Bearbeitung einfach abbrechen, z.B. weil der Useragent nicht gefällt. Wobei die ja scheinbar mit dem PHP nicht wirklich ein Problem haben. versuche also mal die Abfrage-Zeilen so zu vervollständigen, wie die Entwicklerwerkzeuge den Request anzeigen.

        Probieren: curl oder wget (-d zeigt header) $tempfile benutzen, alles senden senden, was firefox, opera, ie, safari & co auch senden.

        Was ich auch nachsehen würde: Einfach mal mit file_get_contents und Deinem Skript auf ein eigenes Skript schießen, welches dann nur $_SERVER dumpt.

        Jörg Reinholz

        1. Hallo und guten Abend,

          Was ich auch nachsehen würde: Einfach mal mit file_get_contents und Deinem Skript auf ein eigenes Skript schießen, welches dann nur $_SERVER dumpt.

          Das habe ich doch schon lange getan. Da ist auch mit meinen Mitteln kein Unterschied mehr feststellbar. Wier kann ich den (auf einem eigenen Host) ALLE Request-Header mitloggen?

          Realistisch wäre gewesen, dass sie mich bereits ausgesperrt hätten. Aber dann würde ja auf file_get_contents() auch kein Response-Body kommen.

          Grüße
          TS

          1. Moin!

            Realistisch wäre gewesen, dass sie mich bereits ausgesperrt hätten. Aber dann würde ja auf file_get_contents() auch kein Response-Body kommen.

            Nicht unrealistisch ist, dass Du den Fehler einfach nicht mehr siehst und auch keinen Hinweis bekommst und deshalb die Webseite für einen Blinker hältst. Geht. Geht nicht. Geht ...

            Um das auszuschließen: Mach morgen weiter.

            Jörg Reinholz

  3. Hallo und gute Nacht,

    keine wirkliche Lösung des Problems aber eine typische PHP-Billiglösung habe ich gefunden.

    <?php
    
    $content = file_get_contents('http://forum.selfhtml.org/');
    
    echo "<pre>\r\n";
    echo htmlspecialchars(print_r($http_response_header, 1)) . "\r\n";
    echo "</pre>\r\n";
    echo "<hr>\r\n";
    echo $content;
    
    ?>
    

    Da fasst man sich an den Kopf. Mit einem Zweizeiler kann ich einen Teil der Aufgabe erledigen, an der ich nun die ganze Zeit rumgeeiert habe.

    WARUM der andere Ansatz bei dem speziellen Host nicht funktioniert, wird aber trotzdem noch Aufgabe bleiben. Dazu müsste ich nun wohl die Implementation von file_get_contents() und von fgets() über Socket vergleichen, oder wie würdet Ihr da vorgehen, um des Rätsels Lösung zu erforschen?

    Grüße
    TS

    1. Tach!

      WARUM der andere Ansatz bei dem speziellen Host nicht funktioniert, wird aber trotzdem noch Aufgabe bleiben. Dazu müsste ich nun wohl die Implementation von file_get_contents() und von fgets() über Socket vergleichen, oder wie würdet Ihr da vorgehen, um des Rätsels Lösung zu erforschen?

      Im Zweifelsfall mit dem Leitungshai die Pakete mitschneiden oder auf andere Weise die Request-Header ermitteln und beide Varianten vergleichen.

      dedlfix.

      1. Hallo,

        Leitungshai

        ich hätte ihn mit Drahthai übersetzt.

        Gruß
        Kalk

        PS: mir fehlt "Übersetzung" als tag

        1. Moin,

          Leitungshai

          ich hätte ihn mit Drahthai übersetzt.

          das wäre die wörtlich(st)e Übersetzung.

          Bei mir heißt das Ding salopp Kabeljau. ;-)

          So long,
           Martin

          1. Hallo und guten Morgen,

            der Fehler steckte nicth in der Funktion.
            Erst nachdem ich mittels Whireshark sehen konnte, dass da ein Content-Body gesendet wurde, und dann nochmal genau hingesehen habe, was ich eigentlich ausgebe, bin ich auf die Lösung gekommen.

            Bei der Billigversion habe ich einfach nur

            echo $content;
            

            geschrieben, was dann dazu geführt hat, dass der Browser sofort noch die Sekundärrequests ausgeführt hat, was aber unbemerkt blieb, weil z.B. der Urchin-Tracker oder auch die Images auf meinem Testserver nicht zu finden sind ...

            Bei meiner Funktion hatte ich hingegen geschrieben

            echo htmlspecialchars($_page['body']);
            

            was dazu führte, dass keine Anzeige erfolgte.

            Warum?
            Weil PHP hier eine Macke hat!

            echo htmlspecialchars($_page['body'],  ENT_QUOTES, 'ISO-8859-1');
            

            Man muss für htmlspecialchars neuerdings eine Codierung angeben, damit es zuverlässig arbeitet. Ulkigerweise produziert es manchmal eine Ausgabe und manchmal nicht. Auch die Einstellung

            ini_set('default_charset', $charset);
            

            ändert leider nichts daran.

            Ich hatte diesen merkwürdingen Fehler neulich schon mal, und habe ihn mir eben leider nicht gemerkt. Da ich noch nicht herausgefunden habe, wann htmlspecialchars() nun noch arbeitet und wann nicht, muss ich also erst einmal alle wesentlichen Skripte nacharbeiten und die Parameter ergänzen.

            BTW: hier wäre jetzt der Tag "Bug?" angebracht. Und später dann vielleicht noch "Bug!" ;-))

            Grüße
            TS

            1. Moin!

              Ich hatte diesen merkwürdingen Fehler neulich schon mal, und habe ihn mir eben leider nicht gemerkt. Da ich noch nicht herausgefunden habe, wann htmlspecialchars() nun noch arbeitet und wann nicht, muss ich also erst einmal alle wesentlichen Skripte nacharbeiten und die Parameter ergänzen.

              BTW: hier wäre jetzt der Tag "Bug?" angebracht. Und später dann vielleicht noch "Bug!" ;-))

              Laut Dokumentation liefert htmlspecialchars() einen leeren String, wenn es "glaubt"

              ini_get("default_charset")

              in der Kodierung "A" zu arbeiten, aber einen String verarbeiten soll, der in der Kodierung "B" ist und Zeichen enthält, die in der Kodierung "A" nicht vorgesehen sind.

              Das ergibt sich allerdings nur wenn man wirklich alles liest:

              • **ENT_IGNORE **: Verwirft ungültige Code Unit Sequenzen anstatt eine leere Zeichenkette zurückzugeben. Die Nutzung dieser Option ist nicht empfehlenswert, da sie » Auswirkungen auf die Sicherheit haben kann.
              • ENT_SUBSTITUTE: Ersetzt ungültige Code Unit Sequenzen mit einem Unicode Ersatz Zeichen U+FFFD (UTF-8) oder &#FFFD; (andernfalls) anstatt eine leere Zeichenkette zurückzugeben.

              Ich würde also sagen, nicht das Programm ist "buggy", sondern die Dokumentation, die darauf deutlicher hinwiesen sollte.

              Jörg Reinholz

              1. Hallo und guten Morgen,

                Ich hatte diesen merkwürdingen Fehler neulich schon mal, und habe ihn mir eben leider nicht gemerkt. Da ich noch nicht herausgefunden habe, wann htmlspecialchars() nun noch arbeitet und wann nicht, muss ich also erst einmal alle wesentlichen Skripte nacharbeiten und die Parameter ergänzen.

                BTW: hier wäre jetzt der Tag "Bug?" angebracht. Und später dann vielleicht noch "Bug!" ;-))

                Laut Dokumentation liefert htmlspecialchars() einen leeren String, wenn es "glaubt"

                ini_get("default_charset")

                in der Kodierung "A" zu arbeiten, aber einen String verarbeiten soll, der in der Kodierung "B" ist und Zeichen enthält, die in der Kodierung "A" nicht vorgesehen sind.

                Das ergibt sich allerdings nur wenn man wirklich alles liest:

                • **ENT_IGNORE **: Verwirft ungültige Code Unit Sequenzen anstatt eine leere Zeichenkette zurückzugeben. Die Nutzung dieser Option ist nicht empfehlenswert, da sie » Auswirkungen auf die Sicherheit haben kann.
                • ENT_SUBSTITUTE: Ersetzt ungültige Code Unit Sequenzen mit einem Unicode Ersatz Zeichen U+FFFD (UTF-8) oder &#FFFD; (andernfalls) anstatt eine leere Zeichenkette zurückzugeben.

                Ich würde also sagen, nicht das Programm ist "buggy", sondern die Dokumentation, die darauf deutlicher hinwiesen sollte.

                Das Standardverhalten ist durchaus suspekt.
                Überhaupt keine Ausgabe zu liefern, während früher ja immer eine kam, ist schon sehr Benutzer(=Programmierer)-unfreundlich. Man könnte ja zumindest eine auf einen "sicheren Zeichensatz" reduzierte Ausgaben liefern. Die würde einem dann eher naheliegen, dass etwas mit der Ausgabe nicht OK ist.

                Oder besser: man könnte zumindest eine Notice oder eine Warning liefern oder einen Eintrag im Error-Log produzieren. Nichts davon geschieht. Die PHP-Core-Entwickler arbeiten einfach nicht sauber!

                Ich werde htmlspecialchars() jedenfalls jetzt ganz oben auf meine Liste für die Fehlersuche setzen. So unscheinbar diese Funktion daherkommt, so essentiell wichtig ist sie doch für die Sicherheit von Webseiten!

                Grüße
                TS

                1. Moin!

                  Oder besser: man könnte zumindest eine Notice oder eine Warning liefern oder einen Eintrag im Error-Log produzieren. Nichts davon geschieht. Die PHP-Core-Entwickler arbeiten einfach nicht sauber!

                  In dem Punkt bin ich allerdings bei Dir. Eine Warnung oder Notiz wäre hier sehr angebracht, denn wenn PHP Daten sonst ändert warnt es ja auch ... und ich sehe nichts, warum man davon in diesem Fall abgehen sollte.

                  Noch ein Tipp. Wenn Du auf die gelieferten Daten keinen Einfluss hast, die also falsch kodiert sein könnten, dann nimm ENT_SUBSTITUTE.

                  Jörg Reinholz

                  1. Hallo und guten Morgen,

                    Noch ein Tipp. Wenn Du auf die gelieferten Daten keinen Einfluss hast, die also falsch kodiert sein könnten, dann nimm ENT_SUBSTITUTE.

                    Habe ich schon reingenommen.

                    Und hattest Du nicht neulich mal ein ausführlicheres Posting zum Thema mb_detect_encoding() verfasst? Da habe ich doch irgendwas mitgelesen. Leider hab ich es mir nicht gleich gemerkt. Nun suche ich danach.

                    Grüße
                    TS

                    1. Moin!

                      Und hattest Du nicht neulich mal ein ausführlicheres Posting zum Thema mb_detect_encoding() verfasst? Da habe ich doch irgendwas mitgelesen. Leider hab ich es mir nicht gleich gemerkt. Nun suche ich danach.

                      Du hast das "ausführlicheres Posting zum Thema mb_detect_encoding()" ja schon gefunden. Das mag ganz nett sein, hilft in Deiner speziellen Situation aber nicht wirklich weiter, weil die Kodierung mancher Dokumente im Web einfach von irgendwelchen Idioten kaputtgemacht wird.

                      Da steht dann in den Ergebnissen von manchen NICHT-"MARKTFÜHRERN im Qualitätsmanagement bei der Erstellung von Webseiten für KMU" zwar UTF-8 drauf, aber es ist UTF-8 UND Windows-1252 wild gemixt drin. (Oder anders herum - aber kaputt ist kaputt!)

                      Jörg Reinholz

            2. Tach!

              Weil PHP hier eine Macke hat!

              echo htmlspecialchars($_page['body'],  ENT_QUOTES, 'ISO-8859-1');
              

              Man muss für htmlspecialchars neuerdings eine Codierung angeben, damit es zuverlässig arbeitet.

              Oh, das ist ja Mist. Die eigentlich interessanten Zeichen sind alle im ASCII-Bereich. Der ist bei UTF-8 und ISO-8859-1 derselbe. htmlspecialchars() stört sich allem Anschein nach an der nicht korrekten Kodierung der Zeichen, die es gar nicht zu verändern gilt. Es nimmt also UTF-8 an, bekommt eine kaputte Zeichensequenz und stellt ohne ein Wort zu sagen die Arbeit ein und verwirft obendrein noch das bisherige Zwischenergebnis. - Die Beschreibung im Handbuch bestätigt diese Annahme und es gibt noch ein paar Flags, mit denen man sich aus dem Regen zurückziehen und unter die Traufe begeben kann (ENT_IGNORE, ENT_SUBSTITUTE, ENT_DISALLOWED).

              Andererseits muss man zugeben, dass die obige Vereinfachung nur auf ISO-8859-x und UTF-8 und noch ein paar weitere Kodierungen zutrifft. PHP muss aber auch die wirklich kritischen Zweifelsfälle berücksichtigen, und da ist die Ausgabe eines Leerstrings die sicherheitstechnisch wohl beste Alternative, wenn es auch für den Anwender durch die schweigende Ersetzung recht unangenehm ist, solche Fehler zu suchen.

              Warum ist mir das noch nicht aufgefallen? Vermutlich, weil ich nicht mehr mit veralteten Kodierungen zu tun gehabt habe.

              dedlfix.

        2. Hallo und guten Morgen,

          Leitungshai

          ich hätte ihn mit Drahthai übersetzt.

          Habe ihn gerade befragt und kann ziwschen den Requests keinen Unterschied feststellen.

          Allerdings kommt mir da gerade noch eine Idee...

          Grüße
          TS

          1. Hallo und guten Morgen,

            Leitungshai

            ich hätte ihn mit Drahthai übersetzt.

            Habe ihn gerade befragt und kann ziwschen den Requests keinen Unterschied feststellen.

            Allerdings kommt mir da gerade noch eine Idee...

            Der Signalleitungshai sagt mir, dass der Server durchaus eine Response schickt. Leider muss da irgendwas drinstehen, was die Anzeige mit der eigenen get_page()-Funktion unterbindet, während file_get_contents() damit umgehen kann.

            Grüße
            TS

            1. Moin!

              Der Signalleitungshai sagt mir, dass der Server durchaus eine Response schickt. Leider muss da irgendwas drinstehen, was die Anzeige mit der eigenen get_page()-Funktion unterbindet, während file_get_contents() damit umgehen kann.

              Dann stellt sich die Frage, wieso das von Fall zu Fall anders ist. Wie gesagt, wenn Du auf dem angesprochenen Server keine Macht hast, dann wird das "irgendwie schwierig", weil Du auch über Dir unbekannte Fehler eines Dir unbekannten Dritten stolpern kannst.

              Eine von sehr vielen Möglichkeiten: Ist die Response vielleicht gepackt?

              Hier wäre es ja nicht undenkbar, dass der Progger einen Cache programmiert hat, der - in dem Fall, dass für die Response bereits eine gecachte Antwort vorliegt, stets gepackte Daten liefert, also eben nicht prüft, ob das empfangende Programm überhaupt gepackte Daten akzeptiert - und womöglich nicht mal in die header schreibt, dass die Daten gepackt ankommen. Wobei ich in dem Fall Zweifel daran hätte, dass irgendein Client damit klarkommt.

              Ohne die konkreten Daten zu sehen ist das aber ein wüstes Herumraten.

              Jörg Reinholz

              1. Hallo und guten Morgen,

                Der Signalleitungshai sagt mir, dass der Server durchaus eine Response schickt. Leider muss da irgendwas drinstehen, was die Anzeige mit der eigenen get_page()-Funktion unterbindet, während file_get_contents() damit umgehen kann.

                Dann stellt sich die Frage, wieso das von Fall zu Fall anders ist. Wie gesagt, wenn Du auf dem angesprochenen Server keine Macht hast, dann wird das "irgendwie schwierig", weil Du auch über Dir unbekannte Fehler eines Dir unbekannten Dritten stolpern kannst.

                Der Fehler steckt mal wieder ganz woanders, als man dachte... Das hatten wir doch neulich schon einmal bei der Grabbellösung für PTO (Glupto). Und das Thema ist hier durchaus ähnlich.

                LÖSUNG siehe
                http://forum.selfhtml.org/self/2015/jun/16/http-und-seiten-lade-funktion/1643361#m1643361

                Da der böse Bube bei allen Seiten, die eine Codierung per HTTP-Header explizit angeben, sauber arbeitet, muss es wohl ein Bug sein. Eine leere Angabe bei der Codierung ist laut RFC immer noch mit "ISO-8859-1" zu behandeln!

                Grüße
                TS

                1. Moin!

                  Da der böse Bube bei allen Seiten, die eine Codierung per HTTP-Header explizit angeben, sauber arbeitet, muss es wohl ein Bug sein. Eine leere Angabe bei der Codierung ist laut RFC immer noch mit "ISO-8859-1" zu behandeln!

                  Nun ja. Stellt sich die Frage, was passiert, wenn der Webserver behauptet, ISO-8859-1 zu liefern, aber auf Grund von Fehlern des Programmierers dann doch UTF-8 drin steht, was man genau so (oder anders herum) ja auf verdammt vielen Seiten, sogar von selbsternannten "Marktführern" findet.

                  Da das, wenn Du mehrere Seiten abholst, auch nicht immer der Fall sein muss, gabs den Blink-Effekt.

                  Und wieso arbeitest Du eigentlich noch in ISO-8859-1 oder -15?

                  Jörg Reinholz

                  1. Hallo und guten Morgen,

                    Und wieso arbeitest Du eigentlich noch in ISO-8859-1 oder -15?

                    Wieso ich?

                    Ich habe ja nicht meine eigenen Seiten zur Überwachung bereit gestellt. Da ist nix sittenwidriges drauf ;-)

                    Grüße
                    TS

                    1. Moin!

                      Ich habe ja nicht meine eigenen Seiten zur Überwachung bereit gestellt. Da ist nix sittenwidriges drauf ;-)

                      Überwachung von Webseiten? (Auf was denn? Nur Funktion oder auch ungewollte Inhalte wie unbekannte Java-Scripte?)

                      Schöner Auftrag.

                      Jörg Reinholz

                      1. Hallo und guten Morgen,

                        Ich habe ja nicht meine eigenen Seiten zur Überwachung bereit gestellt. Da ist nix sittenwidriges drauf ;-)

                        Überwachung von Webseiten? (Auf was denn? Nur Funktion oder auch ungewollte Inhalte wie unbekannte Java-Scripte?)

                        Es ist so eine Art Suchmaschine.

                        Den Thread habe ich übrigens wiedergefunden:
                        http://forum.selfhtml.org/self/2015/may/11/zeichencodierung-im-dokument-wechseln/1640177#m1640177

                        Fand ich ganz interessant. Sollte man mal fertig gausarbeiten, auch in den Kontext des gestern und heute erlebten setzen und im Wiki in der Abteilung "nützliche Funktionen für PHP" unterbringen, die dafür geschaffen werden sollte.

                        Ich habe mich jetzt erst einmal für

                        $encoding_order = 'ASCII,UTF-16,UTF-8,ISO-8859-15,ISO-8859-1';
                        echo htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, mb_detect_encoding($content, $encoding_order));
                        

                        entschieden, was aber noch auszubauen wäre.

                        Grüße
                        TS

                        1. Moin!

                          $encoding_order = 'ASCII,UTF-16,UTF-8,ISO-8859-15,ISO-8859-1';
                          echo htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, mb_detect_encoding($content, $encoding_order));
                          

                          entschieden, was aber noch auszubauen wäre.

                          Der Topf hat ein Loch. Die Daten kommen aus fremden Quellen. Und wie ich zeigen kann, gibt es solche von einem recht speziellen "europäischen Marktführer in der Erstellung von Webseiten und Webkonzepten für KMU", da sind die Kodierungen auf einer Webseite wild gemischt.

                          Jörg Reinholz

                          1. Hallo,

                            [Jörgs blogspot-Link]

                            In dem Satz

                            Das es im Euroweb-Konzern nicht auf die richtige Weise geschieht beweist das Bildschirmfoto.

                            hast du zwei zusammengehörende Grammatikfehler.

                            Gruß
                            Kalk

                            1. Hallo,

                              hast du zwei zusammengehörende Grammatikfehler.

                              Einen davon hast du inzwischen beseitigt. Dass das "das"; das, das nach dem Komma kommt; ein "dass" sein muss, das wollte ich dir noch mitteilen.

                              Gruß
                              Kalk

  4. Hallo und guten Abend,

    nachdem der Fehler ja nun gefunden wurde:
    Bei welchen HTTP-Status-Codes muss man eigentlich mit einem Content-Body rechnen?

    Ich will die Funktion per Argument (false|true) auch die Um- und Weiterleitungen ausführen lassen, bis dann eben entweder der Content-Body gelesen werden muss oder aber Ende aufgrund des Statuscodes ist. Wie muss ich die berücksichtigen?

    • 200 -> Body lesen -> Ende
    • 3xx -> Location-Header vorhanden? -> nochmal
    • 4xx -> ??
    • 5xx -> abbrechen wegen Fehler
    • ...

    Was mach ich mit "Content-Location:"?

    Bei welchen Statuscodes kann/darf Content enthalten sein und wie ist damit umzugehen? Kann eine Response mit Status 304 trotzdem Content enthalten und wie sollte man dann damit umgehen?

    Wie sollte man mit eigentlich unsinnigen Antworten, also z.B. einer Response umgehen, die 200, Content und trotzdem einen "Location: "-Header enthält?

    Grüße
    TS

    1. Tach!

      Bei welchen HTTP-Status-Codes muss man eigentlich mit einem Content-Body rechnen?

      Im Fehlerfall bei allen.

      Ich will die Funktion per Argument (false|true) auch die Um- und Weiterleitungen ausführen lassen, bis dann eben entweder der Content-Body gelesen werden muss oder aber Ende aufgrund des Statuscodes ist. Wie muss ich die berücksichtigen?

      Die theoretische Antwort steht vielleicht in der RFC. Die praktische lautet: Du musst den Body immer dann berücksichtigen, wenn du dir von dessen Inhalt etwas versprichst. Brauchst du den Content von 4xx/5xx-Statuscodes, also die Fehlermeldungsseite? Manchmal steht da vielleicht auch was interessantes drin.

      Wie sollte man mit eigentlich unsinnigen Antworten, also z.B. einer Response umgehen, die 200, Content und trotzdem einen "Location: "-Header enthält?

      So wie es deinem Anwendungsfall am besten nutzt - welcher auch immer das ist.

      dedlfix.