mirror of
https://github.com/linkedin/school-of-sre
synced 2026-01-15 21:18:03 +00:00
Deployed 6e8f373 with MkDocs version: 1.0.4
This commit is contained in:
332
python_web/intro/index.html
Normal file
332
python_web/intro/index.html
Normal file
@@ -0,0 +1,332 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
||||
|
||||
<link rel="shortcut icon" href="../../img/favicon.ico">
|
||||
<title>Intro - school_of_sre</title>
|
||||
<link href="../../css/bootstrap-custom.min.css" rel="stylesheet">
|
||||
<link href="../../css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="../../css/base.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css">
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script src="../../js/jquery-1.10.2.min.js" defer></script>
|
||||
<script src="../../js/bootstrap-3.0.3.min.js" defer></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
|
||||
<!-- Collapsed navigation -->
|
||||
<div class="navbar-header">
|
||||
<!-- Expander button -->
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="../..">school_of_sre</a>
|
||||
</div>
|
||||
|
||||
<!-- Expanded navigation -->
|
||||
<div class="navbar-collapse collapse">
|
||||
<!-- Main navigation -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li >
|
||||
<a href="../..">Home</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Git <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../git/git-basics/">Git Basics</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/branches/">Working With Branches</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/github-hooks/">Github and Hooks</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown active">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Python and Web <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li class="active">
|
||||
<a href="./">Intro</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../python-concepts/">Some Python Concepts</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../python-web-flask/">Python, Web and Flask</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../url-shorten-app/">The URL Shortening App</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../sre-conclusion/">SRE Aspects of The App and Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Systems Design <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/intro/">Intro</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/scalability/">Scalability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/availability/">Availability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/fault-tolerance/">Fault Tolerance</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/conclusion/">Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<a href="#" data-toggle="modal" data-target="#mkdocs_search_modal">
|
||||
<i class="fa fa-search"></i> Search
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="next" href="../../git/github-hooks/">
|
||||
<i class="fa fa-arrow-left"></i> Previous
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="prev" href="../python-concepts/">
|
||||
Next <i class="fa fa-arrow-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="col-md-3"><div class="bs-sidebar hidden-print affix well" role="complementary">
|
||||
<ul class="nav bs-sidenav">
|
||||
<li class="main active"><a href="#school-of-sre-python-and-the-web">School of SRE: Python and The Web</a></li>
|
||||
<li><a href="#pre-reads">Pre - Reads</a></li>
|
||||
<li><a href="#what-to-expect-from-this-training">What to expect from this training</a></li>
|
||||
<li><a href="#what-is-not-covered-under-this-training">What is not covered under this training</a></li>
|
||||
<li><a href="#training-content">Training Content</a></li>
|
||||
<li><a href="#the-python-language">The Python Language</a></li>
|
||||
</ul>
|
||||
</div></div>
|
||||
<div class="col-md-9" role="main">
|
||||
|
||||
<h1 id="school-of-sre-python-and-the-web">School of SRE: Python and The Web</h1>
|
||||
<h2 id="pre-reads">Pre - Reads</h2>
|
||||
<ul>
|
||||
<li>Basic understanding of python language.</li>
|
||||
<li>Basic familiarity with flask framework.</li>
|
||||
</ul>
|
||||
<h2 id="what-to-expect-from-this-training">What to expect from this training</h2>
|
||||
<p>This course is divided into two high level parts. In the first part, assuming familiarity with python language’s basic operations and syntax usage, we will dive a little deeper into understanding python as a language. We will compare python with other programming languages that you might already know like Java and C. We will also explore concepts of Python objects and with help of that, explore python features like decorators.</p>
|
||||
<p>In the second part which will revolve around the web, and also assume familiarity with the Flask framework, we will start from the socket module and work with HTTP requests. This will demystify how frameworks like flask work internally.</p>
|
||||
<p>And to introduce SRE flavour to the course, we will design, develop and deploy (in theory) a URL shortening application. We will emphasize parts of the whole process that are more important as an SRE of the said app/service.</p>
|
||||
<h2 id="what-is-not-covered-under-this-training">What is not covered under this training</h2>
|
||||
<p>Extensive knowledge of python internals and advanced python.</p>
|
||||
<h2 id="training-content">Training Content</h2>
|
||||
<h3 id="lab-environment-setup">Lab Environment Setup</h3>
|
||||
<p>Have latest version of python installed</p>
|
||||
<h3 id="toc">TOC</h3>
|
||||
<ol>
|
||||
<li>The Python Language<ol>
|
||||
<li>Some Python Concepts</li>
|
||||
<li>Python Gotchas</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>Python and Web<ol>
|
||||
<li>Sockets</li>
|
||||
<li>Flask</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>The URL Shortening App<ol>
|
||||
<li>Design</li>
|
||||
<li>Scaling The App</li>
|
||||
<li>Monitoring The App</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
<h2 id="the-python-language">The Python Language</h2>
|
||||
<p>Assuming you know a little bit of C/C++ and Java, let's try to discuss the following questions in context of those two languages and python. You might have heard that C/C++ is a compiled language while python is an interpreted language. Generally, with compiled language we first compile the program and then run the executable while in case of python we run the source code directly like <code>python hello_world.py</code>. While Java, being an interpreted language, still has a separate compilation step and then its run. So what's really the difference?</p>
|
||||
<h3 id="compiled-vs-interpreted">Compiled vs. Interpreted</h3>
|
||||
<p>This might sound a little weird to you: python, in a way is a compiled language! Python has a compiler built-in! It is obvious in the case of java since we compile it using a separate command ie: <code>javac helloWorld.java</code> and it will produce a <code>.class</code> file which we know as a <em>bytecode</em>. Well, python is very similar to that. One difference here is that there is no separate compile command/binary needed to run a python program.</p>
|
||||
<p><strong>What is the difference then, between java and python?</strong>
|
||||
Well, Java's compiler is more strict and sophisticated. As you might know Java is a statically typed language. So the compiler is written in a way that it can verify types related errors during compile time. While python being a <em>dynamic</em> language, types are not known until a program is run. So in a way, python compiler is dumb (or, less strict). But there indeed is a compile step involved when a python program is run. You might have seen python bytecode files with <code>.pyc</code> extension. Here is how you can see bytecode for a given python program.</p>
|
||||
<pre><code class="bash"># Create a Hello World
|
||||
spatel1-mn1:tmp spatel1$ echo "print('hello world')" > hello_world.py
|
||||
|
||||
# Making sure it runs
|
||||
spatel1-mn1:tmp spatel1$ python3 hello_world.py
|
||||
hello world
|
||||
|
||||
# The bytecode of the given program
|
||||
spatel1-mn1:tmp spatel1$ python -m dis hello_world.py
|
||||
1 0 LOAD_NAME 0 (print)
|
||||
2 LOAD_CONST 0 ('hello world')
|
||||
4 CALL_FUNCTION 1
|
||||
6 POP_TOP
|
||||
8 LOAD_CONST 1 (None)
|
||||
10 RETURN_VALUE
|
||||
</code></pre>
|
||||
|
||||
<p>Read more about dis module <a href="https://docs.python.org/3/library/dis.html">here</a></p>
|
||||
<p>Now coming to C/C++, there of course is a compiler. But the output is different than what java/python compiler would produce. Compiling a C program would produce what we also know as <em>machine code</em>. As opposed to bytecode.</p>
|
||||
<h3 id="running-the-programs">Running The Programs</h3>
|
||||
<p>We know compilation is involved in all 3 languages we are discussing. Just that the compilers are different in nature and they output different types of content. In case of C/C++, the output is machine code which can be directly read by your operating system. When you execute that program, your OS will know how exactly to run it. <strong>But this is not the case with bytecode.</strong></p>
|
||||
<p>Those bytecodes are language specific. Python has its own set of bytecode defined (more in <code>dis</code> module) and so does java. So naturally, your operating system will not know how to run it. To run this bytecode, we have something called Virtual Machines. Ie: The JVM or the Python VM (CPython, Jython). These so called Virtual Machines are the programs which can read the bytecode and run it on a given operating system. Python has multiple VMs available. Cpython is a python VM implemented in C language, similarly Jython is a Java implementation of python VM. <strong>At the end of the day, what they should be capable of is to understand python language syntax, be able to compile it to bytecode and be able to run that bytecode.</strong> You can implement a python VM in any language! (And people do so, just because it can be done)</p>
|
||||
<pre><code> The Operating System
|
||||
|
||||
+------------------------------------+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
hello_world.py Python bytecode | Python VM Process |
|
||||
| |
|
||||
+----------------+ +----------------+ | +----------------+ |
|
||||
|print(... | COMPILE |LOAD_CONST... | | |Reads bytecode | |
|
||||
| +--------------->+ +------------------->+line by line | |
|
||||
| | | | | |and executes. | |
|
||||
| | | | | | | |
|
||||
+----------------+ +----------------+ | +----------------+ |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
hello_world.c OS Specific machinecode | A New Process |
|
||||
| |
|
||||
+----------------+ +----------------+ | +----------------+ |
|
||||
|void main() { | COMPILE | binary contents| | | binary contents| |
|
||||
| +--------------->+ +------------------->+ | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
+----------------+ +----------------+ | +----------------+ |
|
||||
| (binary contents |
|
||||
| runs as is) |
|
||||
| |
|
||||
| |
|
||||
+------------------------------------+
|
||||
</code></pre>
|
||||
|
||||
<p>Two things to note for above diagram:</p>
|
||||
<ol>
|
||||
<li>Generally, when we run a python program, a python VM process is started which reads the python source code, compiles it to byte code and run it in a single step. Compiling is not a separate step. Shown only for illustration purpose.</li>
|
||||
<li>Binaries generated for C like languages are not <em>exactly</em> run as is. Since there are multiple types of binaries (eg: ELF), there are more complicated steps involved in order to run a binary but we will not go into that since all that is done at OS level.</li>
|
||||
</ol></div>
|
||||
</div>
|
||||
|
||||
<footer class="col-md-12">
|
||||
<hr>
|
||||
<p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
|
||||
</footer>
|
||||
<script>
|
||||
var base_url = "../..",
|
||||
shortcuts = {"search": 83, "next": 78, "help": 191, "previous": 80};
|
||||
</script>
|
||||
<script src="../../js/base.js" defer></script>
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
<div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="Search Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Search</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
From here you can search these documents. Enter
|
||||
your search terms below.
|
||||
</p>
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="Keyboard Shortcuts Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Keyboard Shortcuts</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20%;">Keys</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="help shortcut"><kbd>?</kbd></td>
|
||||
<td>Open this help</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="next shortcut"><kbd>n</kbd></td>
|
||||
<td>Next page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="prev shortcut"><kbd>p</kbd></td>
|
||||
<td>Previous page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="search shortcut"><kbd>s</kbd></td>
|
||||
<td>Search</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
370
python_web/python-concepts/index.html
Normal file
370
python_web/python-concepts/index.html
Normal file
@@ -0,0 +1,370 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
||||
|
||||
<link rel="shortcut icon" href="../../img/favicon.ico">
|
||||
<title>Some Python Concepts - school_of_sre</title>
|
||||
<link href="../../css/bootstrap-custom.min.css" rel="stylesheet">
|
||||
<link href="../../css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="../../css/base.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css">
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script src="../../js/jquery-1.10.2.min.js" defer></script>
|
||||
<script src="../../js/bootstrap-3.0.3.min.js" defer></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
|
||||
<!-- Collapsed navigation -->
|
||||
<div class="navbar-header">
|
||||
<!-- Expander button -->
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="../..">school_of_sre</a>
|
||||
</div>
|
||||
|
||||
<!-- Expanded navigation -->
|
||||
<div class="navbar-collapse collapse">
|
||||
<!-- Main navigation -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li >
|
||||
<a href="../..">Home</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Git <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../git/git-basics/">Git Basics</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/branches/">Working With Branches</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/github-hooks/">Github and Hooks</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown active">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Python and Web <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../intro/">Intro</a>
|
||||
</li>
|
||||
|
||||
<li class="active">
|
||||
<a href="./">Some Python Concepts</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../python-web-flask/">Python, Web and Flask</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../url-shorten-app/">The URL Shortening App</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../sre-conclusion/">SRE Aspects of The App and Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Systems Design <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/intro/">Intro</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/scalability/">Scalability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/availability/">Availability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/fault-tolerance/">Fault Tolerance</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/conclusion/">Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<a href="#" data-toggle="modal" data-target="#mkdocs_search_modal">
|
||||
<i class="fa fa-search"></i> Search
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="next" href="../intro/">
|
||||
<i class="fa fa-arrow-left"></i> Previous
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="prev" href="../python-web-flask/">
|
||||
Next <i class="fa fa-arrow-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="col-md-3"><div class="bs-sidebar hidden-print affix well" role="complementary">
|
||||
<ul class="nav bs-sidenav">
|
||||
<li class="main active"><a href="#some-python-concepts">Some Python Concepts</a></li>
|
||||
<li><a href="#python-functions">Python Functions</a></li>
|
||||
<li><a href="#decorators">Decorators</a></li>
|
||||
<li><a href="#some-gotchas">Some Gotchas</a></li>
|
||||
</ul>
|
||||
</div></div>
|
||||
<div class="col-md-9" role="main">
|
||||
|
||||
<h1 id="some-python-concepts">Some Python Concepts</h1>
|
||||
<p>Though you are expected to know python and its syntax at basic level, let us discuss some fundamental concepts that will help you understand the python language better.</p>
|
||||
<p><strong>Everything in Python is an object.</strong></p>
|
||||
<p>That includes the functions, lists, dicts, classes, modules, a running function (instance of function definition), everything. In the CPython, it would mean there is an underlying struct variable for each object.</p>
|
||||
<p>In python's current execution context, all the variables are stored in a dict. It'd be a string to object mapping. If you have a function and a float variable defined in the current context, here is how it is handled internally.</p>
|
||||
<pre><code class="python">>>> float_number=42.0
|
||||
>>> def foo_func():
|
||||
... pass
|
||||
...
|
||||
|
||||
# NOTICE HOW VARIABLE NAMES ARE STRINGS, stored in a dict
|
||||
>>> locals()
|
||||
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'float_number': 42.0, 'foo_func': <function foo_func at 0x1055847a0>}
|
||||
</code></pre>
|
||||
|
||||
<h2 id="python-functions">Python Functions</h2>
|
||||
<p>Since functions too are objects, we can see what all attributes a function contains as following</p>
|
||||
<pre><code class="python">>>> def hello(name):
|
||||
... print(f"Hello, {name}!")
|
||||
...
|
||||
>>> dir(hello)
|
||||
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__',
|
||||
'__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__',
|
||||
'__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__',
|
||||
'__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
|
||||
'__subclasshook__']
|
||||
</code></pre>
|
||||
|
||||
<p>While there are a lot of them, let's look at some interesting ones</p>
|
||||
<h4 id="globals"><strong>globals</strong></h4>
|
||||
<p>This attribute, as the name suggests, has references of global variables. If you ever need to know what all global variables are in the scope of this function, this will tell you. See how the function start seeing the new variable in globals</p>
|
||||
<pre><code class="python">>>> hello.__globals__
|
||||
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'hello': <function hello at 0x7fe4e82554c0>}
|
||||
|
||||
# adding new global variable
|
||||
>>> GLOBAL="g_val"
|
||||
>>> hello.__globals__
|
||||
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'hello': <function hello at 0x7fe4e82554c0>, 'GLOBAL': 'g_val'}
|
||||
</code></pre>
|
||||
|
||||
<h3 id="code"><strong>code</strong></h3>
|
||||
<p>This is an interesting one! As everything in python is an object, this includes the bytecode too. The compiled python bytecode is a python code object. Which is accessible via <code>__code__</code> attribute here. A function has an associated code object which carries some interesting information.</p>
|
||||
<pre><code class="python"># the file in which function is defined
|
||||
# stdin here since this is run in an interpreter
|
||||
>>> hello.__code__.co_filename
|
||||
'<stdin>'
|
||||
|
||||
# number of arguments the function takes
|
||||
>>> hello.__code__.co_argcount
|
||||
1
|
||||
|
||||
# local variable names
|
||||
>>> hello.__code__.co_varnames
|
||||
('name',)
|
||||
|
||||
# the function code's compiled bytecode
|
||||
>>> hello.__code__.co_code
|
||||
b't\x00d\x01|\x00\x9b\x00d\x02\x9d\x03\x83\x01\x01\x00d\x00S\x00'
|
||||
</code></pre>
|
||||
|
||||
<p>There are more code attributes which you can enlist by <code>>>> dir(hello.__code__)</code></p>
|
||||
<h2 id="decorators">Decorators</h2>
|
||||
<p>Related to functions, python has another feature called decorators. Let's see how that works, keeping <code>everything is an object</code> in mind.</p>
|
||||
<p>Here is a sample decorator:</p>
|
||||
<pre><code class="python">>>> def deco(func):
|
||||
... def inner():
|
||||
... print("before")
|
||||
... func()
|
||||
... print("after")
|
||||
... return inner
|
||||
...
|
||||
>>> @deco
|
||||
... def hello_world():
|
||||
... print("hello world")
|
||||
...
|
||||
>>>
|
||||
>>> hello_world()
|
||||
before
|
||||
hello world
|
||||
after
|
||||
</code></pre>
|
||||
|
||||
<p>Here <code>@deco</code> syntax is used to decorate the <code>hello_world</code> function. It is essentially same as doing</p>
|
||||
<pre><code class="python">>>> def hello_world():
|
||||
... print("hello world")
|
||||
...
|
||||
>>> hello_world = deco(hello_world)
|
||||
</code></pre>
|
||||
|
||||
<p>What goes inside the <code>deco</code> function might seem complex. Let's try to uncover it.</p>
|
||||
<ol>
|
||||
<li>Function <code>hello_world</code> is created</li>
|
||||
<li>It is passed to <code>deco</code> function</li>
|
||||
<li><code>deco</code> create a new function<ol>
|
||||
<li>This new function is calls <code>hello_world</code> function</li>
|
||||
<li>And does a couple other things</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><code>deco</code> returns the newly created function</li>
|
||||
<li><code>hello_world</code> is replaced with above function</li>
|
||||
</ol>
|
||||
<p>Let's visualize it for better understanding</p>
|
||||
<pre><code> BEFORE function_object (ID: 100)
|
||||
|
||||
"hello_world" +--------------------+
|
||||
+ |print("hello_world")|
|
||||
| | |
|
||||
+--------------> | |
|
||||
| |
|
||||
+--------------------+
|
||||
|
||||
|
||||
WHAT DECORATOR DOES
|
||||
|
||||
creates a new function (ID: 101)
|
||||
+---------------------------------+
|
||||
|input arg: function with id: 100 |
|
||||
| |
|
||||
|print("before") |
|
||||
|call function object with id 100 |
|
||||
|print("after") |
|
||||
| |
|
||||
+---------------------------^-----+
|
||||
|
|
||||
|
|
||||
AFTER |
|
||||
|
|
||||
|
|
||||
"hello_world" +-------------+
|
||||
</code></pre>
|
||||
|
||||
<p>Note how the <code>hello_world</code> name points to a new function object but that new function object knows the reference (ID) of the original function.</p>
|
||||
<h2 id="some-gotchas">Some Gotchas</h2>
|
||||
<ul>
|
||||
<li>While it is very quick to build prototypes in python and there are tons of libraries available, as the codebase complexity increases, type errors become more common and will get hard to deal with. (There are solutions to that problem like type annotations in python. Checkout <a href="http://mypy-lang.org/">mypy</a>.)</li>
|
||||
<li>Because python is dynamically typed language, that means all types are determined at runtime. And that makes python run very slow compared to other statically typed languages.</li>
|
||||
<li>Python has something called <a href="https://www.dabeaz.com/python/UnderstandingGIL.pdf">GIL</a> (global interpreter lock) which is a limiting factor for utilizing multiple CPI cores for parallel computation.</li>
|
||||
<li>Some weird things that python does: https://github.com/satwikkansal/wtfpython</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
|
||||
<footer class="col-md-12">
|
||||
<hr>
|
||||
<p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
|
||||
</footer>
|
||||
<script>
|
||||
var base_url = "../..",
|
||||
shortcuts = {"search": 83, "next": 78, "help": 191, "previous": 80};
|
||||
</script>
|
||||
<script src="../../js/base.js" defer></script>
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
<div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="Search Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Search</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
From here you can search these documents. Enter
|
||||
your search terms below.
|
||||
</p>
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="Keyboard Shortcuts Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Keyboard Shortcuts</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20%;">Keys</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="help shortcut"><kbd>?</kbd></td>
|
||||
<td>Open this help</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="next shortcut"><kbd>n</kbd></td>
|
||||
<td>Next page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="prev shortcut"><kbd>p</kbd></td>
|
||||
<td>Previous page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="search shortcut"><kbd>s</kbd></td>
|
||||
<td>Search</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
270
python_web/python-web-flask/index.html
Normal file
270
python_web/python-web-flask/index.html
Normal file
@@ -0,0 +1,270 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
||||
|
||||
<link rel="shortcut icon" href="../../img/favicon.ico">
|
||||
<title>Python, Web and Flask - school_of_sre</title>
|
||||
<link href="../../css/bootstrap-custom.min.css" rel="stylesheet">
|
||||
<link href="../../css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="../../css/base.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css">
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script src="../../js/jquery-1.10.2.min.js" defer></script>
|
||||
<script src="../../js/bootstrap-3.0.3.min.js" defer></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
|
||||
<!-- Collapsed navigation -->
|
||||
<div class="navbar-header">
|
||||
<!-- Expander button -->
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="../..">school_of_sre</a>
|
||||
</div>
|
||||
|
||||
<!-- Expanded navigation -->
|
||||
<div class="navbar-collapse collapse">
|
||||
<!-- Main navigation -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li >
|
||||
<a href="../..">Home</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Git <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../git/git-basics/">Git Basics</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/branches/">Working With Branches</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/github-hooks/">Github and Hooks</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown active">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Python and Web <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../intro/">Intro</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../python-concepts/">Some Python Concepts</a>
|
||||
</li>
|
||||
|
||||
<li class="active">
|
||||
<a href="./">Python, Web and Flask</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../url-shorten-app/">The URL Shortening App</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../sre-conclusion/">SRE Aspects of The App and Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Systems Design <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/intro/">Intro</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/scalability/">Scalability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/availability/">Availability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/fault-tolerance/">Fault Tolerance</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/conclusion/">Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<a href="#" data-toggle="modal" data-target="#mkdocs_search_modal">
|
||||
<i class="fa fa-search"></i> Search
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="next" href="../python-concepts/">
|
||||
<i class="fa fa-arrow-left"></i> Previous
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="prev" href="../url-shorten-app/">
|
||||
Next <i class="fa fa-arrow-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="col-md-3"><div class="bs-sidebar hidden-print affix well" role="complementary">
|
||||
<ul class="nav bs-sidenav">
|
||||
<li class="main active"><a href="#python-web-amd-flask">Python, Web amd Flask</a></li>
|
||||
<li><a href="#sockets">Sockets</a></li>
|
||||
<li><a href="#flask">Flask</a></li>
|
||||
</ul>
|
||||
</div></div>
|
||||
<div class="col-md-9" role="main">
|
||||
|
||||
<h1 id="python-web-amd-flask">Python, Web amd Flask</h1>
|
||||
<p>Back in the old days, websites were simple. They were simple static html contents. A webserver would be listening on a defined port and according to the HTTP request received, it would read files from disk and return them in response. But since then, complexity has evolved and websites are now dynamic. Depending on the request, multiple operations need to be performed like reading from database or calling other API and finally returning some response (HTML data, JSON content etc.)</p>
|
||||
<p>Since serving web requests is no longer a simple task like reading files from disk and return contents, we need to process each http request, perform some operations programmatically and construct a response.</p>
|
||||
<h2 id="sockets">Sockets</h2>
|
||||
<p>Though we have frameworks like flask, HTTP is still a protocol that works over TCP protocol. So let us setup a TCP server and send an HTTP request and inspect the request's payload. Note that this is not a tutorial on socket programming but what we are doing here is inspecting HTTP protocol at its ground level and look at what its contents look like. (Ref: <a href="https://realpython.com/python-sockets/">Socket Programming in Python (Guide) on RealPython</a>)</p>
|
||||
<pre><code class="python">import socket
|
||||
|
||||
HOST = '127.0.0.1' # Standard loopback interface address (localhost)
|
||||
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
|
||||
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||
s.bind((HOST, PORT))
|
||||
s.listen()
|
||||
conn, addr = s.accept()
|
||||
with conn:
|
||||
print('Connected by', addr)
|
||||
while True:
|
||||
data = conn.recv(1024)
|
||||
if not data:
|
||||
break
|
||||
print(data)
|
||||
</code></pre>
|
||||
|
||||
<p>Then we open <code>localhost:65432</code> in our web browser and following would be the output:</p>
|
||||
<pre><code class="bash">Connected by ('127.0.0.1', 54719)
|
||||
b'GET / HTTP/1.1\r\nHost: localhost:65432\r\nConnection: keep-alive\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 Edg/85.0.564.44\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nSec-Fetch-Site: none\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\nSec-Fetch-Dest: document\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: en-US,en;q=0.9\r\n\r\n'
|
||||
</code></pre>
|
||||
|
||||
<p>Examine closely and the content will look like the HTTP protocol's format. ie:</p>
|
||||
<pre><code>HTTP_METHOD URI_PATH HTTP_VERSION
|
||||
HEADERS_SEPARATED_BY_SEPARATOR
|
||||
</code></pre>
|
||||
|
||||
<p>So though it's a blob of bytes, knowing <a href="https://tools.ietf.org/html/rfc2616">http protocol specification</a>, you can parse that string (ie: split by <code>\r\n</code>) and get meaningful information out of it.</p>
|
||||
<h2 id="flask">Flask</h2>
|
||||
<p>Flask, and other such frameworks does pretty much what we just discussed in the last section (with added more sophistication). They listen on a port on a TCP socket, receive an HTTP request, parse the data according to protocol format and make it available to you in a convenient manner.</p>
|
||||
<p>ie: you can access headers in flask by <code>request.headers</code> which is made available to you by splitting above payload by <code>/r/n</code>, as defined in http protocol.</p>
|
||||
<p>Another example: we register routes in flask by <code>@app.route("/hello")</code>. What flask will do is maintain a registry internally which will map <code>/hello</code> with the function you decorated with. Now whenever a request comes with the <code>/hello</code> route (second component in the first line, split by space), flask calls the registered function and returns whatever the function returned.</p>
|
||||
<p>Same with all other web frameworks in other languages too. They all work on similar principles. What they basically do is understand the HTTP protocol, parses the HTTP request data and gives us programmers a nice interface to work with HTTP requests.</p>
|
||||
<p>Not so much of magic, innit?</p></div>
|
||||
</div>
|
||||
|
||||
<footer class="col-md-12">
|
||||
<hr>
|
||||
<p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
|
||||
</footer>
|
||||
<script>
|
||||
var base_url = "../..",
|
||||
shortcuts = {"search": 83, "next": 78, "help": 191, "previous": 80};
|
||||
</script>
|
||||
<script src="../../js/base.js" defer></script>
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
<div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="Search Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Search</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
From here you can search these documents. Enter
|
||||
your search terms below.
|
||||
</p>
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="Keyboard Shortcuts Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Keyboard Shortcuts</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20%;">Keys</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="help shortcut"><kbd>?</kbd></td>
|
||||
<td>Open this help</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="next shortcut"><kbd>n</kbd></td>
|
||||
<td>Next page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="prev shortcut"><kbd>p</kbd></td>
|
||||
<td>Previous page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="search shortcut"><kbd>s</kbd></td>
|
||||
<td>Search</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
263
python_web/sre-conclusion/index.html
Normal file
263
python_web/sre-conclusion/index.html
Normal file
@@ -0,0 +1,263 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
||||
|
||||
<link rel="shortcut icon" href="../../img/favicon.ico">
|
||||
<title>SRE Aspects of The App and Conclusion - school_of_sre</title>
|
||||
<link href="../../css/bootstrap-custom.min.css" rel="stylesheet">
|
||||
<link href="../../css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="../../css/base.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css">
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script src="../../js/jquery-1.10.2.min.js" defer></script>
|
||||
<script src="../../js/bootstrap-3.0.3.min.js" defer></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
|
||||
<!-- Collapsed navigation -->
|
||||
<div class="navbar-header">
|
||||
<!-- Expander button -->
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="../..">school_of_sre</a>
|
||||
</div>
|
||||
|
||||
<!-- Expanded navigation -->
|
||||
<div class="navbar-collapse collapse">
|
||||
<!-- Main navigation -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li >
|
||||
<a href="../..">Home</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Git <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../git/git-basics/">Git Basics</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/branches/">Working With Branches</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/github-hooks/">Github and Hooks</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown active">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Python and Web <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../intro/">Intro</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../python-concepts/">Some Python Concepts</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../python-web-flask/">Python, Web and Flask</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../url-shorten-app/">The URL Shortening App</a>
|
||||
</li>
|
||||
|
||||
<li class="active">
|
||||
<a href="./">SRE Aspects of The App and Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Systems Design <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/intro/">Intro</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/scalability/">Scalability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/availability/">Availability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/fault-tolerance/">Fault Tolerance</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/conclusion/">Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<a href="#" data-toggle="modal" data-target="#mkdocs_search_modal">
|
||||
<i class="fa fa-search"></i> Search
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="next" href="../url-shorten-app/">
|
||||
<i class="fa fa-arrow-left"></i> Previous
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="prev" href="../../systems_design/intro/">
|
||||
Next <i class="fa fa-arrow-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="col-md-3"><div class="bs-sidebar hidden-print affix well" role="complementary">
|
||||
<ul class="nav bs-sidenav">
|
||||
<li class="main active"><a href="#sre-parts-of-the-app-and-conclusion">SRE Parts of The App and Conclusion</a></li>
|
||||
<li><a href="#scaling-the-app">Scaling The App</a></li>
|
||||
<li><a href="#monitoring-strategy">Monitoring Strategy</a></li>
|
||||
<li><a href="#sre-use-cases">SRE Use-cases</a></li>
|
||||
<li><a href="#optional-exercises">Optional Exercises</a></li>
|
||||
<li><a href="#conclusion">Conclusion</a></li>
|
||||
</ul>
|
||||
</div></div>
|
||||
<div class="col-md-9" role="main">
|
||||
|
||||
<h1 id="sre-parts-of-the-app-and-conclusion">SRE Parts of The App and Conclusion</h1>
|
||||
<h2 id="scaling-the-app">Scaling The App</h2>
|
||||
<p>The design and development is just a part of the journey. We will need to setup continuous integration and continuous delivery pipelines sooner or later. And we have to deploy this app somewhere.</p>
|
||||
<p>Initially we can start with deploying this app on one virtual machine on any cloud provider. But this is a <code>Single point of failure</code> which is something we never allow as an SRE (or even as an engineer). So an improvement here can be having multiple instances of applications deployed behind a load balancer. This certainly prevents problems of one machine going down.</p>
|
||||
<p>Scaling here would mean adding more instances behind the load balancer. But this is scalable upto only a certain point. After that, other bottlenecks in the system will start appearing. ie: DB will become the bottleneck, or perhaps the load balancer itself. How do you know what is the bottleneck? You need to have observability into each aspects of the application architecture.</p>
|
||||
<p>Only after you have metrics, you will be able to know what is going wrong where. <strong>What gets measured, gets fixed!</strong></p>
|
||||
<p>Get deeper insights into scaling from School Of SRE's Scalability module and post going through it, apply your learnings and takeaways to this app. Think how will we make this app geographically distributed and highly available and scalable.</p>
|
||||
<h2 id="monitoring-strategy">Monitoring Strategy</h2>
|
||||
<p>Once we have our application deployed. It will be working ok. But not forever. Reliability is in the title of our job and we make systems reliable by making the design in a certain way. But things still will go down. Machines will fail. Disks will behave weirdly. Buggy code will get pushed to production. And all these possible scenarios will make the system less reliable. So what do we do? <strong>We monitor!</strong></p>
|
||||
<p>We keep an eye on the system's health and if anything is not going as expected, we want ourselves to get alerted.</p>
|
||||
<p>Now let's think in terms of the given url shortening app. We need to monitor it. And we would want to get notified in case something goes wrong. But we first need to decide what is that <em>something</em> that we want to keep an eye on.</p>
|
||||
<ol>
|
||||
<li>Since it's a web app serving HTTP requests, we want to keep an eye on HTTP Status codes and latencies</li>
|
||||
<li>Request volume again is a good candidate, if the app is receiving an unusual amount of traffic, something might be off.</li>
|
||||
<li>We also want to keep an eye on the database so depending on the database solution chosen. Query times, volumes, disk usage etc.</li>
|
||||
<li>Finally, there also needs to be some external monitoring which runs periodic tests from devices outside of your data centers. This emulates customers and ensures that from customer point of view, the system is working as expected.</li>
|
||||
</ol>
|
||||
<h2 id="sre-use-cases">SRE Use-cases</h2>
|
||||
<p>In the world of SRE, python is a widely used language. For small scripts and tooling developed for various purposes. Since tooling developed by SRE works with critical pieces of infrastructure and has great power (to bring things down), it is important to know what you are doing while using a programming language and its features. Also it is equally important to know the language and its characteristics while debugging the issues. As an SRE having a deeper understanding of python language, it has helped me a lot to debug very sneaky bugs and be generally more aware and informed while making certain design decisions.</p>
|
||||
<p>While developing tools may or may not be part of SRE job, supporting tools or services is more likely to be a daily duty. Building an application or tool is just a small part of productionization. While there is certainly that goes in the design of the application itself to make it more robust, as an SRE you are responsible for its reliability and stability once it is deployed and running. And to ensure that, you’d need to understand the application first and then come up with a strategy to monitor it properly and be prepared for various failure scenarios.</p>
|
||||
<h2 id="optional-exercises">Optional Exercises</h2>
|
||||
<ol>
|
||||
<li>Make a decorator that will cache function return values depending on input parameters.</li>
|
||||
<li>Host the URL shortening app on any cloud provider.</li>
|
||||
<li>Setup monitoring using many of the tools available like catchpoint, datadog etc.</li>
|
||||
<li>Create a minimal flask-like framework on top of TCP sockets.</li>
|
||||
</ol>
|
||||
<h2 id="conclusion">Conclusion</h2>
|
||||
<p>This module, in the first part, aims to make you more aware of the things that will happen when you choose python as your programming language and what happens when you run a python program. With the knowledge of how python handles things internally as objects, lot of seemingly magic things in python will start to make more sense.</p>
|
||||
<p>The second part will first explain how a framework like flask works using the existing knowledge of protocols like TCP and HTTP. It then touches the whole lifecycle of an application development lifecycle including the SRE parts of it. While the design and areas in architecture considered will not be exhaustive, it will give a good overview of things that are also important being an SRE and why they are important.</p></div>
|
||||
</div>
|
||||
|
||||
<footer class="col-md-12">
|
||||
<hr>
|
||||
<p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
|
||||
</footer>
|
||||
<script>
|
||||
var base_url = "../..",
|
||||
shortcuts = {"search": 83, "next": 78, "help": 191, "previous": 80};
|
||||
</script>
|
||||
<script src="../../js/base.js" defer></script>
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
<div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="Search Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Search</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
From here you can search these documents. Enter
|
||||
your search terms below.
|
||||
</p>
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="Keyboard Shortcuts Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Keyboard Shortcuts</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20%;">Keys</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="help shortcut"><kbd>?</kbd></td>
|
||||
<td>Open this help</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="next shortcut"><kbd>n</kbd></td>
|
||||
<td>Next page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="prev shortcut"><kbd>p</kbd></td>
|
||||
<td>Previous page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="search shortcut"><kbd>s</kbd></td>
|
||||
<td>Search</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
332
python_web/url-shorten-app/index.html
Normal file
332
python_web/url-shorten-app/index.html
Normal file
@@ -0,0 +1,332 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
||||
|
||||
<link rel="shortcut icon" href="../../img/favicon.ico">
|
||||
<title>The URL Shortening App - school_of_sre</title>
|
||||
<link href="../../css/bootstrap-custom.min.css" rel="stylesheet">
|
||||
<link href="../../css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="../../css/base.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css">
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script src="../../js/jquery-1.10.2.min.js" defer></script>
|
||||
<script src="../../js/bootstrap-3.0.3.min.js" defer></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
|
||||
<!-- Collapsed navigation -->
|
||||
<div class="navbar-header">
|
||||
<!-- Expander button -->
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="../..">school_of_sre</a>
|
||||
</div>
|
||||
|
||||
<!-- Expanded navigation -->
|
||||
<div class="navbar-collapse collapse">
|
||||
<!-- Main navigation -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li >
|
||||
<a href="../..">Home</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Git <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../git/git-basics/">Git Basics</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/branches/">Working With Branches</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../git/github-hooks/">Github and Hooks</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown active">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Python and Web <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../intro/">Intro</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../python-concepts/">Some Python Concepts</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../python-web-flask/">Python, Web and Flask</a>
|
||||
</li>
|
||||
|
||||
<li class="active">
|
||||
<a href="./">The URL Shortening App</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../sre-conclusion/">SRE Aspects of The App and Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Systems Design <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/intro/">Intro</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/scalability/">Scalability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/availability/">Availability</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/fault-tolerance/">Fault Tolerance</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../systems_design/conclusion/">Conclusion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<a href="#" data-toggle="modal" data-target="#mkdocs_search_modal">
|
||||
<i class="fa fa-search"></i> Search
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="next" href="../python-web-flask/">
|
||||
<i class="fa fa-arrow-left"></i> Previous
|
||||
</a>
|
||||
</li>
|
||||
<li >
|
||||
<a rel="prev" href="../sre-conclusion/">
|
||||
Next <i class="fa fa-arrow-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="col-md-3"><div class="bs-sidebar hidden-print affix well" role="complementary">
|
||||
<ul class="nav bs-sidenav">
|
||||
<li class="main active"><a href="#the-url-shortening-app">The URL Shortening App</a></li>
|
||||
<li><a href="#design">Design</a></li>
|
||||
</ul>
|
||||
</div></div>
|
||||
<div class="col-md-9" role="main">
|
||||
|
||||
<h1 id="the-url-shortening-app">The URL Shortening App</h1>
|
||||
<p>Let's build a very simple URL shortening app using flask and try to incorporate all aspects of the development process including the reliability aspects. We will not be building the UI and we will come up with a minimal set of API that will be enough for the app to function well.</p>
|
||||
<h2 id="design">Design</h2>
|
||||
<p>We don't jump directly to coding. First thing we do is gather requirements. Come up with an approach. Have the approach/design reviewed by peers. Evolve, iterate, document the decisions and tradeoffs. And then finally implement. While we will not do the full blown design document here, we will raise certain questions here that are important to the design.</p>
|
||||
<h3 id="1-high-level-operations-and-api-endpoints">1. High Level Operations and API Endpoints</h3>
|
||||
<p>Since it's a URL shortening app, we will need an API for generating the shorten link given an original link. And an API/Endpoint which will accept the shorten link and redirect to original URL. We are not including the user aspect of the app to keep things minimal. These two API should make app functional and usable by anyone.</p>
|
||||
<h3 id="2-how-to-shorten">2. How to shorten?</h3>
|
||||
<p>Given a url, we will need to generate a shortened version of it. One approach could be using random characters for each link. Another thing that can be done is to use some sort of hashing algorithm. The benefit here is we will reuse the same hash for the same link. ie: if lot of people are shortening <code>https://www.linkedin.com</code> they all will have the same value, compared to multiple entries in DB if chosen random characters.</p>
|
||||
<p>What about hash collisions? Even in random characters approach, though there is a less probability, hash collisions can happen. And we need to be mindful of them. In that case we might want to prepend/append the string with some random value to avoid conflict.</p>
|
||||
<p>Also, choice of hash algorithm matters. We will need to analyze algorithms. Their CPU requirements and their characteristics. Choose one that suits the most.</p>
|
||||
<h3 id="3-is-url-valid">3. Is URL Valid?</h3>
|
||||
<p>Given a URL to shorten, how do we verify if the URL is valid? Do we even verify or validate? One basic check that can be done is see if the URL matches a regex of a URL. To go even further we can try opening/visiting the URL. But there are certain gotchas here.</p>
|
||||
<ol>
|
||||
<li>We need to define success criteria. ie: HTTP 200 means it is valid.</li>
|
||||
<li>What is the URL is in private network?</li>
|
||||
<li>What if URL is temporarily down?</li>
|
||||
</ol>
|
||||
<h3 id="4-storage">4. Storage</h3>
|
||||
<p>Finally, storage. Where will we store the data that we will generate over time? There are multiple database solutions available and we will need to choose the one that suits this app the most. Relational database like MySQL would be a fair choice but <strong>be sure to checkout School of SRE's database section for deeper insights into making a more informed decision.</strong></p>
|
||||
<h3 id="5-other">5. Other</h3>
|
||||
<p>We are not accounting for users into our app and other possible features like rate limiting, customized links etc but it will eventually come up with time. Depending on the requirements, they too might need to get incorporated.</p>
|
||||
<p>The minimal working code is given below for reference but I'd encourage you to come up with your own.</p>
|
||||
<pre><code class="python">from flask import Flask, redirect, request
|
||||
|
||||
from hashlib import md5
|
||||
|
||||
app = Flask("url_shortener")
|
||||
|
||||
mapping = {}
|
||||
|
||||
@app.route("/shorten", methods=["POST"])
|
||||
def shorten():
|
||||
global mapping
|
||||
payload = request.json
|
||||
|
||||
if "url" not in payload:
|
||||
return "Missing URL Parameter", 400
|
||||
|
||||
# TODO: check if URL is valid
|
||||
|
||||
hash_ = md5()
|
||||
hash_.update(payload["url"].encode())
|
||||
digest = hash_.hexdigest()[:5] # limiting to 5 chars. Less the limit more the chances of collission
|
||||
|
||||
if digest not in mapping:
|
||||
mapping[digest] = payload["url"]
|
||||
return f"Shortened: r/{digest}\n"
|
||||
else:
|
||||
# TODO: check for hash collission
|
||||
return f"Already exists: r/{digest}\n"
|
||||
|
||||
|
||||
@app.route("/r/<hash_>")
|
||||
def redirect_(hash_):
|
||||
if hash_ not in mapping:
|
||||
return "URL Not Found", 404
|
||||
return redirect(mapping[hash_])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
||||
|
||||
"""
|
||||
OUTPUT:
|
||||
|
||||
|
||||
===> SHORTENING
|
||||
|
||||
spatel1-mn1:tmp spatel1$ curl localhost:5000/shorten -H "content-type: application/json" --data '{"url":"https://linkedin.com"}'
|
||||
Shortened: r/a62a4
|
||||
|
||||
|
||||
===> REDIRECTING, notice the response code 302 and the location header
|
||||
|
||||
spatel1-mn1:tmp spatel1$ curl localhost:5000/r/a62a4 -v
|
||||
* Uses proxy env variable NO_PROXY == '127.0.0.1'
|
||||
* Trying ::1...
|
||||
* TCP_NODELAY set
|
||||
* Connection failed
|
||||
* connect to ::1 port 5000 failed: Connection refused
|
||||
* Trying 127.0.0.1...
|
||||
* TCP_NODELAY set
|
||||
* Connected to localhost (127.0.0.1) port 5000 (#0)
|
||||
> GET /r/a62a4 HTTP/1.1
|
||||
> Host: localhost:5000
|
||||
> User-Agent: curl/7.64.1
|
||||
> Accept: */*
|
||||
>
|
||||
* HTTP 1.0, assume close after body
|
||||
< HTTP/1.0 302 FOUND
|
||||
< Content-Type: text/html; charset=utf-8
|
||||
< Content-Length: 247
|
||||
< Location: https://linkedin.com
|
||||
< Server: Werkzeug/0.15.4 Python/3.7.7
|
||||
< Date: Tue, 27 Oct 2020 09:37:12 GMT
|
||||
<
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<title>Redirecting...</title>
|
||||
<h1>Redirecting...</h1>
|
||||
* Closing connection 0
|
||||
<p>You should be redirected automatically to target URL: <a href="https://linkedin.com">https://linkedin.com</a>. If not click the link.
|
||||
"""
|
||||
</code></pre></div>
|
||||
</div>
|
||||
|
||||
<footer class="col-md-12">
|
||||
<hr>
|
||||
<p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
|
||||
</footer>
|
||||
<script>
|
||||
var base_url = "../..",
|
||||
shortcuts = {"search": 83, "next": 78, "help": 191, "previous": 80};
|
||||
</script>
|
||||
<script src="../../js/base.js" defer></script>
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
<div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="Search Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Search</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
From here you can search these documents. Enter
|
||||
your search terms below.
|
||||
</p>
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="Keyboard Shortcuts Modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="exampleModalLabel">Keyboard Shortcuts</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20%;">Keys</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="help shortcut"><kbd>?</kbd></td>
|
||||
<td>Open this help</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="next shortcut"><kbd>n</kbd></td>
|
||||
<td>Next page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="prev shortcut"><kbd>p</kbd></td>
|
||||
<td>Previous page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="search shortcut"><kbd>s</kbd></td>
|
||||
<td>Search</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user