From 26470de563bbe3bc65a73718aee1988ba64e8601 Mon Sep 17 00:00:00 2001 From: gsingh58 <gurmail-singh@wisc.edu> Date: Tue, 5 Mar 2024 05:22:26 -0600 Subject: [PATCH] lec12 and 13: ipynb files added --- lecture_material/12-web-2/solution.ipynb | 101 +++++++++++ lecture_material/12-web-2/solution.py | 54 ++++++ .../12-web-2/template_lec_001.ipynb | 84 ++++++++++ lecture_material/12-web-2/template_lec_001.py | 36 ++++ .../12-web-2/template_lec_002.ipynb | 84 ++++++++++ lecture_material/12-web-2/template_lec_002.py | 36 ++++ lecture_material/13-web-3/solution.ipynb | 158 ++++++++++++++++++ lecture_material/13-web-3/solution.py | 91 ++++++++++ .../13-web-3/template_lec_001.ipynb | 110 ++++++++++++ lecture_material/13-web-3/template_lec_001.py | 47 ++++++ .../13-web-3/template_lec_002.ipynb | 110 ++++++++++++ lecture_material/13-web-3/template_lec_002.py | 47 ++++++ 12 files changed, 958 insertions(+) create mode 100644 lecture_material/12-web-2/solution.ipynb create mode 100644 lecture_material/12-web-2/solution.py create mode 100644 lecture_material/12-web-2/template_lec_001.ipynb create mode 100644 lecture_material/12-web-2/template_lec_001.py create mode 100644 lecture_material/12-web-2/template_lec_002.ipynb create mode 100644 lecture_material/12-web-2/template_lec_002.py create mode 100644 lecture_material/13-web-3/solution.ipynb create mode 100644 lecture_material/13-web-3/solution.py create mode 100644 lecture_material/13-web-3/template_lec_001.ipynb create mode 100644 lecture_material/13-web-3/template_lec_001.py create mode 100644 lecture_material/13-web-3/template_lec_002.ipynb create mode 100644 lecture_material/13-web-3/template_lec_002.py diff --git a/lecture_material/12-web-2/solution.ipynb b/lecture_material/12-web-2/solution.ipynb new file mode 100644 index 0000000..8ca8f48 --- /dev/null +++ b/lecture_material/12-web-2/solution.ipynb @@ -0,0 +1,101 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cf313adf", + "metadata": {}, + "source": [ + "# Web 2: Flask" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d55e4bb4-9f29-4f4f-bba6-05054718259b", + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import time\n", + "import urllib.robotparser" + ] + }, + { + "cell_type": "markdown", + "id": "527600aa", + "metadata": {}, + "source": [ + "### Rate-limited webpage parsing\n", + "\n", + "- `requests` module:\n", + " - `resp = requests.get(<URL>)` method: enables us to send HTTP GET request\n", + " - `resp.status_code`: status code of the response\n", + " - `resp.text`: `str` text content of the response\n", + " - `resp.headers`: `dict` content of response headers" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8241e51c", + "metadata": {}, + "outputs": [], + "source": [ + "base_url = \"http://34.123.132.20:5000/\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "6cc81b85", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'welcome!'" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def friendly_get(url):\n", + " while True:\n", + " resp = requests.get(url)\n", + " if resp.status_code == 429:\n", + " seconds = int(resp.headers.get(\"Retry-After\", 1))\n", + " print(f\"sleep {seconds}\")\n", + " time.sleep(seconds)\n", + " continue\n", + " resp.raise_for_status() # raise exception if not 200\n", + " return resp\n", + " \n", + "friendly_get(base_url + \"/slow\").text" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/lecture_material/12-web-2/solution.py b/lecture_material/12-web-2/solution.py new file mode 100644 index 0000000..941b19f --- /dev/null +++ b/lecture_material/12-web-2/solution.py @@ -0,0 +1,54 @@ +import flask # requires installation if not already installed - pip3 install flask +import time +import json + +app = flask.Flask("my application") # name of the web application can be anything + +major_counts = {} +last_visit = 0 # TODO: dict of visit times, for each IP + +# TODO: create a slow page +# GOAL: don't let people visit this more often than once per 3s +# flask.request.remote_addr: enables us to take action based on the IP address from +# which we receive the request +@app.route("/slow") +def slow(): + global last_visit + print("VISITOR", flask.request.remote_addr) + if time.time() - last_visit > 3: + last_visit = time.time() + return "welcome!" + else: + return flask.Response("<b>go away</b>", + status=429, + headers={"Retry-After": "3"}) + +# TODO: write code for creating a page for time.html +# TEMPLATE semi-static / semi-dynamic +@app.route("/time.html") +def clock(): + with open("time.html") as f: + s = f.read() + s = s.replace("REPLACE_ME", str(time.time())) + return s + +# TODO: create a dynamic page ha.html +# DYNAMIC +@app.route("/ha.html") +def laugh(): + return "ha "*1000 + +# STATIC +# @ operator is called a "decorator" +@app.route("/") +def home(): + with open("index.html") as f: + html = f.read() + + return html + +if __name__ == "__main__": + app.run(host="0.0.0.0", debug=True, threaded=False) + +# app.run never returns, so don't define functions +# after this (the def lines will never be reached) diff --git a/lecture_material/12-web-2/template_lec_001.ipynb b/lecture_material/12-web-2/template_lec_001.ipynb new file mode 100644 index 0000000..d4f7589 --- /dev/null +++ b/lecture_material/12-web-2/template_lec_001.ipynb @@ -0,0 +1,84 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cf313adf", + "metadata": {}, + "source": [ + "# Web 2: Flask" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d55e4bb4-9f29-4f4f-bba6-05054718259b", + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import time\n" + ] + }, + { + "cell_type": "markdown", + "id": "527600aa", + "metadata": {}, + "source": [ + "### Rate-limited webpage parsing\n", + "\n", + "- `requests` module:\n", + " - `resp = requests.get(<URL>)` method: enables us to send HTTP GET request\n", + " - `resp.status_code`: status code of the response\n", + " - `resp.text`: `str` text content of the response\n", + " - `resp.headers`: `dict` content of response headers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8241e51c", + "metadata": {}, + "outputs": [], + "source": [ + "base_url = \"http://34.123.132.20:5000/\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cc81b85", + "metadata": {}, + "outputs": [], + "source": [ + "def friendly_get(url):\n", + " while True:\n", + " resp = requests.get(url)\n", + " resp.raise_for_status() # raise exception if not 200\n", + " return resp\n", + " \n", + "friendly_get(base_url + \"/slow\").text" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/lecture_material/12-web-2/template_lec_001.py b/lecture_material/12-web-2/template_lec_001.py new file mode 100644 index 0000000..94e9273 --- /dev/null +++ b/lecture_material/12-web-2/template_lec_001.py @@ -0,0 +1,36 @@ +import flask # requires installation if not already installed - pip3 install flask +import time +import json + +app = flask.Flask("my application") # name of the web application can be anything + +major_counts = {} +last_visit = 0 # TODO: dict of visit times, for each IP + +# TODO: create a slow page +# GOAL: don't let people visit this more often than once per 3s +# flask.request.remote_addr: enables us to take action based on the IP address from +# which we receive the request + +# TODO: write code for creating a page for time.html +# TEMPLATE semi-static / semi-dynamic + +# TODO: create a dynamic page ha.html +# DYNAMIC + +# STATIC +# @ operator is called a "decorator" +# STATIC +# @ operator is called a "decorator" +@app.route("/") +def home(): + with open("index.html") as f: + html = f.read() + + return html + +if __name__ == "__main__": + app.run(host="0.0.0.0", debug=True, threaded=False) + +# app.run never returns, so don't define functions +# after this (the def lines will never be reached) diff --git a/lecture_material/12-web-2/template_lec_002.ipynb b/lecture_material/12-web-2/template_lec_002.ipynb new file mode 100644 index 0000000..d4f7589 --- /dev/null +++ b/lecture_material/12-web-2/template_lec_002.ipynb @@ -0,0 +1,84 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cf313adf", + "metadata": {}, + "source": [ + "# Web 2: Flask" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d55e4bb4-9f29-4f4f-bba6-05054718259b", + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import time\n" + ] + }, + { + "cell_type": "markdown", + "id": "527600aa", + "metadata": {}, + "source": [ + "### Rate-limited webpage parsing\n", + "\n", + "- `requests` module:\n", + " - `resp = requests.get(<URL>)` method: enables us to send HTTP GET request\n", + " - `resp.status_code`: status code of the response\n", + " - `resp.text`: `str` text content of the response\n", + " - `resp.headers`: `dict` content of response headers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8241e51c", + "metadata": {}, + "outputs": [], + "source": [ + "base_url = \"http://34.123.132.20:5000/\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cc81b85", + "metadata": {}, + "outputs": [], + "source": [ + "def friendly_get(url):\n", + " while True:\n", + " resp = requests.get(url)\n", + " resp.raise_for_status() # raise exception if not 200\n", + " return resp\n", + " \n", + "friendly_get(base_url + \"/slow\").text" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/lecture_material/12-web-2/template_lec_002.py b/lecture_material/12-web-2/template_lec_002.py new file mode 100644 index 0000000..94e9273 --- /dev/null +++ b/lecture_material/12-web-2/template_lec_002.py @@ -0,0 +1,36 @@ +import flask # requires installation if not already installed - pip3 install flask +import time +import json + +app = flask.Flask("my application") # name of the web application can be anything + +major_counts = {} +last_visit = 0 # TODO: dict of visit times, for each IP + +# TODO: create a slow page +# GOAL: don't let people visit this more often than once per 3s +# flask.request.remote_addr: enables us to take action based on the IP address from +# which we receive the request + +# TODO: write code for creating a page for time.html +# TEMPLATE semi-static / semi-dynamic + +# TODO: create a dynamic page ha.html +# DYNAMIC + +# STATIC +# @ operator is called a "decorator" +# STATIC +# @ operator is called a "decorator" +@app.route("/") +def home(): + with open("index.html") as f: + html = f.read() + + return html + +if __name__ == "__main__": + app.run(host="0.0.0.0", debug=True, threaded=False) + +# app.run never returns, so don't define functions +# after this (the def lines will never be reached) diff --git a/lecture_material/13-web-3/solution.ipynb b/lecture_material/13-web-3/solution.ipynb new file mode 100644 index 0000000..6e99ca0 --- /dev/null +++ b/lecture_material/13-web-3/solution.ipynb @@ -0,0 +1,158 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cf313adf", + "metadata": {}, + "source": [ + "# Web 3: More Flask" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d55e4bb4-9f29-4f4f-bba6-05054718259b", + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import time\n", + "import urllib.robotparser" + ] + }, + { + "cell_type": "markdown", + "id": "527600aa", + "metadata": {}, + "source": [ + "### Rate-limited webpage parsing\n", + "\n", + "- `requests` module:\n", + " - `resp = requests.get(<URL>)` method: enables us to send HTTP GET request\n", + " - `resp.status_code`: status code of the response\n", + " - `resp.text`: `str` text content of the response\n", + " - `resp.headers`: `dict` content of response headers" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8241e51c", + "metadata": {}, + "outputs": [], + "source": [ + "base_url = \"http://34.123.132.20:5000/\"" + ] + }, + { + "cell_type": "markdown", + "id": "23ba100b", + "metadata": {}, + "source": [ + "### `urllib.robotparser`\n", + "\n", + "- Documentation: https://docs.python.org/3/library/urllib.robotparser.html" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "379c3ae5-7344-45b1-88c3-b35f0bd8eb5b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rp = urllib.robotparser.RobotFileParser()\n", + "rp.set_url(base_url + \"/robots.txt\")\n", + "rp.read()\n", + "rp.can_fetch(\"cs320bot\", base_url + \"/slow\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2e3fb01c-4281-4cbf-8828-98e04d27d09a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rp.can_fetch(\"cs320bot\", base_url + \"/never\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6cc81b85", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'welcome!'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def friendly_get(url):\n", + " if not rp.can_fetch(\"cs320bot\", url):\n", + " raise Exception(\"you're not supposed to visit that page\")\n", + " while True:\n", + " resp = requests.get(url)\n", + " if resp.status_code == 429:\n", + " seconds = int(resp.headers.get(\"Retry-After\", 1))\n", + " print(f\"sleep {seconds}\")\n", + " time.sleep(seconds)\n", + " continue\n", + " resp.raise_for_status() # raise exception if not 200\n", + " return resp\n", + " \n", + "friendly_get(base_url + \"/slow\").text" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/lecture_material/13-web-3/solution.py b/lecture_material/13-web-3/solution.py new file mode 100644 index 0000000..3253c47 --- /dev/null +++ b/lecture_material/13-web-3/solution.py @@ -0,0 +1,91 @@ +import flask # requires installation if not already installed - pip3 install flask +import time +import json + +app = flask.Flask("my application") # name of the web application can be anything + +major_counts = {} +last_visit = 0 # TODO: dict of visit times, for each IP + +# TODO: create a survey page +# flask.request.args: enables us to get the arguments passed as part of the URL +@app.route("/survey") +def survey(): + major = flask.request.args.get("major", "unkown") + if not major in major_counts: + major_counts[major] = 0 + major_counts[major] += 1 + + return "MAJORS: \n" + json.dumps(major_counts) + +# TODO: create an add page +@app.route("/add") +def adder(): + args = dict(flask.request.args) + try: + x = float(args["x"]) + y = float(args["y"]) + except KeyError: + return "Please specify x and y." + return f"{x} + {y} = {x+y}" + +# TODO: create a never page +@app.route("/never") +def never(): + return "humans only, no bots allowed!" + +# TODO: create a robots.txt page +# flask.Response: enables us to create a response object instance +# Arguments: str representing reponse, headers dict representing metadata +@app.route("/robots.txt") +def bot_rules(): + return flask.Response("""\ + User-Agent: * + Disallow: /never + """, headers={"Content-Type": "text/plain"}) + +# TODO: create a slow page +# GOAL: don't let people visit this more often than once per 3s +# flask.request.remote_addr: enables us to take action based on the IP address from +# which we receive the request +@app.route("/slow") +def slow(): + global last_visit + print("VISITOR", flask.request.remote_addr) + if time.time() - last_visit > 3: + last_visit = time.time() + return "welcome!" + else: + return flask.Response("<b>go away</b>", + status=429, + headers={"Retry-After": "3"}) + +# TODO: write code for creating a page for time.html +# TEMPLATE semi-static / semi-dynamic +@app.route("/time.html") +def clock(): + with open("time.html") as f: + s = f.read() + s = s.replace("REPLACE_ME", str(time.time())) + return s + +# TODO: create a dynamic page ha.html +# DYNAMIC +@app.route("/ha.html") +def laugh(): + return "ha "*1000 + +# STATIC +# @ operator is called a "decorator" +@app.route("/") +def home(): + with open("index.html") as f: + html = f.read() + + return html + +if __name__ == "__main__": + app.run(host="0.0.0.0", debug=True, threaded=False) + +# app.run never returns, so don't define functions +# after this (the def lines will never be reached) diff --git a/lecture_material/13-web-3/template_lec_001.ipynb b/lecture_material/13-web-3/template_lec_001.ipynb new file mode 100644 index 0000000..66eb333 --- /dev/null +++ b/lecture_material/13-web-3/template_lec_001.ipynb @@ -0,0 +1,110 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cf313adf", + "metadata": {}, + "source": [ + "# Web 3: More Flask" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d55e4bb4-9f29-4f4f-bba6-05054718259b", + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import time\n" + ] + }, + { + "cell_type": "markdown", + "id": "527600aa", + "metadata": {}, + "source": [ + "### Rate-limited webpage parsing\n", + "\n", + "- `requests` module:\n", + " - `resp = requests.get(<URL>)` method: enables us to send HTTP GET request\n", + " - `resp.status_code`: status code of the response\n", + " - `resp.text`: `str` text content of the response\n", + " - `resp.headers`: `dict` content of response headers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8241e51c", + "metadata": {}, + "outputs": [], + "source": [ + "base_url = \"http://34.123.132.20:5000/\"" + ] + }, + { + "cell_type": "markdown", + "id": "23ba100b", + "metadata": {}, + "source": [ + "### `urllib.robotparser`\n", + "\n", + "- Documentation: https://docs.python.org/3/library/urllib.robotparser.html" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "379c3ae5-7344-45b1-88c3-b35f0bd8eb5b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e3fb01c-4281-4cbf-8828-98e04d27d09a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cc81b85", + "metadata": {}, + "outputs": [], + "source": [ + "def friendly_get(url):\n", + " while True:\n", + " resp = requests.get(url)\n", + " resp.raise_for_status() # raise exception if not 200\n", + " return resp\n", + " \n", + "friendly_get(base_url + \"/slow\").text" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/lecture_material/13-web-3/template_lec_001.py b/lecture_material/13-web-3/template_lec_001.py new file mode 100644 index 0000000..b939f28 --- /dev/null +++ b/lecture_material/13-web-3/template_lec_001.py @@ -0,0 +1,47 @@ +import flask # requires installation if not already installed - pip3 install flask +import time +import json + +app = flask.Flask("my application") # name of the web application can be anything + +major_counts = {} +last_visit = 0 # TODO: dict of visit times, for each IP + +# TODO: create a survey page +# flask.request.args: enables us to get the arguments passed as part of the URL + +# TODO: create an add page + +# TODO: create a never page + +# TODO: create a robots.txt page +# flask.Response: enables us to create a response object instance +# Arguments: str representing reponse, headers dict representing metadata + +# TODO: create a slow page +# GOAL: don't let people visit this more often than once per 3s +# flask.request.remote_addr: enables us to take action based on the IP address from +# which we receive the request + +# TODO: write code for creating a page for time.html +# TEMPLATE semi-static / semi-dynamic + +# TODO: create a dynamic page ha.html +# DYNAMIC + +# STATIC +# @ operator is called a "decorator" +# STATIC +# @ operator is called a "decorator" +@app.route("/") +def home(): + with open("index.html") as f: + html = f.read() + + return html + +if __name__ == "__main__": + app.run(host="0.0.0.0", debug=True, threaded=False) + +# app.run never returns, so don't define functions +# after this (the def lines will never be reached) diff --git a/lecture_material/13-web-3/template_lec_002.ipynb b/lecture_material/13-web-3/template_lec_002.ipynb new file mode 100644 index 0000000..66eb333 --- /dev/null +++ b/lecture_material/13-web-3/template_lec_002.ipynb @@ -0,0 +1,110 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cf313adf", + "metadata": {}, + "source": [ + "# Web 3: More Flask" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d55e4bb4-9f29-4f4f-bba6-05054718259b", + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import time\n" + ] + }, + { + "cell_type": "markdown", + "id": "527600aa", + "metadata": {}, + "source": [ + "### Rate-limited webpage parsing\n", + "\n", + "- `requests` module:\n", + " - `resp = requests.get(<URL>)` method: enables us to send HTTP GET request\n", + " - `resp.status_code`: status code of the response\n", + " - `resp.text`: `str` text content of the response\n", + " - `resp.headers`: `dict` content of response headers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8241e51c", + "metadata": {}, + "outputs": [], + "source": [ + "base_url = \"http://34.123.132.20:5000/\"" + ] + }, + { + "cell_type": "markdown", + "id": "23ba100b", + "metadata": {}, + "source": [ + "### `urllib.robotparser`\n", + "\n", + "- Documentation: https://docs.python.org/3/library/urllib.robotparser.html" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "379c3ae5-7344-45b1-88c3-b35f0bd8eb5b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e3fb01c-4281-4cbf-8828-98e04d27d09a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cc81b85", + "metadata": {}, + "outputs": [], + "source": [ + "def friendly_get(url):\n", + " while True:\n", + " resp = requests.get(url)\n", + " resp.raise_for_status() # raise exception if not 200\n", + " return resp\n", + " \n", + "friendly_get(base_url + \"/slow\").text" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/lecture_material/13-web-3/template_lec_002.py b/lecture_material/13-web-3/template_lec_002.py new file mode 100644 index 0000000..b939f28 --- /dev/null +++ b/lecture_material/13-web-3/template_lec_002.py @@ -0,0 +1,47 @@ +import flask # requires installation if not already installed - pip3 install flask +import time +import json + +app = flask.Flask("my application") # name of the web application can be anything + +major_counts = {} +last_visit = 0 # TODO: dict of visit times, for each IP + +# TODO: create a survey page +# flask.request.args: enables us to get the arguments passed as part of the URL + +# TODO: create an add page + +# TODO: create a never page + +# TODO: create a robots.txt page +# flask.Response: enables us to create a response object instance +# Arguments: str representing reponse, headers dict representing metadata + +# TODO: create a slow page +# GOAL: don't let people visit this more often than once per 3s +# flask.request.remote_addr: enables us to take action based on the IP address from +# which we receive the request + +# TODO: write code for creating a page for time.html +# TEMPLATE semi-static / semi-dynamic + +# TODO: create a dynamic page ha.html +# DYNAMIC + +# STATIC +# @ operator is called a "decorator" +# STATIC +# @ operator is called a "decorator" +@app.route("/") +def home(): + with open("index.html") as f: + html = f.read() + + return html + +if __name__ == "__main__": + app.run(host="0.0.0.0", debug=True, threaded=False) + +# app.run never returns, so don't define functions +# after this (the def lines will never be reached) -- GitLab