10. Jupyter Notebook

ehemalige Veranstaltungen ia3.netz + ia3.data sowie ia4.Netz im Studiengang Interaktive Medien

(c) 2020 Hochschule Augsburg - Fakultät für Informatik - Prof.Dr.Nik Klever

Musterlösung - Online Probe Prüfung

Hinweis zur Prüfung:

  • Jupyter Notebook Zellen
    • Bitte löschen sie weder ganze Zellen (auch nicht die Aufgabenstellungen) noch Code oder Text in den Zellen, auch nicht wenn sie Fehler entdecken oder Fehlermeldungen bekommen.
    • Stattdessen sollten sie die entsprechende Zelle mit Copy Cells kopieren und mit Paste Cells Below unten wieder einfügen (die entsprechenden Menü-Punkte finden sie im Edit-Menü).
    • Warum ?
    • Wenn sie in den Zellen irgendeinen Code löschen, kann ich ihnen für teilweise richtigen Code keine Punkte gutschreiben ! Wenn sie jedoch in fehlerhaften Zellen einen Teil des Codes trotz eines Fehlers oder Exceptions richtig haben, kann ich dafür trotzdem entsprechende Punkte darauf vergeben !
  • Beachten sie auch bitte unbedingt die Strategie zur Aufgabenlösung !
  • Beachten Sie bei allen Aufgaben auch das Programmier-Paradigma DRY - Don't repeat yourself, d.h. es sollte Copy-And-Paste innerhalb des Codes vermieden und stattdessen eher eine Schleife, eine Funktion, eine Klasse angedacht werden.

Viel Erfolg !

Aufgabe 1 - Herunterladen einer Webseite mittels HTTP und der Bibliothek telnetlib

Teilfrage 1

Laden Sie die Startseite (d.h. ohne weitere Pfadangabe in der Anfrage) von der Webseite www.pro-air.de mittels mittels der Bibliothek ''telnetlib'' herunter. Schreiben sie hierzu eine Funktion httpRequest, die ihnen sowohl Head als auch Body des HTTP-Requests zurückliefert. Geben sie nach dem jeweiligen Aufruf der Funktion den Header komplett und vom Body nur die ersten 2000 Zeichen aus.

Hinweis: Die heruntergeladene Seite sollte letztendlich mit dem Seitenquelltext der entsprechenden Seite, wenn sie diese im Browser aufrufen, identisch sein.

In [1]:
from telnetlib import Telnet

def httpRequest(host,pfad="/",port=80):
    connection = Telnet(host,port)
    connection.write(bytes("GET {} HTTP/1.1\r\n".format(pfad),"utf-8"))
    connection.write(bytes("Host: {}\r\n".format(host),"utf-8"))
    connection.write(b"Connection: close\r\n")
    connection.write(b"\r\n")
    head, body = connection.read_all().split(b"\r\n\r\n",1)
    return head.decode("utf-8"), body.decode("utf-8")

head, body = httpRequest("www.pro-air.de")
print(head)
print("----"*10)
print(body[:2000])
HTTP/1.1 200 OK
Date: Wed, 19 Dec 2018 19:01:13 GMT
Server: Apache/1.3.39 (Unix) mod_gzip/1.3.26.1a PHP/4.4.8 FrontPage/5.0.2.2635 mod_ssl/2.8.30 OpenSSL/1.0.2a
Last-Modified: Tue, 10 Oct 2017 07:58:43 GMT
ETag: "e892c-4f-59dc7db3"
Accept-Ranges: bytes
Content-Length: 79
Connection: close
Content-Type: text/html
----------------------------------------
<meta http-equiv="refresh" content="0;url=http://pro-air.de/proair/index.html">
In [2]:
head, body = httpRequest("pro-air.de",pfad="/proair/index.html")
print(head)
print("----"*10)
print(body[:2000])
HTTP/1.1 200 OK
Date: Wed, 19 Dec 2018 19:01:14 GMT
Server: Apache/1.3.39 (Unix) mod_gzip/1.3.26.1a PHP/4.4.8 FrontPage/5.0.2.2635 mod_ssl/2.8.30 OpenSSL/1.0.2a
Last-Modified: Mon, 14 May 2018 09:25:55 GMT
ETag: "e7697a-f61c-5af95623"
Accept-Ranges: bytes
Content-Length: 63004
Connection: close
Content-Type: text/html
----------------------------------------
<!DOCTYPE html>
	<html lang="de" dir="ltr">
		<head>
        
        	<meta charset="UTF-8">
            
			<script>var themeHasJQuery = !!window.jQuery;</script>
			<script type="text/javascript" src="./assets/js/jquery.js"></script>
			<script>window._$ = jQuery.noConflict(themeHasJQuery);</script>

			<link rel="stylesheet" href="./assets/css/bootstrap.css" media="screen" />

			<script type="text/javascript" src="./assets/js/bootstrap.min.js"></script>
            <!--[if lte IE 9]>
            <link rel="stylesheet" href="./assets/css/layout.ie.css">
            <script src="./assets/js/layout.ie.js"></script>
            <![endif]-->

			<link class="" href='http://fonts.googleapis.com/css?family=Open+Sans:300,300italic,regular,italic,600,600italic,700,700italic,800,800italic&subset=latin' 
            rel='stylesheet' type='text/css'>
			<script type="text/javascript" src="./assets/js/layout.core.js"></script>

			<script src="./assets/js/CloudZoom.js"></script>

			<link rel="stylesheet" href="./assets/css/style.css">
            <link rel="stylesheet" type="text/css" href="assets/css/MyFontsWebfontsKit.css">

			<script src="./assets/js/script.js"></script>
            
            <link href="./assets/css/letitsnow.css" rel="stylesheet">
            <script src="./assets/js/modernizr.min.js"></script>

			

            <title>pro air Medienagentur GmbH</title>
            <meta name="title" content="pro air Medienagentur GmbH Augsburg"/>
            <meta name="description" content="Full-Service-Werbeagentur! Mit uns stehen Sie im Mittelpunkt! Wir arbeiten in der City von Augsburg. Da, wo das Leben pulsiert. "/> 
            <meta name="keywords" content="pro air Medienagentur GmbH, Mediaplanung, Eventservice, Messeservice, Imagefilm, Radiospot, TV-Spot, Kinospot, Aussenwerbung, Augsburg"/>
            <meta name="author" content="pro air Medienagentur GmbH | 020779"/>
            <meta name="robots" content="INDEX, FOLLOW"/>
            
            
  

Teilfrage 2

Wieviele Requests mussten Sie schicken, damit Sie die Startseite letztendlich wirklich heruntergeladen haben ?

2

Teilfrage 3

Welche IP-Adresse hat dieser Webserver ?

Hinweis: Verwenden Sie hierzu die Bibliothek socket und die Methode gethostbyname

In [3]:
from socket import gethostbyname
ip1 = gethostbyname("www.pro-air.de")
print(ip1)
ip2 = gethostbyname("pro-air.de")
print(ip2)
80.82.223.105
80.82.223.105

Teilfrage 4

Welcher Internet-Domain gehört diese IP-Adresse an ?

Hinweis: Verwenden Sie hierzu die Bibliothek socket und die Methode gethostbyaddr, die den zur entsprechenden IP-Adresse gehörenden primären Internet Hostnamen als ersten Parameter zurückliefert.

In [4]:
from socket import gethostbyaddr
rs1 = gethostbyaddr(ip1)
print(rs1)
rs2 = gethostbyaddr(ip2)
print(rs2)
('mailserver.uranus11.de', [], ['80.82.223.105'])
('mailserver.uranus11.de', [], ['80.82.223.105'])

Dieser Webserver gehört der Internet-Domain uranus11.de an

Teilfrage 5

Welcher Firma gehört diese Internet-Domain ?

Hinweis: Verwenden Sie hierzu die Url https://www.denic.de und schauen sie sich die E-Mail-Adresse zum Abuse Contact an

Fa. Norplex, Dipl.Ing. Günter Bittner

Teilfrage 6

Wieviele Requests - in erster Näherung - braucht ein Browser mindestens um die komplette Webseite zusammenzustellen und auszuliefern ?

Hinweis: Nehmen Sie hierzu die oben heruntergeladene Webseite und verwenden Sie entweder String-Methoden oder die Bibliothek html.parser um die Webseite komplett zu durchsuchen.

In [5]:
count = body.lower().count("<img ")
count += body.lower().count("<link ")
count += body.lower().count("<script ")
print(count)
54
In [6]:
from html.parser import HTMLParser

class MyHTMLParser(HTMLParser):
    
    def __init__(self):
        super().__init__()
        self.count = 0

    def handle_starttag(self, tag, attrs):
        if tag in ["img","script"]:
            for attr in attrs:
                if attr[0].lower() == "src":
                    self.count += 1
        elif tag == "link":
            for attr in attrs:
                if attr[0].lower() == "href":
                    self.count += 1

parser = MyHTMLParser()
parser.feed(body)
print(parser.count)
52

Aufgabe 2 - E-Mail

Teilfrage 1 - E-Mail mit SMTP mittels der Bibliothek telnetlib verschicken

Verschicken Sie eine E-Mail an ihre eigene Hochschul-E-Mail-Adresse mit einer Kopie dieser E-Mail an mich, d.h. an meine Hochschul-E-Mail-Adresse nik.klever@hs-augsburg.de, an Stefan König, d.h. an seine Hochschul-E-Mail-Adresse stefan.koenig@hs-augsburg.de sowie an sich selbst über den hochschuleigenen Mail-Server smtp.hs-augsburg.de. Verwenden Sie hierzu ebenfalls die Bibliothek ''telnetlib''. Geben Sie in dem Betreff dieser E-Mail [ia3netzdata-onlinetest] und ihre Matrikelnr an. Geben Sie ausserdem irgendeinen Text ein.

In [7]:
from telnetlib import Telnet

connection = Telnet("smtp.hs-augsburg.de",25)

response = connection.read_until(b'\r\n')
print("\tS: {}".format(response.decode('utf-8')))
send = b"HELO meinRechner\r\n"
connection.write(send)
print("C: {}".format(send.decode('utf-8')))

response = connection.read_until(b'\r\n')
print("\tS: {}".format(response.decode('utf-8')))
send = b"MAIL FROM: <test@test.de>\r\n"
connection.write(send)
print("C: {}".format(send.decode('utf-8')))

response = connection.read_until(b'\r\n')
print("\tS: {}".format(response.decode('utf-8')))
send = b"RCPT TO: <nik.klever@hs-augsburg.de>\r\n"
connection.write(send)
print("C: {}".format(send.decode('utf-8')))

response = connection.read_until(b'\r\n')
print("\tS: {}".format(response.decode('utf-8')))
send = b"RCPT TO: <stefan.koenig@hs-augsburg.de>\r\n"
connection.write(send)
print("C: {}".format(send.decode('utf-8')))

response = connection.read_until(b'\r\n')
print("\tS: {}".format(response.decode('utf-8')))
send = b"RCPT TO: <nik@hs-augsburg.de>\r\n"
connection.write(send)
print("C: {}".format(send.decode('utf-8')))

response = connection.read_until(b'\r\n')
print("\tS: {}".format(response.decode('utf-8')))
send = b"DATA\r\n"
connection.write(send)
print("C: {}".format(send.decode('utf-8')))

response = connection.read_until(b'\r\n')
print("\tS: {}".format(response.decode('utf-8')))
send = b"""From: test@test.de
To: nik.klever@hs-augsburg.de
Cc: stefan.koenig@hs-augsburg.de, nik@hs-augsburg.de
Message-Id: <0456798A824341.B856AF0056@test.de>
Content-Type: text/plain
Subject: [ia3netzdata-onlinetest] MatrNr 12345678

Hallo,

dies ist eine Testmail

Nik"""
connection.write(send)
connection.write(b"\r\n.\r\n")
print("C: {}".format(send.decode('utf-8')))

response = connection.read_until(b'\r\n')
print("\tS: {}".format(response.decode('utf-8')))
send = b"QUIT\r\n"
connection.write(send)
print("C: {}".format(send.decode('utf-8')))
	S: 220 fly2.rz.hs-augsburg.de ESMTP Postfix

C: HELO meinRechner

	S: 250 fly2.rz.hs-augsburg.de

C: MAIL FROM: <test@test.de>

	S: 250 2.1.0 Ok

C: RCPT TO: <nik.klever@hs-augsburg.de>

	S: 250 2.1.5 Ok

C: RCPT TO: <stefan.koenig@hs-augsburg.de>

	S: 250 2.1.5 Ok

C: RCPT TO: <nik@hs-augsburg.de>

	S: 550 5.1.1 <nik@hs-augsburg.de>: Recipient address rejected: User unknown in virtual alias table

C: DATA

	S: 354 End data with <CR><LF>.<CR><LF>

C: From: test@test.de
To: nik.klever@hs-augsburg.de
Cc: stefan.koenig@hs-augsburg.de, nik@hs-augsburg.de
Message-Id: <0456798A824341.B856AF0056@test.de>
Content-Type: text/plain
Subject: [ia3netzdata-onlinetest] MatrNr 12345678

Hallo,

dies ist eine Testmail

Nik
	S: 250 2.0.0 Ok: queued as EBB4A120A66

C: QUIT

Teilfrage 2 - E-Mail mit SMTP mittels der Bibliothek smtplib verschicken

Verschicken Sie nun die gleiche E-Mail wieder an alle drei Adressen mittels der Bibliothek smtplib. Vergleichen Sie hierzu die Beispiele in der Python Dokumentation des Moduls email

In [8]:
# Import smtplib for the actual sending function
import smtplib

# Import the email modules we'll need
from email.message import EmailMessage

text = """
Ich hoffe, die EMail kommt an 

Viele Grüße
"""

msg = EmailMessage()
msg.set_content(text)


me = "meineEMail@adresse.de"
you = "nik.klever@hs-augsburg.de"
cc = "stefan.koenig@hs-augsburg.de"

msg['Subject'] = "[ia3netzdata-onlinetest] MatrNr 12345678"
msg['From'] = me
msg['To'] = you
msg['Cc'] = cc

# Send the message via our own SMTP server.
s = smtplib.SMTP('smtp.hs-augsburg.de')
s.send_message(msg, me, [you, cc])
s.quit()
Out[8]:
(221, b'2.0.0 Bye')

Aufgabe 3 - Erstellen eines Flask-Webservers

Hinweis zu Flask und Jupyter

Bitte beachten Sie, dass Code, in dem ein Flask-Server läuft nicht gleichzeitig weitere Codezeilen abgearbeitet werden können. Daher ist es notwendig die Flask-Server Teilfrage 1 mittels

%%writefile flaskserver.py

in eine Datei zu schreiben und dann in einem eigenen Jupyter Notebook beginnend mit dem Namen IA3_Online_Probe_Pruefung_Flaskserver sowie ihrem Namen und ihrer Matrikelnummer in der ersten Zelle über einen Shell-Aufruf mittels

!python flaskserver.py

laufen zu lassen. Beachten sie, dass dieses Notebook ebenfalls zur Abgabe zählt und daher nicht gelöscht werden sollte.

Host- und Portnummer

Beachten sie zudem, dass sie als Standardhost "0.0.0.0" verwenden müssen sowie den Port

portNummerXXXX

sodass sie den Aufruf für run wie folgt verwenden:

app.run(host="0.0.0.0",port=portNummerXXXX)

Teilfrage 1

Erstellen Sie in einem Editor einen Flask-Webserver der als Antwort auf einen Request sowohl alle Header-Felder des entsprechenden HTTP-Requests als auch die WSGI Umgebung in einem abwechselnd unterschiedlichen Hintergrund in jeweils einer Unordered List anzeigt. Verwenden sie dabei die Methode render_template_string und nicht render_template ! Dabei ist der zurückgegebene Response-Wert (z.B. in einer Variablen resp) in einem Aufruf an den Logger vor dem eigentlichen return auszugeben

In [9]:
%%writefile flaskserver.py
from flask import Flask, request, render_template_string
app = Flask(__name__)

template = """<html>
    <head>
    <title>Index Seite</title>
  <style type="text/css">
.even { background-color:#ffffff; }
.odd { background-color:#e0e0e0; }
  </style>
    </head>
<body>
    <h2>Request Header</h2>
    <ul>
{% for hdr in headers %}
      <li class =  "{{loop.cycle('odd','even')}}"> {{ hdr }} </li>
{% endfor %}
    </ul>

    <h2>WSGI Umgebung</h2>
    <ul>
{% for item in environ %}
      <li class =  "{{loop.cycle('odd','even')}}"> {{ item }}: {{ environ[item] }} </li>
{% endfor %}
    </ul>

</body>
    </html>"""

@app.route("/")
def index():
    headers = request.headers
    environ = request.environ
    app.logger.info(headers)
    return render_template_string(template,headers=headers,environ=environ)

if __name__ == "__main__":
    app.run(host="0.0.0.0",port=8499)
Writing flaskserver.py

Teilfrage 2

Laden Sie - analog wie in Aufgabe 1 - die Startseite ihres Flask-Webservers mittels der Bibliothek ''telnetlib'' herunter.

In [10]:
head, body = httpRequest("127.0.0.1",port=8499)
print(head)
print("----"*10)
print(body[:2000])
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1847
Server: Werkzeug/0.14.1 Python/3.6.6
Date: Wed, 19 Dec 2018 19:01:41 GMT
----------------------------------------
<html>
    <head>
    <title>Index Seite</title>
  <style type="text/css">
.even { background-color:#ffffff; }
.odd { background-color:#e0e0e0; }
  </style>
    </head>
<body>
    <h2>Request Header</h2>
    <ul>

      <li class =  "odd"> (&#39;Host&#39;, &#39;127.0.0.1&#39;) </li>

      <li class =  "even"> (&#39;Connection&#39;, &#39;close&#39;) </li>

    </ul>

    <h2>WSGI Umgebung</h2>
    <ul>

      <li class =  "odd"> wsgi.version: (1, 0) </li>

      <li class =  "even"> wsgi.url_scheme: http </li>

      <li class =  "odd"> wsgi.input: &lt;_io.BufferedReader name=5&gt; </li>

      <li class =  "even"> wsgi.errors: &lt;_io.TextIOWrapper name=&#39;&lt;stderr&gt;&#39; mode=&#39;w&#39; encoding=&#39;UTF-8&#39;&gt; </li>

      <li class =  "odd"> wsgi.multithread: True </li>

      <li class =  "even"> wsgi.multiprocess: False </li>

      <li class =  "odd"> wsgi.run_once: False </li>

      <li class =  "even"> werkzeug.server.shutdown: &lt;function WSGIRequestHandler.make_environ.&lt;locals&gt;.shutdown_server at 0x7effbb9af1e0&gt; </li>

      <li class =  "odd"> SERVER_SOFTWARE: Werkzeug/0.14.1 </li>

      <li class =  "even"> REQUEST_METHOD: GET </li>

      <li class =  "odd"> SCRIPT_NAME:  </li>

      <li class =  "even"> PATH_INFO: / </li>

      <li class =  "odd"> QUERY_STRING:  </li>

      <li class =  "even"> REMOTE_ADDR: 127.0.0.1 </li>

      <li class =  "odd"> REMOTE_PORT: 55292 </li>

      <li class =  "even"> SERVER_NAME: 0.0.0.0 </li>

      <li class =  "odd"> SERVER_PORT: 8499 </li>

      <li class =  "even"> SERVER_PROTOCOL: HTTP/1.1 </li>

      <li class =  "odd"> HTTP_HOST: 127.0.0.1 </li>

      <li class =  "even"> HTTP_CONNECTION: close </li>

      <li class =  "odd"> werkzeug.request: &lt;Request &#39;http://127.0.0.1/&#39; [GET]&gt; </li>

    </ul>

</body>
    </html>

Teilfrage 3

Laden Sie die Startseite ihres Flask-Webservers mittels der Bibliothek ''urllib.request'' herunter.

In [11]:
from urllib.request import urlopen

req = urlopen("http://127.0.0.1:8499")
resp = req.read()
print(resp.decode("utf-8"))
<html>
    <head>
    <title>Index Seite</title>
  <style type="text/css">
.even { background-color:#ffffff; }
.odd { background-color:#e0e0e0; }
  </style>
    </head>
<body>
    <h2>Request Header</h2>
    <ul>

      <li class =  "odd"> (&#39;Accept-Encoding&#39;, &#39;identity&#39;) </li>

      <li class =  "even"> (&#39;Host&#39;, &#39;127.0.0.1:8499&#39;) </li>

      <li class =  "odd"> (&#39;User-Agent&#39;, &#39;Python-urllib/3.6&#39;) </li>

      <li class =  "even"> (&#39;Connection&#39;, &#39;close&#39;) </li>

    </ul>

    <h2>WSGI Umgebung</h2>
    <ul>

      <li class =  "odd"> wsgi.version: (1, 0) </li>

      <li class =  "even"> wsgi.url_scheme: http </li>

      <li class =  "odd"> wsgi.input: &lt;_io.BufferedReader name=5&gt; </li>

      <li class =  "even"> wsgi.errors: &lt;_io.TextIOWrapper name=&#39;&lt;stderr&gt;&#39; mode=&#39;w&#39; encoding=&#39;UTF-8&#39;&gt; </li>

      <li class =  "odd"> wsgi.multithread: True </li>

      <li class =  "even"> wsgi.multiprocess: False </li>

      <li class =  "odd"> wsgi.run_once: False </li>

      <li class =  "even"> werkzeug.server.shutdown: &lt;function WSGIRequestHandler.make_environ.&lt;locals&gt;.shutdown_server at 0x7effbb9be158&gt; </li>

      <li class =  "odd"> SERVER_SOFTWARE: Werkzeug/0.14.1 </li>

      <li class =  "even"> REQUEST_METHOD: GET </li>

      <li class =  "odd"> SCRIPT_NAME:  </li>

      <li class =  "even"> PATH_INFO: / </li>

      <li class =  "odd"> QUERY_STRING:  </li>

      <li class =  "even"> REMOTE_ADDR: 127.0.0.1 </li>

      <li class =  "odd"> REMOTE_PORT: 55294 </li>

      <li class =  "even"> SERVER_NAME: 0.0.0.0 </li>

      <li class =  "odd"> SERVER_PORT: 8499 </li>

      <li class =  "even"> SERVER_PROTOCOL: HTTP/1.1 </li>

      <li class =  "odd"> HTTP_ACCEPT_ENCODING: identity </li>

      <li class =  "even"> HTTP_HOST: 127.0.0.1:8499 </li>

      <li class =  "odd"> HTTP_USER_AGENT: Python-urllib/3.6 </li>

      <li class =  "even"> HTTP_CONNECTION: close </li>

      <li class =  "odd"> werkzeug.request: &lt;Request &#39;http://127.0.0.1:8499/&#39; [GET]&gt; </li>

    </ul>

</body>
    </html>

Teilfrage 4

Öffnen Sie die Startseite ihres Flask-Webservers mittels ihres Browsers und der Url

http://python.hs-augsburg.de:portNummerXXXX

und kopieren Sie den Seitenquelltext in ihr Notebook.

In [ ]:
%%HTML

<html>
    <head>
    <title>Index Seite</title>
  <style type="text/css">
.even { background-color:#ffffff; }
.odd { background-color:#e0e0e0; }
  </style>
    </head>
<body>
    <h2>Request Header</h2>
    <ul>

      <li class =  "odd"> (&#39;Host&#39;, &#39;klever.hs-augsburg.de:8499&#39;) </li>

      <li class =  "even"> (&#39;Connection&#39;, &#39;keep-alive&#39;) </li>

      <li class =  "odd"> (&#39;Upgrade-Insecure-Requests&#39;, &#39;1&#39;) </li>

      <li class =  "even"> (&#39;User-Agent&#39;, &#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36&#39;) </li>

      <li class =  "odd"> (&#39;Accept&#39;, &#39;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8&#39;) </li>

      <li class =  "even"> (&#39;Accept-Encoding&#39;, &#39;gzip, deflate&#39;) </li>

      <li class =  "odd"> (&#39;Accept-Language&#39;, &#39;de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7&#39;) </li>

      <li class =  "even"> (&#39;Cookie&#39;, &#39;_xsrf=2|39b777d8|5640bccf50685dea32d11ffefef4dc50|1539243857; _ga=GA1.2.2097609113.1541753547&#39;) </li>

    </ul>

    <h2>WSGI Umgebung</h2>
    <ul>

      <li class =  "odd"> wsgi.version: (1, 0) </li>

      <li class =  "even"> wsgi.url_scheme: http </li>

      <li class =  "odd"> wsgi.input: &lt;_io.BufferedReader name=5&gt; </li>

      <li class =  "even"> wsgi.errors: &lt;_io.TextIOWrapper name=&#39;&lt;stderr&gt;&#39; mode=&#39;w&#39; encoding=&#39;UTF-8&#39;&gt; </li>

      <li class =  "odd"> wsgi.multithread: True </li>

      <li class =  "even"> wsgi.multiprocess: False </li>

      <li class =  "odd"> wsgi.run_once: False </li>

      <li class =  "even"> werkzeug.server.shutdown: &lt;function WSGIRequestHandler.make_environ.&lt;locals&gt;.shutdown_server at 0x7effbb9be1e0&gt; </li>

      <li class =  "odd"> SERVER_SOFTWARE: Werkzeug/0.14.1 </li>

      <li class =  "even"> REQUEST_METHOD: GET </li>

      <li class =  "odd"> SCRIPT_NAME:  </li>

      <li class =  "even"> PATH_INFO: / </li>

      <li class =  "odd"> QUERY_STRING:  </li>

      <li class =  "even"> REMOTE_ADDR: 62.216.204.79 </li>

      <li class =  "odd"> REMOTE_PORT: 6776 </li>

      <li class =  "even"> SERVER_NAME: 0.0.0.0 </li>

      <li class =  "odd"> SERVER_PORT: 8499 </li>

      <li class =  "even"> SERVER_PROTOCOL: HTTP/1.1 </li>

      <li class =  "odd"> HTTP_HOST: klever.hs-augsburg.de:8499 </li>

      <li class =  "even"> HTTP_CONNECTION: keep-alive </li>

      <li class =  "odd"> HTTP_UPGRADE_INSECURE_REQUESTS: 1 </li>

      <li class =  "even"> HTTP_USER_AGENT: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 </li>

      <li class =  "odd"> HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 </li>

      <li class =  "even"> HTTP_ACCEPT_ENCODING: gzip, deflate </li>

      <li class =  "odd"> HTTP_ACCEPT_LANGUAGE: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7 </li>

      <li class =  "even"> HTTP_COOKIE: _xsrf=2|39b777d8|5640bccf50685dea32d11ffefef4dc50|1539243857; _ga=GA1.2.2097609113.1541753547 </li>

      <li class =  "odd"> werkzeug.request: &lt;Request &#39;http://klever.hs-augsburg.de:8499/&#39; [GET]&gt; </li>

    </ul>

</body>
    </html>

Teilfrage 5

Beenden sie ihren Flaskserver über den Menüpunkt File und darin Close and Halt. Vergleichen sie die drei Ergebnisse sowohl aus dem Flaskserver Notebook als auch in den Ergebnissen der Aufrufe und diskutieren sie den Unterschied.

Jeder Client telnetlib, urllib.request und Browser schicken unterschiedliche Header-Zeilen mit, aus der insbesondere die Komplexität bzw. Simplizität der jeweiligen Clients erkennbar wird.