diff --git a/lecture_13_networking_http_webservers/materials/networking_http.ipynb b/lecture_13_networking_http_webservers/materials/networking_http.ipynb index 4fe2df3..e58502d 100644 --- a/lecture_13_networking_http_webservers/materials/networking_http.ipynb +++ b/lecture_13_networking_http_webservers/materials/networking_http.ipynb @@ -249,7 +249,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "pycharm": { "is_executing": true @@ -258,7 +258,19 @@ "slide_type": "slide" } }, - "outputs": [], + "outputs": [ + { + "ename": "OSError", + "evalue": "[Errno 48] Address already in use", + "output_type": "error", + "traceback": [ + "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[0;31mOSError\u001B[0m Traceback (most recent call last)", + "\u001B[0;32m/var/folders/9g/c878182n0_xf46hl9h8py4bm0000gp/T/ipykernel_15471/3371367506.py\u001B[0m in \u001B[0;36m\u001B[0;34m\u001B[0m\n\u001B[1;32m 4\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 5\u001B[0m \u001B[0ms\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0msocket\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0msocket\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0msocket\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mAF_INET\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0msocket\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mSOCK_STREAM\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m----> 6\u001B[0;31m \u001B[0ms\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mbind\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m\"0.0.0.0\"\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;36m9000\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 7\u001B[0m \u001B[0ms\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mlisten\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;36m1\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 8\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;31mOSError\u001B[0m: [Errno 48] Address already in use" + ] + } + ], "source": [ "# in python:\n", "# server:\n", @@ -850,7 +862,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.5" + "version": "3.9.9" } }, "nbformat": 4, diff --git a/lecture_14_restful_api_design_microservices_best_practices/materials/img/jetbrains-python-stats.png b/lecture_14_restful_api_design_microservices_best_practices/materials/img/jetbrains-python-stats.png index 2a472f7..1efdc43 100644 Binary files a/lecture_14_restful_api_design_microservices_best_practices/materials/img/jetbrains-python-stats.png and b/lecture_14_restful_api_design_microservices_best_practices/materials/img/jetbrains-python-stats.png differ diff --git a/lecture_14_restful_api_design_microservices_best_practices/materials/web_frameworks.ipynb b/lecture_14_restful_api_design_microservices_best_practices/materials/web_frameworks.ipynb index 5e47a28..cda3142 100644 --- a/lecture_14_restful_api_design_microservices_best_practices/materials/web_frameworks.ipynb +++ b/lecture_14_restful_api_design_microservices_best_practices/materials/web_frameworks.ipynb @@ -23,11 +23,11 @@ } }, "source": [ - "## ISO/OSI model\n", + "## What do you use python for\n", "\n", "![](img/jetbrains-python-stats.png)\n", "\n", - "" + "" ] }, { @@ -171,7 +171,7 @@ " path(\"/articles/2003/\", views.special_case_2003),\n", " path(\"/articles//\", views.year_archive),\n", " path(\"/articles///\", views.month_archive),\n", - " path(\"/articles////\", views.article),\n", + " path(\"/articles////\", views.article),\n", "]\n", "```" ] @@ -255,6 +255,11 @@ }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Data Representation example\n", "\n", @@ -266,16 +271,13 @@ "\n", "def detail(request, poll_id):\n", " try:\n", - " p = Poll.bjects.get(pk=poll_id)\n", + " p = Poll.objects.get(pk=poll_id)\n", " except Poll.DoesNotExist:\n", " raise Http404(\"Poll does not exist\")\n", "\n", " return render(request, \"polls/detail.html\", {\"poll\": p})\n", "```" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", @@ -301,6 +303,11 @@ }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Data Model: ORM example\n", "\n", @@ -320,13 +327,15 @@ " release_date = models.DateField()\n", " num_start = models.IntegerField()\n", "```" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Background Tasks\n", "\n", @@ -338,13 +347,15 @@ "- Could be scaled to another machines or cloud services\n", "- Help implementing Web Application as a part of [CQRS](https://ru.wikipedia.org/wiki/CQRS) or any other Asynchronous Messaging paradigm\n", "- Celery is the most popular task scheduler for Python" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Advanced Web Development Topics\n", "\n", @@ -353,13 +364,15 @@ "- Template Engines\n", "- Static Files serving\n", "- Configuration and Deployment" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Caching\n", "\n", @@ -370,24 +383,28 @@ "- Cache is always need to be fresh\n", "- LRU Caching with Read Thru Cache is one of the most popular caching strategies\n", "- Redis is the most popular Key-Value store using for Cached data" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Caching\n", "\n", "![](img/general-chaching-diag.png)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Authentication and Authorization\n", "\n", @@ -395,39 +412,45 @@ "- **Authorization** - gives those users permission to access a resource.\n", "- Popular web frameworks provides readymade Authentication solutions. This is the best choice for the most of Authentication duties.\n", "- Many of popular web frameworks also has community plugins for implementing third-party Authentication (Okta and other OAuth providers, LDAP, SAML SSO providers)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Authentication Types\n", "\n", "- HTTP Basic Auth (pass username and password in request parameters)\n", "- API Key (issue the key within a Web App profile and use it)\n", "- OAuth (user credentials do not pass to the application, security token using instead. Also any token is bind to specific role. Authentication with Authorization features)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## OAuth\n", "\n", "![](img/slack-oauth-diag.png)\n", "\n", "" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Template Engines\n", "\n", @@ -435,13 +458,15 @@ "- Template Engines widely using if Web Application do not need a standalone Frontend\n", "- The most popular Template Engines are: Jinja2 and Django Templates\n", "- Templates are rendering in realtime, unless you do not need to pre-render some of" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Static Files serving\n", "\n", @@ -450,13 +475,15 @@ "- But basically you do not need to serve static with your Backend, and have to rely on Nginx, Cloud CDN, or Frontend Application.\n", "\n", "![](img/general-static-files-serving-diag.png)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Configuration and Deployment\n", "\n", @@ -465,13 +492,15 @@ "- Secret values must be keeped away from configuraton but also should be available to get imported into Application Runtime\n", "- Django support more verbose Debug mode for better development\n", "- Modern Python Web Application could be deployed with Docker container or deployed as is to Cloud infrastructure." - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Modern Python Web Frameworks\n", "\n", @@ -485,13 +514,15 @@ " - Falcon\n", " - Tornado\n", " - Sanic" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Django Essentials\n", "\n", @@ -509,13 +540,15 @@ " - I18n, RSS, sitemaps\n", "- Backward compatibility\n", "- Truly follow [DRY](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself) principles" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Flask Essentials\n", "\n", @@ -524,39 +557,45 @@ "- Very simple and ready-to-go API\n", "- Rich Documentation\n", "- Best for tiny applications or prototyping" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## RESTful API\n", "\n", "- RESTful API: Design\n", "- RESTful API Tools: OpenAPI\n", "- RESTful API Tools: FastAPI" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## RESTful API\n", "\n", "![](img/general-restful-diag.png)\n", "\n", "" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## RESTful API: Design\n", "\n", @@ -568,13 +607,15 @@ "- Keep connection alive\n", "- Use compression for network performance\n", "- Use caching headers" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## RESTful API Tools: OpenAPI\n", "\n", @@ -587,13 +628,15 @@ "- Solve problems of bad API Documentation\n", "- Good for API auto-testing\n", "- Easy to track API changes" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## RESTful API Tools: FastAPI\n", "\n", @@ -603,26 +646,30 @@ "- Perfect in data validation with Python Type Hints and Pydantic Library\n", "- Great Documentation\n", "- Built-in support for OpenAPI" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## RESTful Frameworks and Tools\n", "\n", "- FastAPI\n", "- Django REST Framework\n", "- Flask-restful" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## More to Read\n", "\n", @@ -642,21 +689,20 @@ "- RESTful Design:\n", " - [Best Practices (Microsoft)](https://docs.microsoft.com/ru-ru/azure/architecture/best-practices/api-design)\n", " - [Django REST Framework Tutorial](https://www.django-rest-framework.org/tutorial/quickstart/)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Special thanks Evgenii Uvarov for original slides!\n", "\n", "# THE END" - ], - "metadata": { - "collapsed": false - } + ] } ], "metadata": { @@ -676,7 +722,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.5" + "version": "3.9.9" } }, "nbformat": 4,