Webserver Redirect



  • Hallo,

    ich entwickle gerade einen Webserver. Dieser muß auch mal mit einem Redirect antworten können.

    Im RFC zu HTTP 1.1 steht, daß im Locationfeld der Antwort eine absolute URI stehen sollte. Also habe ich es so implementiert:

    Bei GET http://localhost:12345/Company Folder/KPPM/{4052}
    antworte ich mit 'nem Redirect zu

    http://localhost:12345/Company Folder/KPPM/Galerie/

    Das bestraft mir der Browser (Seamonkey und Internet Explorer) mit einer Fehlermeldung wegen falscher Daten.

    Lasse ich aber den Port weg. Also

    http://localhost/Company Folder/KPPM/Galerie/

    fügen beide Browser selbstständig den Port ein und alles funkt wunderbar.

    So sieht daher jetzt meine Antwort aus:

    HTTP/1.1 301 Moved Permanently
    Connection: Close
    Server: CRESD Web Server Toolkit (Jan 31 2014-12:39:01)
    Location: http://localhost/Company%20Folder/KPPM/Galerie/
    Content-Type: text/plain
    
    http://localhost/Company%20Folder/KPPM/Galerie/
    

    Was mache ich aber, wenn ich tatsächlich einen anderen Port angeben wollte?

    Im Internet habe ich zu diesem Thema leider nur gefunden, wie ich Apache entsprechend konfigurieren kann.

    mfg Martin
    P.S: Es ist nur rein Neugierde. Das aktuelle Problem ist gelöst.





  • tntnet schrieb:

    Location: /something ist völlig ok. Siehe beispielsweise http://stackoverflow.com/questions/8250259/is-a-302-redirect-to-relative-url-valid-or-invalid.

    Das ist auch meine Erfahrung. Im RFC steht aber:

    The field value consists of a single absolute URI.
    Location = "Location" ":" absoluteURI

    Meine Frage bezog sich aber, was ich hier rein theoretisch angeben müsste, wollte ich dem Client sagen, daß er einen anderen Port als den bisherigen wählen soll. Wenn ich dieses Problem hätte, fiele mir als Lösung nur ein, einen entsprechenden HTML-Code zu generieren, der einen refresh tag enthält. Ebenso wäre natürlich auch interessant, ob das mit der relativen URL so vom Stnadard abgedeckt ist. Dann sollte ich vielleicht auch mal meinen Client überarbeiten. Der erwartet nämlich tatsächlich eine absolute URL und könnte mit einer relativen nix anfangen. 😡

    mfg Martin



  • http://datatracker.ietf.org/doc/draft-ietf-httpbis-p2-semantics/history/
    ...mal schauen wann das mal richtig final wird 😉

    Absolute URL mit Port wäre schon korrekt, das sind wohl eher Browser-Bugs 😉
    (Kann ich mit dem IE11 übrigens nicht reproduzieren)



  • geeky schrieb:

    http://datatracker.ietf.org/doc/draft-ietf-httpbis-p2-semantics/history/
    ...mal schauen wann das mal richtig final wird 😉

    Absolute URL mit Port wäre schon korrekt, das sind wohl eher Browser-Bugs 😉
    (Kann ich mit dem IE11 übrigens nicht reproduzieren)

    Seamonkey 2.23 zeigt mir das an:

    Fehler: Beschädigte Inhalte

    Die Seite, die Sie anzusehen versuchen, kann nicht angezeigt werden, da ein Fehler in der Datenübertragung festgestellt wurde.

    Die Seite, die Sie anzusehen versuchen, kann nicht angezeigt werden, da ein Fehler in der Datenübertragung festgestellt wurde.

    Bitte kontaktieren Sie die Website-Betreiber, um sie über dieses Problem zu verständigen.

    Internet Explorer 11

    Die Seite kann nicht angezeigt werden.

    •Vergewissern Sie sich, dass die Webadresse http://localhost:12345 stimmt.
    •Suchen Sie die Seite mit Ihrer Suchmaschine.
    •Aktualisieren Sie die Seite in ein paar Minuten.

    Dies war der Request:

    http://localhost:12345/Company Folder/KPPM/{4052}

    Und das war die Antwort meines Servers:

    HTTP/1.1 301 Moved Permanently
    Connection: Close
    Server: CRESD Web Server Toolkit (Feb 2 2014-11:49:36)
    Date: 02 Feb 2014 11:54:04 +0100
    Location: http://localhost:12345/Company Folder/KPPM/Galerie/
    Content-Type: text/plain

    http://localhost:12345/Company Folder/KPPM/Galerie/

    Lasse ich aber den Port in der Antwort weg, führen beide Browser den Redirect korrekt aus und fügen selbstständig den Port ein. Ich habe einfach mal geschaut, wie der IIS mit Livelink in einem solchen Fall antwortet: Das Gespann lässt beim Redirect im Locationfeld den Port weg. Deswegen ist es bei mir derzeit auch so implementiert.

    mfg Martin



  • mgaeckler schrieb:

    Im RFC steht aber:

    The field value consists of a single absolute URI.
    Location = "Location" ":" absoluteURI

    Das ist ein Fehler im RFC, siehe auch hier:
    http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p2-semantics-17.html#rfc.section.9.5

    Meine Frage bezog sich aber, was ich hier rein theoretisch angeben müsste, wollte ich dem Client sagen, daß er einen anderen Port als den bisherigen wählen soll.

    Weiß ich gerade auch nicht auswendig. Probier doch einfach mal aus, was ein Apache und nginx machen.



  • nman schrieb:

    Weiß ich gerade auch nicht auswendig. Probier doch einfach mal aus, was ein Apache und nginx machen.

    Das ist mir für jetzt zu aufwendig. Das werde ich testen, wenn ich es wirklich mal brauchen sollte. Ich antworte jetzt mit einer absoluten URL und lasse halt einfach den Port weg. Für das aktuelle Problem reicht mir die Lösung, IIS + Livelink machen es genauso und sowohl Seamonkey als auch IE machen, was sie sollen. 🙂

    mfg Martin



  • mgaeckler schrieb:

    Dies war der Request:

    http://localhost:12345/Company Folder/KPPM/{4052}

    Und das war die Antwort meines Servers:

    HTTP/1.1 301 Moved Permanently
    Connection: Close
    Server: CRESD Web Server Toolkit (Feb 2 2014-11:49:36)
    Date: 02 Feb 2014 11:54:04 +0100
    Location: http://localhost:12345/Company Folder/KPPM/Galerie/
    Content-Type: text/plain

    http://localhost:12345/Company Folder/KPPM/Galerie/

    Lasse ich aber den Port in der Antwort weg, führen beide Browser den Redirect korrekt aus und fügen selbstständig den Port ein. Ich habe einfach mal geschaut, wie der IIS mit Livelink in einem solchen Fall antwortet: Das Gespann lässt beim Redirect im Locationfeld den Port weg. Deswegen ist es bei mir derzeit auch so implementiert.

    mfg Martin

    Hallo,

    ich kann das Problem hier nicht nachvollziehen. Ich habe tntnet verwendet, um genau so einen Request zu erzeugen. Der Request sieht bei mir so aus:

    http://localhost:8000/redirect
    

    und die Antwort:

    HTTP/1.1 301 Moved Permanently                                
    Date: Sun, 02 Feb 2014 13:51:23 GMT                   
    Server: Tntnet/2.3                                           
    Content-Length: 26
    Content-Type: text/html; charset=UTF-8
    Connection: close
    Location: http://localhost:8000/foo                                         
    
    http://localhost:8000/foo
    

    Sowohl Firefox als auch Seamonkey und auch der Konquerer reagieren darauf wie erwartet. Sie führen den Redirect durch.



  • tntnet schrieb:

    Hallo,

    ich kann das Problem hier nicht nachvollziehen. Ich habe tntnet verwendet, um genau so einen Request zu erzeugen. Der Request sieht bei mir so aus:

    http://localhost:8000/redirect
    

    und die Antwort:

    HTTP/1.1 301 Moved Permanently                                
    Date: Sun, 02 Feb 2014 13:51:23 GMT                   
    Server: Tntnet/2.3                                           
    Content-Length: 26
    Content-Type: text/html; charset=UTF-8
    Connection: close
    Location: http://localhost:8000/foo                                         
    
    http://localhost:8000/foo
    

    Sowohl Firefox als auch Seamonkey und auch der Konquerer reagieren darauf wie erwartet. Sie führen den Redirect durch.

    Hallo,

    Danke für Deine Mühe. Das ist sehr komisch. Außer daß Dein Server beim Content-Type lügt, sehe ich keinen wirklichen Unterschied in der Antwort unserer Server. Vieleicht sollte ich mal ausprobieren, ob die Browser tatsächlich belogen werden wollen. 🙄

    mfg Martin



  • mgaeckler schrieb:

    Hallo,

    Danke für Deine Mühe. Das ist sehr komisch. Außer daß Dein Server beim Content-Type lügt, sehe ich keinen wirklichen Unterschied in der Antwort unserer Server. Vieleicht sollte ich mal ausprobieren, ob die Browser tatsächlich belogen werden wollen. 🙄

    mfg Martin

    Hi,

    auch mit "Content-Type: text/plain" funktioniert das bei mir. Das "text/html; charset=UTF-8" ist halt der default.

    Das macht auch kaum Mühe. Mit tntnet ist das schnell gemacht. Hier ist die Seite, mit der ich teste:

    <%cpp>
    const char* location = "http://localhost:8000/foo";
    reply.setHeader(tnt::httpheader::location, location);
    reply.setContentType("text/plain");
    reply.out() << location << '\n';
    return HTTP_MOVED_PERMANENTLY;
    </%cpp>
    


  • tntnet schrieb:

    mgaeckler schrieb:

    Hallo,

    Danke für Deine Mühe. Das ist sehr komisch. Außer daß Dein Server beim Content-Type lügt, sehe ich keinen wirklichen Unterschied in der Antwort unserer Server. Vieleicht sollte ich mal ausprobieren, ob die Browser tatsächlich belogen werden wollen. 🙄

    mfg Martin

    Hi,

    auch mit "Content-Type: text/plain" funktioniert das bei mir. Das "text/html; charset=UTF-8" ist halt der default.

    Das macht auch kaum Mühe. Mit tntnet ist das schnell gemacht. Hier ist die Seite, mit der ich teste:

    <%cpp>
    const char* location = "http://localhost:8000/foo";
    reply.setHeader(tnt::httpheader::location, location);
    reply.setContentType("text/plain");
    reply.out() << location << '\n';
    return HTTP_MOVED_PERMANENTLY;
    </%cpp>
    

    Dann werd ich wohl mal schaun müssen, was Dein Server anders macht wie meiner.

    mfg Martin



  • mgaeckler schrieb:

    Dann werd ich wohl mal schaun müssen, was Dein Server anders macht wie meiner.
    mfg Martin

    Das muß leider ausfallen.

    make[1]: Entering directory /root/tntnet/tntnet-2.2.1/sdk/demos' ../../sdk/tools/ecppc/ecppc -o alldemos.cpp alldemos.ecpp /root/tntnet/tntnet-2.2.1/sdk/tools/ecppc/.libs/ecppc: error while loading shared libraries: libcxxtools.so.9: cannot open shared object file: No such file or directory make[1]: *** [alldemos.cpp] Error 127 make[1]: Leaving directory/root/tntnet/tntnet-2.2.1/sdk/demos'
    make: *** [all-recursive] Error 1
    linux-n8or:~/tntnet/tntnet-2.2.1 #

    mfg Martin



  • mgaeckler schrieb:

    mgaeckler schrieb:

    Dann werd ich wohl mal schaun müssen, was Dein Server anders macht wie meiner.
    mfg Martin

    Das muß leider ausfallen.

    make[1]: Entering directory /root/tntnet/tntnet-2.2.1/sdk/demos' ../../sdk/tools/ecppc/ecppc -o alldemos.cpp alldemos.ecpp /root/tntnet/tntnet-2.2.1/sdk/tools/ecppc/.libs/ecppc: error while loading shared libraries: libcxxtools.so.9: cannot open shared object file: No such file or directory make[1]: *** [alldemos.cpp] Error 127 make[1]: Leaving directory/root/tntnet/tntnet-2.2.1/sdk/demos'
    make: *** [all-recursive] Error 1
    linux-n8or:~/tntnet/tntnet-2.2.1 #

    mfg Martin

    Mach mal ein ldconfig als root. Das hilft. Steht auch in den FAQs. Wenn man Libraries installiert, muss man immer ldconfig aufrufen, um den dynamic loader cache neu zu initialisieren.



  • tntnet schrieb:

    Mach mal ein ldconfig als root. Das hilft. Steht auch in den FAQs. Wenn man Libraries installiert, muss man immer ldconfig aufrufen, um den dynamic loader cache neu zu initialisieren.

    Ich gestehe, habe nur den "quick start guide" gelesen. Danke es funktioniert jetzt. Ich werde den Fall jetzt untersuchen.

    BTW: Spricht etwas dagegen, ldconfig ins makefile aufzunehmen?

    mfg Martin



  • mgaeckler schrieb:

    Danke es funktioniert jetzt. Ich werde den Fall jetzt untersuchen.

    Bingo, ich habe meinen Fehler gefunden.

    Da ärgere ich mich über mich selbst, weil 1. hab ich den RFC nicht richtig gelesen und 2. hätte ich es mir auch denken können. 😡

    Der Browser muß im HOST-Feld natürlich den Port, auf dem er schreibt, mitschicken. Das ist sinnvoll, weil der muß nicht identisch sein, mit dem Port, auf dem der Server lauscht.

    Seamonkey und der IE haben daher im hostfeld localhost:12345 geschrieben. Das host-feld habe ich so wie ich's bekommen habe in den redirect eingefügt plus dem Port, auf dem mein Server lauscht. Dadurch war meine Antwort nicht wie behauptet
    Location: http://localhost:12345/...
    sondern
    Location: http://localhost:12345:12345/...

    Das wurde natürlich zurecht von beiden Browsern angemossert.

    Gemerkt habe ich das deshalb nicht, weil meine Prüfsoftware, mit der ich die Antwort überprüft habe, im hostfeld fälschlicherweise den Port weggelassen hat.

    Jetzt habe ich sowohl den Server als auch den Client behoben und alles funkt so wie's soll.

    mfg Martin
    P.S.: Damit hat sich natürlich meine ursprüngliche Frage erledigt. 😃



  • Da hätte ich für die Zukunft einen Tipp für Dich. Ich habe das so getestet:

    echo -ne 'GET /redirect HTTP/1.1\r\nConnection:close\r\n\r\n'|nc localhost 8000
    

    Damit kann ich meine Requests zusammenbauen wie ich will und sehe dann auch die komplette Antwort völlig unzensiert. Damit hattest Du es auch gleich gesehen.

    Das ldconfig ist immer wieder ärgerlich. Das ist aber im Prinzip kein Problem von cxxtools/tntnet sondern ein Grundlegendes Problem des GNU Loaders. Im Build-System versuche ich mich soweit es geht an die Standards zu halten. Daher verwende ich autotools und ich verlasse mich darauf, dass die das richtig machen. Da es ein GNU Problem ist, sollte das nicht in der Library gefixt werden. Auch fürchte ich, dass Packager eher ein Problem damit haben, wenn ldconfig aufgerufen würde, da das nicht üblich ist. Tntnet läuft auch nicht nur auf GNU Systemen. Ich selbst verwende es auf der Arbeit unter AIX und dort tritt das Problem nicht auf.



  • tntnet schrieb:

    Da hätte ich für die Zukunft einen Tipp für Dich. Ich habe das so getestet:

    echo -ne 'GET /redirect HTTP/1.1\r\nConnection:close\r\n\r\n'|nc localhost 8000
    

    Damit kann ich meine Requests zusammenbauen wie ich will und sehe dann auch die komplette Antwort völlig unzensiert. Damit hattest Du es auch gleich gesehen.

    Guter Gedanke, hätte mir aber wahrscheinlich nix genützt, denn da mein Prüfprogramm den Port nicht angehängt hat, hätte ich das mit diesem Kommando auch nicht gemacht. Gefunden habe ich das Problem, weil ich 1. Dank Deiner Hilfe wußte, daß es hätte funktionieren müssen und 2. ich mit Wireshark den Mist gesehen habe.

    tntnet schrieb:

    Das ldconfig ist immer wieder ärgerlich. Das ist aber im Prinzip kein Problem von cxxtools/tntnet sondern ein Grundlegendes Problem des GNU Loaders. Im Build-System versuche ich mich soweit es geht an die Standards zu halten. Daher verwende ich autotools und ich verlasse mich darauf, dass die das richtig machen. Da es ein GNU Problem ist, sollte das nicht in der Library gefixt werden. Auch fürchte ich, dass Packager eher ein Problem damit haben, wenn ldconfig aufgerufen würde, da das nicht üblich ist. Tntnet läuft auch nicht nur auf GNU Systemen. Ich selbst verwende es auf der Arbeit unter AIX und dort tritt das Problem nicht auf.

    OK sehe ich ein. Hab ich halt wohl Pech gehabt.

    Übrigens, Dein Quick Start Guide enthält eine kleine Ungenauigkeit. Zumindest hat es bei mir so nicht gefunkt. Du schreibst:

    To build and execute your first enter the following commands:

    cd myfirstproject
    make
    tntnet

    Danach lief zwar der tntnet server, hat aber die Anwendung nicht gestartet. Ich konnte keine Verbindung herstellen. So hat's aber geklappt:

    cd myfirstproject
    make test

    Zusätzlich hat der tntserver sich im Sekundentakt beschwert, weil eine Gruppe und ein User fehlte (hab jetzt vergessen wie die hiessen). Ich wundere mich, wozu er die braucht.

    Ich habe mir auch erlaubt, einen Blick in Deine Quellen zu werfen. Sehr schön zu lesen, ich bin gleich zurecht gekommen. Dabei ist mir aufgefallen, daß Du eine Exception HttpReturn wirfst, wenn jemand HttpReply::redirect aufruft. Die wird zwar von Deinem Server abgefangen und dann eine entsprechende Antwort an den Client geschickt aber besteht da nicht die Gefahr, daß irgendwelche Ressourcen evtl. nicht freigegeben werden oder kann diese Funktiopn von einer Webanwendung gar nicht aufgerufen werden und Deine Objekt sind in der Lage, ihre Ressourcen in deren Destruktoren aufzuräumen?

    mfg Martin



  • mgaeckler schrieb:

    Ich habe mir auch erlaubt, einen Blick in Deine Quellen zu werfen. Sehr schön zu lesen, ich bin gleich zurecht gekommen. Dabei ist mir aufgefallen, daß Du eine Exception HttpReturn wirfst, wenn jemand HttpReply::redirect aufruft. Die wird zwar von Deinem Server abgefangen und dann eine entsprechende Antwort an den Client geschickt aber besteht da nicht die Gefahr, daß irgendwelche Ressourcen evtl. nicht freigegeben werden oder kann diese Funktiopn von einer Webanwendung gar nicht aufgerufen werden und Deine Objekt sind in der Lage, ihre Ressourcen in deren Destruktoren aufzuräumen?

    mfg Martin

    Freut mich, dass Du mit dem Code gut zurecht kommst. Die Probleme mit dem User und auch das "make test" verstehe ich nicht. Eigentlich sollte das out-of-the-box funktionieren. Und das tut es normalerweise auch.

    In C++ muss man eigentlich immer exception-safe programmieren. Und tntnet ist exception-safe. Das bedeutet, dass alle Resourcen auch bei einer exception frei gegeben werden. Eine Webapplikation darf jederzeit eine Exception werfen. Tntnet kümmert sich darum, dass diese abgefangen wird und eine korrekte Antwort zum Client gesendet wird.

    Genau das ist einer der größten Vorteile von C++. Nämlich dass Resourcen automatisch aufgeräumt werden können, obwohl von C++-Kritikern das Gegenteil behauptet wird. C++ braucht eben keine Garbage collection. Allerdings - und das wäre dann eher eine berechtigte Kritik - liegt das in der Verantwortung des Entwicklers. Aber wenn man sich einen gewissen Stil erlernt hat (Stichwort RAII), dann ist das gar kein Problem mehr.



  • tntnet schrieb:

    Freut mich, dass Du mit dem Code gut zurecht kommst. Die Probleme mit dem User und auch das "make test" verstehe ich nicht. Eigentlich sollte das out-of-the-box funktionieren. Und das tut es normalerweise auch.

    Das dachte ich mir schon. Du machst mir auch nicht den Eindruck, irgendwas hinzurotzen so nach dem Motto passt scho. Ich habe das Problem auch nicht näher untersucht, da mit dem Aufruf aus dem Makefile es ja gepasst hat.

    tntnet schrieb:

    In C++ muss man eigentlich immer exception-safe programmieren. Und tntnet ist exception-safe. Das bedeutet, dass alle Resourcen auch bei einer exception frei gegeben werden. Eine Webapplikation darf jederzeit eine Exception werfen. Tntnet kümmert sich darum, dass diese abgefangen wird und eine korrekte Antwort zum Client gesendet wird.

    Genau das ist einer der größten Vorteile von C++. Nämlich dass Resourcen automatisch aufgeräumt werden können, obwohl von C++-Kritikern das Gegenteil behauptet wird. C++ braucht eben keine Garbage collection. Allerdings - und das wäre dann eher eine berechtigte Kritik - liegt das in der Verantwortung des Entwicklers. Aber wenn man sich einen gewissen Stil erlernt hat (Stichwort RAII), dann ist das gar kein Problem mehr.

    Du hast vollkommen recht. Im übrigen muß man ja die Funktion nicht aufrufen, um einen Redirect zu senden, und es ist zumindest im Header auch dokumentiert, daß sie eine Exception wirft. So kann sich halt jeder Anwender Deines Frameworks selbst entscheiden, ob er Exceptions werfen will oder nicht.

    Die C++-Kritiker haben die Philosophie von C++ nicht verstanden. Sie denken wohl, weil man nicht sicher programmieren muß, macht es auch niemand.

    mfg Martin


Anmelden zum Antworten