Seite 1 von 1

Frage zum SimpleHTTP Server

Verfasst: Samstag 17. Dezember 2016, 15:42
von ds2k5
Hallo,
ich habe unter Python 3.4.2 einen Beispiel Code ausprobiert für einen HTTP Server.

Wenn ich dieses dann z.B: mit nmap scanne sieht man: SimpleHTTPServer 0.6 (Python 3.4.2)
Wie kann man die "Info" ausschalten bzw. ändern ?

Danke

Code:

Code: Alles auswählen

#!/usr/bin/python3
#
import http.server
import socketserver

PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", PORT), Handler)
print("serving at port", PORT)
httpd.serve_forever()

Re: Frage zum SimpleHTTP Server

Verfasst: Samstag 17. Dezember 2016, 15:56
von Dav1d
Das liegt wohl an den Headern, die der Server sendet: https://hg.python.org/cpython/file/1756 ... er.py#l478

Das kann man auch relativ einfach im Browser nachvollziehen: Bild (oder via `curl -I`)

`server_version` zu überschreiben sollte hier ausreichen. (`server_version` ist natürlich auch in der Dokumentation zu finden)

Re: Frage zum SimpleHTTP Server

Verfasst: Samstag 17. Dezember 2016, 16:42
von ds2k5
Vielen Dank

bekomm es zwar im Moment nicht zum laufen...
aber ich hoffe ich finde meine Fehler

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 11:59
von kbr
ds2k5 hat geschrieben:ich habe unter Python 3.4.2 einen Beispiel Code ausprobiert für einen HTTP Server.

Wenn ich dieses dann z.B: mit nmap scanne sieht man: SimpleHTTPServer 0.6 (Python 3.4.2)
Wie kann man die "Info" ausschalten bzw. ändern ?
Dies kannst Du ändern, indem Du einen eigenen RequestHandler definierst und verwendest. 'server_version' ist ein Klassen-Attribut das bei Aufruf von 'version_string()' mit der System-Version konkateniert wird. Überladen dieser Methode und setzen des Klassen-Attributes erlaubt Dir dann, jede beliebige Info, oder auch gar keine, auszugeben:

Code: Alles auswählen

import http.server
import socketserver

class MyRequestHandler(http.server.SimpleHTTPRequestHandler):

    def version_string(self):
        """Return the server software version string."""
        return self.server_version
    
PORT = 8000
Handler = MyRequestHandler
Handler.server_version = 'MyServer 0.1'
httpd = socketserver.TCPServer(("", PORT), Handler)
print("serving at port", PORT)
httpd.serve_forever()
Wobei mir die Lösung mit dem Klassen-Attribut nicht sonderlich gefällt, aber in der Standard-Library ist es so implementiert. Bei einem eigenen RequestHandler würde ich es wohl als Instance-Attribut anlegen.

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 12:05
von BlackJack
@kbr: Die Idee ist wohl eher den Wert auch in der abgeleiteten Klasse als Klassenattribut zu definieren und nicht von ”aussen” auf der Klasse zu setzen.

Code: Alles auswählen

class MyRequestHandler(http.server.SimpleHTTPRequestHandler):

    server_version = 'My Superserver 42.23'

    def version_string(self):
        """Return the server software version string."""
        return self.server_version

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 12:19
von Sirius3
@kbr: für jeden Request wird eine Handler-Instanz erzeugt, aber Du willst ja nicht für jede Instanz eine andere Server-Version. Daher ist hier ein Klassenattribut genau das richtige, das man ja, wie BlackJack schon geschrieben hat, bei der Klasse definiert und nicht außerhalb setzt. Warum nennst Du MyRequestHandler in Handler um? Das könnte suggerieren, dass man server_version individuell setzen könnte, was so nicht geht.

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 12:27
von kbr
@BlackJack: oder so. Aber wenn das Klassen-Attribut in der abgeleiteten Klasse angelegt wird, muss dies auch wieder von außen gesetzt werden, wenn die Ausgabe der Information geändert werden soll, bzw unterdrückt werden soll – sofern Du dafür nicht auch eine eigene Klasse anlegst.

@Sirius3: Ich habe einfach das Originalbeispiel verwendet. Die Umbenennung ist auch dort nicht erforderlich und vermeidet nur eine lange nachfolgende Zeile.

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 12:36
von Sirius3
@kbr: wie schon gesagt, die Version ist nichts, was man pro Request setzen will. Daher ist der übliche Weg, die Handler-Klasse abzuleiten und Klassenvariablen zu setzen und/oder Methoden zu überschreiben.

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 13:23
von kbr
@Sirius3: Das hat mit pro Request nichts zu tun, sondern mit pro Applikation. Wenn die Server-Version als Klassen-Attribut angelegt ist, dann muss diese eben von außen geändert werden, wenn eine andere Information geliefert werden oder die bestehende unterdrückt werden soll. Statt dessen dafür ein Instanz-Attribut zu verwenden bietet allerdings keinen Vorteil, wie ich nach absenden meines Postings gesehen habe.

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 14:22
von BlackJack
@kbr: Ich verstehe nicht worauf Du mit Deiner Argumentation hinaus willst. Wenn ich eine andere Anwendung schreibe, dann hat die ja auch einen anderen Handler, also eine eigene Klasse der ich auch ein eigenes `server_version`-Attribut spendieren kann. Das was Du da machst ist eine globale Variable verändern, bzw. aus etwas das eigentlich eine Konstante sein sollte, eine Variable, und dann auch noch eine globale, zu machen.

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 16:33
von kbr
@BlackJack: Ob Du nun eine neue Klasse schreibst oder von einer bestehenden ein Klassen-Attribut änderst, macht keinen Unterschied, solange Instanzen der geänderten Klasse nicht auch noch woanders verwendet werden. Und dies ist ja hier nicht der Fall. Aber im Prinzip ist das schon richtig: im zweiten Fall lauern potentiell Seiteneffekte.

Was ich für den OP gerne hätte, wäre so etwas:

Code: Alles auswählen

handler = get_signature_handler(SimpleHTTPRequestHandler, 'MySuperServer')
Daher meine ursprüngliche Idee einer Instanz-Variablen. Aber nicht jede Idee ist eine gute Idee und wenn ich in den Sourcecode schaue, wäre dies, von der Sinnhaftigkeit einmal abgesehen, auch gar nicht so einfach umzusetzen.

Am saubersten ist in der Tat eine separate Klasse mit eigenem Klassen-Attribut. Für jede Anwendung aber alleine wegen der Server-Information einen eigenen Handler schreiben zu müssen, ist auch nicht so toll. Zum Glück geht das auch 'einfacher':

Code: Alles auswählen

def get_signature_handler(handler, server_version='', sys_version=''):
    d = {'server_version': server_version, 'sys_version': sys_version}
    return type('SignatureHandler', (handler,), d)
Das ist natürlich auch nur wieder eine weitere Idee und muss nicht der Weisheit letzter Schluß sein ... :)

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 17:55
von BlackJack
@kbr: Ich verstehe es immer noch nicht so wirklich. Natürlich für jede Anwendung eine eigene Handler-Klasse, denn das muss man doch *sowieso* machen. Nicht alleine wegen der Serverinformation, sondern weil jede Anwendung ja auch etwas anderes *macht*. Sonst wär's ja keine andere Anwendung sondern die gleiche, und bei gleicher Anwendung ist die gleiche Serverinformation ja auch normal.

Re: Frage zum SimpleHTTP Server

Verfasst: Sonntag 18. Dezember 2016, 20:15
von kbr
@BlackJack: Mag ja sein. Die Frage des OP war, wie er die Meldung modifizieren kann. Das wird er nun wohl können. Welches Vorgehen er dafür in seiner Situation als sinnvoll erachtet bleibt ihm überlassen – so wie Dir auch.