Gunther: URL Analyse

Hallo werte Selfgemeinde!

Ich möchte zu Übungszwecken die Funktion wie sie bspw. Firebug unter "Netzwerk" bietet nachbauen, d.h. ich möchte zu einer gegebenen URL auswerten

  • Umleitungen Ja|Nein (wenn Ja, wie viele?)
  • Anzahl der HTTP Requests
  • Größe der jeweiligen Resourcen

Meine Idee(n) bezüglich der Umsetzung sehen wiefolgt aus:

  • (HTML) Resource per 'file_get_contents' in String einlesen
  • $http_response_header auswerten
  • eingelesene Datei nach link, script, img, object, video (und welche vergessen?) Elementen durchsuchen, bzw. nach allem, was ein 'src' Attribut hat

Bei externen CSS- und Script-Dateien muss ich diese dann wiederum auf weitere externe Resourcen hin "durchforsten". In CSS-Dateien bspw. nach '@import' und '@font-face' , respektive nach 'src' und 'url' Angaben.

Anhand der Response Header stelle ich ja fest, ob Dateien komprimiert ausgeliefert wurden. Falls ja, bezieht sich die 'content-length' Angabe auf die komprimierte Source?
Wie kann ich dann die unkomprimierte Größe ermitteln?

Bevor ich mich an die Arbeit mache, irgendwelche Meinungen, Ideen & Tipps?
Bin wie immer für alle Anregungen dankbar! :-)

Gruß Gunther

  1. Tach!

    Bei externen CSS- und Script-Dateien muss ich diese dann wiederum auf weitere externe Resourcen hin "durchforsten".

    Erst zur Laufzeit bekannte in Javascript versteckte URLs wirst du nicht mit Parsen herausfinden.

    Anhand der Response Header stelle ich ja fest, ob Dateien komprimiert ausgeliefert wurden. Falls ja, bezieht sich die 'content-length' Angabe auf die komprimierte Source?

    Ja, das ist die Transfer-Länge. Im Zweifelsfall bitte die passende RFC befragen.

    Wie kann ich dann die unkomprimierte Größe ermitteln?

    Du bekommst nur die unkomprimierte Version durchgereicht. Der Webserver packt es bereits aus.

    dedlfix.

    1. Tach!

      Erst zur Laufzeit bekannte in Javascript versteckte URLs wirst du nicht mit Parsen herausfinden.

      Du sprichst bspw. von "Image Preloading"? Ja, solche Sachen kann man so nicht erfassen (das "Problem" haben aber alle mir bekannten Tools), oder kennst du eine Methode mit vertretbarem Aufwand, die solche Fälle auch noch mit einschließt?

      Anhand der Response Header stelle ich ja fest, ob Dateien komprimiert ausgeliefert wurden. Falls ja, bezieht sich die 'content-length' Angabe auf die komprimierte Source?

      Ja, das ist die Transfer-Länge. Im Zweifelsfall bitte die passende RFC befragen.

      Wie kann ich dann die unkomprimierte Größe ermitteln?

      Du bekommst nur die unkomprimierte Version durchgereicht. Der Webserver packt es bereits aus.

      Jetzt bin ich etwas "irritiert"!?
      Wozu dann die Komprimierung? Ich dachte eigentlich, der Browser packts aus ...

      Gruß Gunther

      1. Hallo,

        Du bekommst nur die unkomprimierte Version durchgereicht. Der Webserver packt es bereits aus.
        Jetzt bin ich etwas "irritiert"!?
        Wozu dann die Komprimierung? Ich dachte eigentlich, der Browser packts aus ...

        ja, richtig. Oder allgemeiner: Der Client packt's aus.

        Wenn du aber eine Implementierung in PHP vorhast -sonst hättest du das ja nicht als Themengebiet gewählt- dann wird dein Webserver, auf dem PHP läuft, für diese Transaktion zum Client. Und der Webserver (der in deinem Fall Client ist), dekomprimiert die vom Fremdserver abgerufenen Inhalte, bevor er sie an PHP durchreicht.

        Ciao,
         Martin

        --
        Die letzten Worte der Challenger-Crew:
        Lasst doch mal die Frau ans Steuer!
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Hallo Martin,

          ja, richtig. Oder allgemeiner: Der Client packt's aus.

          si, si senior ...

          Wenn du aber eine Implementierung in PHP vorhast -sonst hättest du das ja nicht als Themengebiet gewählt-

          Genau, das hast du goldrichtig und messerscharf geschlossen ...! ;-)

          dann wird dein Webserver, auf dem PHP läuft, für diese Transaktion zum Client. Und der Webserver (der in deinem Fall Client ist), dekomprimiert die vom Fremdserver abgerufenen Inhalte, bevor er sie an PHP durchreicht.

          Ja, aber nach meinen bisherigen "Nachforschungen" gibt der content-length Header in diesem Fall die Größe der komprimierten Datei an. Also die der tatsächlichen übertragenen Datenmenge. Ich habe das aber bisher noch nirgendwo in verlässlicher Form gefunden. Angenommen dem ist so, würde ich gerne wissen, ob es eine (ich gehe mal davon aus) Möglichkeit gibt, die unkomprimierte Größe der Resource ebenfalls zu ermitteln?

          Gruß Gunther

      2. Tach!

        Erst zur Laufzeit bekannte in Javascript versteckte URLs wirst du nicht mit Parsen herausfinden.
        Du sprichst bspw. von "Image Preloading"?

        Oder von Ajax-Request, oder Include-Funktionen der JS-Frameworks. Kurz, alles was nicht standardisiert ist und das Nachzuladende als einfaches Stringliteral angibt.

        Ja, solche Sachen kann man so nicht erfassen (das "Problem" haben aber alle mir bekannten Tools), oder kennst du eine Methode mit vertretbarem Aufwand, die solche Fälle auch noch mit einschließt?

        Der Browser lässt das Javascript laufen und durch dessen Wirken kommen die Requests zustande, die natürlich der Browser ausführt und dessen Tools sie überwachen können.

        Wie kann ich dann die unkomprimierte Größe ermitteln?
        Du bekommst nur die unkomprimierte Version durchgereicht. Der Webserver packt es bereits aus.
        Wozu dann die Komprimierung? Ich dachte eigentlich, der Browser packts aus ...

        Ich war hier auf dem falschen Dampfer. Wenn der Webserver einen Request entgegennimmt, dann packt der den aus, bevor ihn PHP zu Gesicht bekommt. Aber dein Fall ist ja anders. Du spielst hier Client und verwendest einen in PHP eingebauten Wrapper, um mit file_get_contents() einen Webzugriff zu machen. Von dem Wrapper nahm ich auch an, dass der sich um das Auspacken kümmert. Zumindest kam hier nie eine Anfrage diesbezüglich. Allerdings gibt es einige Fundstellen im Netz, bei denen wohl doch komprimierte Daten über file_get_contents() empfangen wurden - nebst Lösungsvorschlägen.

        dedlfix.

  2. Hallo werte Selfgemeinde!

    Manchmal "lauern" Probleme ja gerade da, wo man sie am wenigsten erwartet hätte ...!
    Und zwar suche ich nach einer Möglichkeit (in PHP) um aus einer URL nur den Pfad zu ermitteln.

    Eine URL kann ja u.a. folgende Formate haben:

    • http.//example.com/path/to/file.html
    • http.//example.com/path/to/file
    • http.//example.com/path/to/
    • http.//example.com/path/to

    Wobei bei entsprechender Serverkonfiguration ja in allen Fällen durchaus dieselbe Resource ausgeliefert werden kann.

    Und wenn diese relative Pfadangaben enthält, muss ich daraus zuverlässig absolute machen.

    Mit is_dir() und is_file() habe ich bis jetzt keine brauchbaren Ergebnisse erzielen können.

    Wäre für jeden Tipp dankbar!

    Gruß Gunther

    1. Tach!

      Und zwar suche ich nach einer Möglichkeit (in PHP) um aus einer URL nur den Pfad zu ermitteln.

      Alles was PHP zum Server und dem Request weiß, steht in $_SERVER.

      Eine URL kann ja u.a. folgende Formate haben:

      • http.//example.com/path/to/file.html
      • http.//example.com/path/to/file
      • http.//example.com/path/to/
      • http.//example.com/path/to

      Ein weiteres Format kann sein: http://example.com/path/to/file.html/path/info

      Wobei bei entsprechender Serverkonfiguration ja in allen Fällen durchaus dieselbe Resource ausgeliefert werden kann.

      Ob da ein Zusammenhang zwischen URL und ausgeführter PHP-Datei besteht, kann PHP nicht unbedingt wissen. Pfade oder auch nur Bestandteile können fiktiv sein, gerade in Zeiten, wo kaum noch eine Konfiguration ohne mod_rewrite auszukommen scheint.

      Und wenn diese relative Pfadangaben enthält, muss ich daraus zuverlässig absolute machen.

      Das einzig zuverlässige ist die magische Konstante __FILE__, die den Dateinamen der aktuellen Datei (auch wenn sie inkludiert wurde) angibt, und das auch noch unter Auflösung sämtlicher Symlinks. Dazu gibt es auch noch __DIR__, was dirname(__FILE__) entspricht.

      dedlfix.

      1. Tach!

        Ob da ein Zusammenhang zwischen URL und ausgeführter PHP-Datei besteht, kann PHP nicht unbedingt wissen. Pfade oder auch nur Bestandteile können fiktiv sein, gerade in Zeiten, wo kaum noch eine Konfiguration ohne mod_rewrite auszukommen scheint.

        Und wenn diese relative Pfadangaben enthält, muss ich daraus zuverlässig absolute machen.

        Das einzig zuverlässige ist die magische Konstante __FILE__, die den Dateinamen der aktuellen Datei (auch wenn sie inkludiert wurde) angibt, und das auch noch unter Auflösung sämtlicher Symlinks. Dazu gibt es auch noch __DIR__, was dirname(__FILE__) entspricht.

        Ich lade doch eine Resource per cURL in einen String und parse diesen anschließend.
        Somit habe ich ja gewisse Informationen, u.a. per curl_getinfo() und get_headers(). Letzteres ist bspw. sehr hilfreich, wenn der jeweilige Server mit MultiViews konfiguriert ist, da dann der Content-Location Header den tatsächlichen Dateinamen enthält.

        Da es aber ja sehr viele verschiedene Varianten geben kann, wie wir schon festgestellt haben, hatte ich die Hoffnung, dass es eine Methode für alle gibt.

        Wie kann ich denn im jeweiligen Einzelfall vorgehen, um aus relativen Pfadangaben in meinem String absolute zu machen?
        Von mir aus kann es auch eine Trial & Error Methode sein, da es im wesentlichen ja nur um die Ausgangsdatei geht und Zeit/ Geschwindigkeit kein relevanter Faktor ist.

        Gruß Gunther

        1. Tach!

          Ich lade doch eine Resource per cURL in einen String und parse diesen anschließend.

          Achso, du schaust ja von außen. Ich hatte jetzt nicht nochmal in den anderen Thread-Teil geschaut, so dass mir das nicht mehr in Erinnerung war.

          Somit habe ich ja gewisse Informationen, u.a. per curl_getinfo() und get_headers(). Letzteres ist bspw. sehr hilfreich, wenn der jeweilige Server mit MultiViews konfiguriert ist, da dann der Content-Location Header den tatsächlichen Dateinamen enthält.

          Das einzige, was du dann siehst, sind die HTTP-Response-Header. Die geben eigentlich gar keine Auskunft über Interna des Systems. Höchstens ein Redirect von foo auf foo/ kann aussagen, dass foo ein Pfad-Bestandteil ist. Aber auch das kann täuschen.

          Was ist für dich der absolute Dateiname? Das Script, das letztlich die umgeschriebene SEO-URL bearbeitet, mit seinem vollen Namen ab Dateisystem-Wurzel oder wenigstens DocumentRoot? -> Nahezu aussichtslos. Oder ist es der Teil der URL nach dem Hostnamen (und Port)? -> parse_url() und dirname(auf den path-Teil).

          Da es aber ja sehr viele verschiedene Varianten geben kann, wie wir schon festgestellt haben, hatte ich die Hoffnung, dass es eine Methode für alle gibt.

          Wie kann ich denn im jeweiligen Einzelfall vorgehen, um aus relativen Pfadangaben in meinem String absolute zu machen?

          Was willst du denn eigentlich erreichen?

          dedlfix.

          1. Tach!

            Achso, du schaust ja von außen. Ich hatte jetzt nicht nochmal in den anderen Thread-Teil geschaut, so dass mir das nicht mehr in Erinnerung war.

            Kein Problem ...

            Was willst du denn eigentlich erreichen?

            Ich muss ja in jeder Datei "gucken", welche weiteren externen Resourcen geladen werden.
            Also z.B. in der Ausgangs HTML-Datei Stylesheet(s), Javascript(s), Image(s) usw.! Und wenn diese eine relative Pfadangabe haben (bspw. 'css-files/style.css'), dann muss ich daraus eben eine absolute (z.B. 'http://example.com/css-files/style.css') machen, um auch diese Resource per cURL laden und analysieren zu können.

            Gruß Gunther

            1. Hallo Gunther,

              möglich, dass mir hier ein Denkfehler unterläuft – vielleicht gibt es aber auch eine ganz einfache Lösung:

              Ich muss ja in jeder Datei "gucken", welche weiteren externen Resourcen geladen werden.
              Also z.B. in der Ausgangs HTML-Datei Stylesheet(s), Javascript(s), Image(s) usw.! Und wenn diese eine relative Pfadangabe haben (bspw. 'css-files/style.css'), dann muss ich daraus eben eine absolute (z.B. 'http://example.com/css-files/style.css') machen, um auch diese Resource per cURL laden und analysieren zu können.

              Wenn du CURLINFO_EFFECTIVE_URL verwendest, musst du nur noch, wie es auch ein Browser tun würde, relative Pfadangaben und den „effective“ URL zusammenbringen und erhälst einen absoluten URL. Wie das auf dem (entfernten) Server intern abläuft muss dich dabei nicht interessieren, ein Browser wüsste darüber ja auch nicht Bescheid.

              Viele Grüße,
              Claudius

              1. Hallo Claudius!

                Wenn du CURLINFO_EFFECTIVE_URL verwendest, musst du nur noch, wie es auch ein Browser tun würde, relative Pfadangaben und den „effective“ URL zusammenbringen und erhälst einen absoluten URL. Wie das auf dem (entfernten) Server intern abläuft muss dich dabei nicht interessieren, ein Browser wüsste darüber ja auch nicht Bescheid.

                Ich verwende ja schon curl_getinfo().
                Das ist auch teilweise ganz hilfreich. Versagt aber u.a. bie Multiviews, da man dann z.B. folgendes erhält:
                Aufruf: http://example.com/start
                Tatsächliche Resource: http://example.com/start.php
                Anzeige curl_getinfo() "url": http://example.com/start

                Das bedeutet in solch einem Fall weiss ich anhand von curl_getinfo() eben nicht, ob mein gesuchter Pfad nun

                • http://example.com/
                  oder
                  -http://example.com/start/
                  lautet.
                  In diesem Fall hilft nur get_headers() weiter, da der Content-Location Header in diesem Fall Auskunft gibt. In obigem Beispiel also:
                  [Content-Location] => start.php

                Da ich selber aber nur Apache Server zum "Probieren" zur Verfügung habe, stellt sich ja u.a. auch die Frage, ob und welche "Überraschungen" ggf. noch andere Server IIS & Co. auf Lager haben?

                Gruß Gunther

            2. Tach!

              Ich muss ja in jeder Datei "gucken", welche weiteren externen Resourcen geladen werden.

              Ich hätte ja jetzt dirname() auf den Pfadteil der URL (inklusive "Dateiname") anzuwenden empfohlen, aber das hat in meinem Test nicht vollständig mitgespielt

              dirname('/foo/bar/qux.html') -> /foo/bar - passt
              dirname('/foo/bar/')         -> /foo     - passt nicht, muss /foo/bar/ bleiben
              dirname('/foo/bar')          -> /foo     - passt

              Das heißt also, dass du da zumindest den Sonderfall "Slash am Ende" abfangen musst, bei dem du den Pfad gleich ohne zu dirname()n weiterverwenden kannst.

              dedlfix.

              1. Tach!

                Ich muss ja in jeder Datei "gucken", welche weiteren externen Resourcen geladen werden.

                Ich hätte ja jetzt dirname() auf den Pfadteil der URL (inklusive "Dateiname") anzuwenden empfohlen, aber das hat in meinem Test nicht vollständig mitgespielt

                dirname('/foo/bar/qux.html') -> /foo/bar - passt
                dirname('/foo/bar/')         -> /foo     - passt nicht, muss /foo/bar/ bleiben
                dirname('/foo/bar')          -> /foo     - passt

                Das heißt also, dass du da zumindest den Sonderfall "Slash am Ende" abfangen musst, bei dem du den Pfad gleich ohne zu dirname()n weiterverwenden kannst.

                Auch in Fällen wie
                http://example.net/path/to/resource
                die "ausreichend" sind, wenn die eigentliche Resource die Index-Datei von
                http://example.net/path/to/resource/
                ist, liefert dirname dann
                http://example.net/path/to

                In solchen Fällen reicht aber wiederum die URL Angabe von curl_getinfo(), die dann richtig angibt
                http://example.net/path/to/resource/

                Also so wie ich es sehe, muss ich immer mind. zwei der Infos "auswerten", um entscheiden zu können, um welchen Fall es sich konkret handelt, um dann meinen Pfad entsprechend "zusammenzubasteln" ...!

                Hast du evt. gleich noch einen Tipp für mich, falls solche Konstrukte wie "../../../path/to/resource.file" auftreten? Ich meine im Bezug auf meine "Basis-URL" und das entsprechende "rückwärtsgehen"?

                Gruß Gunther

                1. Tach!

                  Auch in Fällen wie
                  http://example.net/path/to/resource
                  die "ausreichend" sind, wenn die eigentliche Resource die Index-Datei von
                  http://example.net/path/to/resource/
                  ist, liefert dirname dann
                  http://example.net/path/to

                  Nein, du musst und darfst keinen / hinzufügen. Wenn der Webserver darauf besteht, muss er dem Client einen Redirect zur Ressource mit / schicken. Der Client hat keine Möglichkeit, zu wissen oder festzustellen ob ein / zum Anfordern weiterer relativer Ressourcen notwendig ist oder nicht. Er muss und wird mit dem auskommen, was ihm bekannt ist. Für

                  http://example.net/path/to/resource

                  ist allein

                  http://example.net/path/to/

                  als Basis für relative Angaben zu verwenden.

                  Wenn also resource ein Verzeichnis ist und der Client .../resource anfordert, schickt der Server ein Redirect zu .../resource/, von dem aus der Client korrekt weiterarbeiten kann. Deswegen sollte man als derjenige, der den Link irgendwo hinschreibt den abschließenden / nicht weglassen, weil man sich so den Redirect sparen kann (auch wenn der zeitlich möglicherweise nicht ins Gewicht fällt).

                  Hast du evt. gleich noch einen Tipp für mich, falls solche Konstrukte wie "../../../path/to/resource.file" auftreten? Ich meine im Bezug auf meine "Basis-URL" und das entsprechende "rückwärtsgehen"?

                  Funktion realpath()

                  dedlfix.

                  1. Tach!

                    Wenn also resource ein Verzeichnis ist und der Client .../resource anfordert, schickt der Server ein Redirect zu .../resource/, von dem aus der Client korrekt weiterarbeiten kann. Deswegen sollte man als derjenige, der den Link irgendwo hinschreibt den abschließenden / nicht weglassen, weil man sich so den Redirect sparen kann (auch wenn der zeitlich möglicherweise nicht ins Gewicht fällt).

                    FACK, aber die Ausgangs-URL kommt ja von einer Benutzereingabe ..., d.h. ich muss halt mit allen Varianten "rechnen". ;-)

                    Hast du evt. gleich noch einen Tipp für mich, falls solche Konstrukte wie "../../../path/to/resource.file" auftreten? Ich meine im Bezug auf meine "Basis-URL" und das entsprechende "rückwärtsgehen"?

                    Funktion realpath()

                    Besten Dank!

                    Dann "bastel" ich erstmal weiter. Vielen Dank einstweilen und bis zur nächsten Frage/ zum nächsten Problem.

                    Gruß Gunther