<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nicolas Mesa</title>
    <description>The latest articles on DEV Community by Nicolas Mesa (@nicolasmesa).</description>
    <link>https://dev.to/nicolasmesa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F107712%2F335e5bc1-2368-489b-9445-4bacc744c1fa.png</url>
      <title>DEV Community: Nicolas Mesa</title>
      <link>https://dev.to/nicolasmesa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nicolasmesa"/>
    <language>en</language>
    <item>
      <title>Booting Your Own Kernel on Raspberry Pi via Uart</title>
      <dc:creator>Nicolas Mesa</dc:creator>
      <pubDate>Wed, 21 Aug 2019 02:13:02 +0000</pubDate>
      <link>https://dev.to/nicolasmesa/booting-your-own-kernel-on-raspberry-pi-via-uart-565f</link>
      <guid>https://dev.to/nicolasmesa/booting-your-own-kernel-on-raspberry-pi-via-uart-565f</guid>
      <description>&lt;p&gt;Cross-posted from my personal blog &lt;a href="https://blog.nicolasmesa.co"&gt;https://blog.nicolasmesa.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the last few weeks, I’ve been reading a great &lt;a href="https://github.com/s-matyukevich/raspberry-pi-os/"&gt;book&lt;/a&gt; about building your own operating system for a Raspberry Pi from scratch. It has been a great experience, and I’ve learned a lot. One thing I didn’t like was my development workflow, which looked like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make a code change.&lt;/li&gt;
&lt;li&gt;Build the change.&lt;/li&gt;
&lt;li&gt;Unplug the Raspberry Pi.&lt;/li&gt;
&lt;li&gt;Remove the SD card.&lt;/li&gt;
&lt;li&gt;Plug the SD card to my laptop.&lt;/li&gt;
&lt;li&gt;Copy the newly built kernel over to the SD card.&lt;/li&gt;
&lt;li&gt;Eject the SD card.&lt;/li&gt;
&lt;li&gt;Place the SD card back on the Raspberry Pi.&lt;/li&gt;
&lt;li&gt;Connect the Raspberry Pi to my computer.&lt;/li&gt;
&lt;li&gt;Close previous terminal since the &lt;code&gt;screen&lt;/code&gt; command made it pretty useless.&lt;/li&gt;
&lt;li&gt;Connect to the Raspberry Pi using the &lt;code&gt;screen&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Test my change.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of this was pretty time consuming making the feedback loop very slow (especially, when I forgot a crucial step such as placing the SD card back in the Raspberry Pi). I searched to see if there was a way to improve my workflow and found an issue in the github repo called &lt;a href="https://github.com/s-matyukevich/raspberry-pi-os/issues/115"&gt;UART boot&lt;/a&gt;. I read through it and decided to build the UART boot myself as a learning exercise. In this blog post, I go through the process that I took to make UART boot work, including my wrong assumptions/failures and how I overcame them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;To make this project worth my time, I decided that it needed to be able to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The kernel must act as both the UART bootloader and the kernel itself (a single executable).&lt;/li&gt;
&lt;li&gt;I must be able to send a newly compiled kernel over UART, and the Raspberry Pi must boot.&lt;/li&gt;
&lt;li&gt;I must be able to have an interactive session over UART using my program (basically, replace &lt;code&gt;screen&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;screen&lt;/code&gt; replacement must leave my terminal in a working state (I assume there’s a way to make this work in &lt;code&gt;screen&lt;/code&gt; but, I wanted to do this as a learning exercise).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;If you want to follow along, you’ll need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To meet all the &lt;a href="https://github.com/s-matyukevich/raspberry-pi-os/blob/master/docs/Prerequisites.md"&gt;prerequisites from the book&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;To have completed the &lt;a href="https://github.com/s-matyukevich/raspberry-pi-os/blob/master/docs/lesson01/rpi-os.md"&gt;first lesson&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;To have completed the &lt;a href="https://github.com/s-matyukevich/raspberry-pi-os/blob/master/docs/lesson01/exercises.md"&gt;second exercise&lt;/a&gt; to use UART instead of Mini UART (this might still work with Mini UART, but I haven’t tried).&lt;/li&gt;
&lt;li&gt;Python 3.7 (This is the version I used).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; If you haven’t completed the exercise and would still like to follow along, follow the setup instructions below. I also tagged each commit to make it easier to follow along/jump ahead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;If you already have your project, make sure that you’ve built your kernel and have it in the SD card. Otherwise, you can clone my &lt;a href="https://github.com/nicolasmesa/PiOS"&gt;repository&lt;/a&gt; and can follow along:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git clone https://github.com/nicolasmesa/PiOS
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git checkout tags/uart-boot-initial
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Git tags
&lt;/h4&gt;

&lt;p&gt;I’ve created commit tags for each section in case you want to experiment with a specific part of the project. You can checkout the tags by running the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git checkout tags/&amp;lt;tag-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I’ll reference the tag name at the end of each section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git tag:&lt;/strong&gt; &lt;code&gt;uart-boot-initial&lt;/code&gt; - &lt;a href="https://github.com/nicolasmesa/PiOS/tree/uart-boot-initial"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;screen&lt;/code&gt; replacement
&lt;/h2&gt;

&lt;p&gt;To be able to send the kernel over UART, we need to establish a serial connection with the Raspberry Pi and send the kernel bytes. The &lt;code&gt;screen&lt;/code&gt; replacement will do the same thing with the difference that it will also read from the serial connection and &lt;code&gt;stdin&lt;/code&gt; and will write to &lt;code&gt;stdout&lt;/code&gt;. If we’re able to make this work, sending the kernel should be easy.&lt;/p&gt;

&lt;p&gt;Let’s get started by installing &lt;code&gt;pyserial&lt;/code&gt; (I suggest you do this in a &lt;a href="https://docs.python-guide.org/dev/virtualenvs/"&gt;virtual environment&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;&lt;span class="nv"&gt;pyserial&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;3.4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s create a file called &lt;code&gt;boot_send.py&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;select&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;serial&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tty&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UartConnection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baud_rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baud_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ascii"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes_to_send&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes_to_send&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_len&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in_waiting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_buffer_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_decode_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_buffer&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start_interactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setcbreak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fileno&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rfd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_file&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rfd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_buffer_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;input_file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rfd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Got keyboard interrupt. Terminating..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;OSError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Got OSError. Terminating..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"stty sane"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_decode_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes_to_decode&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;bytes_to_decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ascii"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wow, that’s a lot of code! Let’s go through it.&lt;/p&gt;

&lt;h5&gt;
  
  
  Constructor
&lt;/h5&gt;

&lt;p&gt;The constructor (&lt;code&gt;__init__&lt;/code&gt;) receives two arguments which we use to create a serial connection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;file_path&lt;/code&gt;: The path to the file where the UART device is (&lt;code&gt;/dev/cu.SLAB_USBtoUART&lt;/code&gt; in my computer).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;baud_rate&lt;/code&gt;: The baud rate to use in the serial connection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Utility methods
&lt;/h5&gt;

&lt;p&gt;We have a bunch of utility methods with varying levels of abstraction, but they all end up calling either &lt;code&gt;send_bytes&lt;/code&gt; (which calls &lt;code&gt;serial.write&lt;/code&gt;) or &lt;code&gt;read&lt;/code&gt; (which calls &lt;code&gt;serial.read&lt;/code&gt;).&lt;/p&gt;

&lt;h5&gt;
  
  
  start_interactive
&lt;/h5&gt;

&lt;p&gt;The &lt;code&gt;start_interactive&lt;/code&gt; method receives two arguments (&lt;code&gt;input_file&lt;/code&gt; and &lt;code&gt;output_file&lt;/code&gt;). We will use these arguments as &lt;code&gt;stdin&lt;/code&gt; and &lt;code&gt;stdout&lt;/code&gt;, respectively. The first thing this method does is call &lt;code&gt;tty.setcbreak(input_file.fileno())&lt;/code&gt; on the &lt;code&gt;stdin&lt;/code&gt; file. &lt;code&gt;tty.setcbreak&lt;/code&gt; turns &lt;a href="https://www.oreilly.com/library/view/python-standard-library/0596000960/ch12s08.html"&gt;the &lt;code&gt;tty&lt;/code&gt; into “raw” mode&lt;/a&gt; and allows us to read the characters as they are typed instead of buffering them until the user presses enter.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;select&lt;/code&gt; function receives a set of file descriptors to monitor. When called, it blocks until one of those files has data that we can read. When the &lt;code&gt;select&lt;/code&gt; function returns, the &lt;code&gt;rfd&lt;/code&gt; variable has a list of file descriptors that have data available. Next, we verify if the &lt;code&gt;serial&lt;/code&gt; file descriptor has data available, and, if it does, we read it all and send the output to our terminal (&lt;code&gt;output_file&lt;/code&gt;). We also check if our &lt;code&gt;input_file&lt;/code&gt; has data, and, if it does, we send it over the serial connection to the Raspberry Pi. Note that in this case, we don’t write anything to the &lt;code&gt;output_file&lt;/code&gt; and we rely on the Raspberry Pi echoing back the character that we sent.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;os.system("stty sane")&lt;/code&gt; call makes our tty not be in raw mode anymore. This function allows us to keep using the same terminal (instead of the problem I had with &lt;code&gt;screen&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
    &lt;span class="n"&gt;uart_connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UartConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c1"&gt;# Change these to match your setup
&lt;/span&gt;        &lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'/dev/cu.SLAB_USBtoUART'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;baud_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;115200&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_interactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;' __main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, let’s execute the script. Assuming everything worked, you should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python boot_send.py
&lt;span class="go"&gt;Hello world!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should be able to type anything you want, and the Raspberry Pi should echo it back. Press &lt;code&gt;ctrl-c&lt;/code&gt; to exit, and your terminal should still work normally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you’re using the git branch I provided, you’ll need to hit &lt;code&gt;enter&lt;/code&gt; to see the “Hello world!” message. I did this to make sure that the kernel only sends the &lt;code&gt;Hello world!&lt;/code&gt; message after &lt;code&gt;boot_send&lt;/code&gt; has connected successfully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git tag:&lt;/strong&gt; &lt;code&gt;uart-boot-screen-replacement&lt;/code&gt; - &lt;a href="https://github.com/nicolasmesa/PiOS/tree/uart-boot-screen-replacement"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending the kernel over UART
&lt;/h2&gt;

&lt;p&gt;Sending the kernel should be no different than sending characters over serial; everything gets translated to bytes, after all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protocol
&lt;/h3&gt;

&lt;p&gt;We’ll use the following protocol to send the kernel:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Raspberry Pi boots into the kernel and blocks while waiting to read a single line.&lt;/li&gt;
&lt;li&gt;If the line it reads matches the word &lt;code&gt;kernel&lt;/code&gt; then we go into UART booting mode, if not, we skip the UART boot.&lt;/li&gt;
&lt;li&gt;When in UART booting mode, the &lt;code&gt;boot_send&lt;/code&gt; script sends an integer (4 bytes) containing the size of the kernel that we’re about to send.&lt;/li&gt;
&lt;li&gt;The Raspberry Pi takes note of this size and sends it back.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;boot_send&lt;/code&gt; script verifies that the Raspberry Pi got the correct number.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;boot_send&lt;/code&gt; script starts reading the kernel and sends it byte by byte over the serial connection.&lt;/li&gt;
&lt;li&gt;The Raspberry Pi receives each byte and…

&lt;ol&gt;
&lt;li&gt;Keeps a running sum of all the bytes (a checksum).&lt;/li&gt;
&lt;li&gt;Places that byte in memory (overwriting the current kernel).&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;When the Raspberry Pi receives the number of bytes equal to the size of the kernel (sent in a previous step), it sends the checksum over UART.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;boot_send&lt;/code&gt; script verifies that the checksums match (for error detection purposes).&lt;/li&gt;
&lt;li&gt;The Raspberry Pi responds with the string &lt;code&gt;"Done"&lt;/code&gt; to denote that it will now jump to the new kernel.&lt;/li&gt;
&lt;li&gt;The Raspberry Pi jumps back to address &lt;code&gt;0x00&lt;/code&gt; to start executing in the new kernel.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;boot_send&lt;/code&gt; script starts an interactive session.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One thing that we need to keep in mind is &lt;a href="https://en.wikipedia.org/wiki/Endianness"&gt;endianness&lt;/a&gt; when sending the size. I decided to use big-endian for all communication.&lt;/p&gt;

&lt;h3&gt;
  
  
  boot_send modifications
&lt;/h3&gt;

&lt;p&gt;We need to add some functionality to our &lt;code&gt;boot_send&lt;/code&gt; script to implement the protocol:&lt;/p&gt;

&lt;h5&gt;
  
  
  UartConnection
&lt;/h5&gt;

&lt;p&gt;Let’s add these functions to our &lt;code&gt;UartConnection&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UartConnection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s"&gt;'Number can only be 4 bytes long'&lt;/span&gt;
        &lt;span class="n"&gt;number_in_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byteorder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'big'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number_in_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;bytes_to_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
        &lt;span class="n"&gt;number_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes_to_read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number_bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byteorder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'big'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_decode_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The most important thing to call out here is the &lt;code&gt;byteorder&lt;/code&gt; which we decided to use (&lt;code&gt;big&lt;/code&gt; stands for &lt;code&gt;big-endian&lt;/code&gt;).&lt;/p&gt;

&lt;h5&gt;
  
  
  Kernel checksum
&lt;/h5&gt;

&lt;p&gt;We compute a checksum to validate against some errors. I don’t think this is the best way to check for errors since something as simple as changing the order of two bytes would still make this checksum pass. I use it because it gives me a bit more confidence that things are working as expected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_kernel_checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kernel_bytes&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kernel_bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We wrap around at &lt;code&gt;2^32&lt;/code&gt; because that’s the max size of an integer.&lt;/p&gt;

&lt;h5&gt;
  
  
  send_kernel
&lt;/h5&gt;

&lt;p&gt;Let’s add a function to send the kernel to the Raspberry Pi following our protocol:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_kernel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"kernel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;kernel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;checksum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_kernel_checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sending kernel with size"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"and checksum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;size_confirmation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_int&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;size_confirmation&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Expected size to be"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"but got"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size_confirmation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Kernel size confirmed. Sending kernel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Validating checksum..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;checksum_confirmation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_int&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;checksum_confirmation&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Expected checksum to be"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s"&gt;"but was"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checksum_confirmation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

        &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_line&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Done"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Didn't get confirmation for the kernel. Got"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our function receives a &lt;code&gt;path&lt;/code&gt; to the kernel file and a &lt;code&gt;UartConnection&lt;/code&gt; object. We use these to follow the protocol described above to send the kernel to the Raspberry Pi.&lt;/p&gt;

&lt;h5&gt;
  
  
  Calling the &lt;code&gt;send_kernel&lt;/code&gt; function
&lt;/h5&gt;

&lt;p&gt;Let’s make a small tweak to our &lt;code&gt;main&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;    &lt;span class="n"&gt;uart_connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UartConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;send_kernel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"kernel8.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;uart_connection&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Done!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;uart_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_interactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error sending kernel :("&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our script sends the kernel first and then starts an interactive session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git tag:&lt;/strong&gt; &lt;code&gt;uart-boot-boot-send-client-side&lt;/code&gt; - &lt;a href="https://github.com/nicolasmesa/PiOS/tree/uart-boot-boot-send-client-side"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Kernel side modifications
&lt;/h3&gt;

&lt;p&gt;Let’s dive into the modifications needed for the kernel.&lt;/p&gt;

&lt;h5&gt;
  
  
  branch_to_address
&lt;/h5&gt;

&lt;p&gt;The last part of our boot protocol involves jumping back to address &lt;code&gt;0x00&lt;/code&gt; and starting the execution from that memory location. Let’s start by adding a function that can do that.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;utils.h&lt;/code&gt; file and add the function declaration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;branch_to_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, go to the &lt;code&gt;utils.S&lt;/code&gt; file and add the definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight armasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;global&lt;/span&gt; &lt;span class="nf"&gt;branch_to_address&lt;/span&gt;
&lt;span class="nl"&gt;branch_to_address&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;br&lt;/span&gt; &lt;span class="nv"&gt;x0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  uart_send_int / uart_read_int
&lt;/h5&gt;

&lt;p&gt;We’ll need to send and read integers via UART (for the kernel size and the checksum). Let’s open the &lt;code&gt;uart.h&lt;/code&gt; file and add the following declarations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;uart_send_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;uart_read_int&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s implement the functions in the &lt;code&gt;uart.c&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;uart_read_int&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uart_recv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;uart_send_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;uart_send&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)((&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;uart_send&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)((&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;uart_send&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)((&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;uart_send&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;uart_read_int&lt;/code&gt;, we read one byte at a time (most significant byte first) and keep shifting those bytes to the left until we get the 4 bytes that represent the integer. In the &lt;code&gt;uart_send_int&lt;/code&gt;, we send one byte at a time (most significant byte first). Note that using pointers here is not a good idea since we shouldn’t make assumptions on how the Raspberry Pi stores &lt;code&gt;int&lt;/code&gt;s in memory (&lt;a href="https://en.wikipedia.org/wiki/Endianness"&gt;big-endian vs. little-endian&lt;/a&gt;).&lt;/p&gt;

&lt;h5&gt;
  
  
  include utils.h
&lt;/h5&gt;

&lt;p&gt;Open the &lt;code&gt;kernel.c&lt;/code&gt; file and add the following &lt;code&gt;#include&lt;/code&gt; statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include "utils.h"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  readline
&lt;/h5&gt;

&lt;p&gt;Here we write a pretty simple &lt;code&gt;readline&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxlen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;maxlen&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uart_recv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  strcmp
&lt;/h5&gt;

&lt;p&gt;Our protocol needs to read a line of text and compare it against the word &lt;code&gt;kernel&lt;/code&gt;. To do that, we need a string comparison function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;str1&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;str2&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  copy_and_jump_to_kernel
&lt;/h5&gt;

&lt;p&gt;Now we have all the pieces to implement the protocol we brought up before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;copy_and_jump_to_kernel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;kernel_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uart_read_int&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;uart_send_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kernel_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;checksum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;kernel_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uart_recv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;checksum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;uart_send_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;uart_send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Done copying kernel&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;branch_to_address&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function receives the kernel size and sends it back. Then, receives each byte from the new kernel and places it in memory starting on address &lt;code&gt;0x00&lt;/code&gt;. Next, it sends the calculated checksum and a string saying &lt;code&gt;"Done copying the kernel"&lt;/code&gt;. Finally, it branches to start executing at address &lt;code&gt;0x00&lt;/code&gt; (where the new kernel resides).&lt;/p&gt;

&lt;h5&gt;
  
  
  kernel_main
&lt;/h5&gt;

&lt;p&gt;Let’s add the logic to read a line on boot, and compare it against &lt;code&gt;kernel&lt;/code&gt; to decide if we want to boot over UART or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;kernel_main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;buff_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;uart_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;buff_size&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buff_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"kernel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;copy_and_jump_to_kernel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;uart_send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;uart_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uart_recv&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that the call to &lt;code&gt;copy_and_jump_to_kernel&lt;/code&gt; never returns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git tag:&lt;/strong&gt; &lt;code&gt;uart-boot-boot-send-kernel-side&lt;/code&gt; - &lt;a href="https://github.com/nicolasmesa/PiOS/tree/uart-boot-boot-send-kernel-side"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing our UART boot
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Build the kernel and copy it to the SD card
&lt;/h4&gt;

&lt;p&gt;Here are the steps I took to build the kernel and copy it to the SD card on my Mac:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./build.sh
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;kernel8.img /Volumes/boot/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Booting test: sending the same kernel
&lt;/h4&gt;

&lt;p&gt;Now eject the SD card and put in your Raspberry Pi.&lt;/p&gt;

&lt;p&gt;Let’s run our &lt;code&gt;boot_send&lt;/code&gt; script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python boot_send.py 
&lt;span class="go"&gt;Sending kernel with size 1991 and checksum 201267
Kernel size confirmed. Sending kernel
Validating checksum...
Done!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you see this, it means that you just sent a new kernel (the same kernel that you installed in the SD card) over UART! At this point, the &lt;code&gt;kernel&lt;/code&gt; is stuck in the &lt;code&gt;readline&lt;/code&gt; function to check whether you want to send a new kernel or not. Let’s press enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Hello world!
Got keyboard interrupt. Terminating...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Press &lt;code&gt;ctrl-c&lt;/code&gt; to exit.&lt;/p&gt;

&lt;h4&gt;
  
  
  Booting test: making a small change
&lt;/h4&gt;

&lt;p&gt;Sending the same kernel is not why we did all this work! Let’s make a small change to our kernel code, compile it and send it over UART (instead of putting it in the SD card). Go to the &lt;code&gt;kernel_main&lt;/code&gt; function and change the string that we send:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;kernel_main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
   &lt;span class="n"&gt;uart_send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello from a new kernel!!!&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s compile it and execute our python script (no need to copy anything to the SD card anymore!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./build.sh
&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python boot_send.py 
&lt;span class="go"&gt;Sending kernel with size 2005 and checksum 202127
Kernel size confirmed. Sending kernel
Validating checksum...
Done!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Great! We sent the kernel! Now, the moment of truth! Let’s press enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Hello from a new kernel!!!
Got keyboard interrupt. Terminating...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Git tag:&lt;/strong&gt; &lt;code&gt;uart-boot-string-change-test-uart-boot&lt;/code&gt; - &lt;a href="https://github.com/nicolasmesa/PiOS/tree/uart-boot-string-change-test-uart-boot"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Booting test: adding a function
&lt;/h4&gt;

&lt;p&gt;We did it! We’re done, right? Well, not so fast! Let’s try to make a different change. Let’s add a function and call it from &lt;code&gt;kernel_main&lt;/code&gt;. Open the &lt;code&gt;kernel.c&lt;/code&gt; file and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;my_test_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;uart_send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sending a test message!&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;kernel_main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
   &lt;span class="n"&gt;uart_send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello from a new kernel!!!&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
   &lt;span class="n"&gt;my_test_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We added a new function called &lt;code&gt;my_test_function&lt;/code&gt;, and we call it from &lt;code&gt;kernel_main&lt;/code&gt;. Let’s compile and send this over UART:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./build.sh
&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python boot_send.py Sending kernel with size 2077 and checksum 208704
&lt;span class="go"&gt;Kernel size confirmed. Sending kernel
Validating checksum...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It hangs in the &lt;em&gt;Validating checksum…&lt;/em&gt; part! So, what’s going on? Let’s think for a minute about what we’re doing. The Raspberry Pi loads our kernel from the SD card onto address &lt;code&gt;0x00&lt;/code&gt; and starts executing code in that address. When we copy the kernel over (over UART), we overwrite the kernel from the SD card with the new kernel. If the kernels are the same, it won’t make a difference since we’re effectively leaving the code as-is. Our string change didn’t affect us either because the strings go in the &lt;code&gt;.rodata&lt;/code&gt; (read-only data) section of the executable which goes after the &lt;code&gt;.text&lt;/code&gt; section (where the executable code lives), so changing the string doesn’t modify the addresses of the executable code. Adding a function, however, changes the &lt;code&gt;.text&lt;/code&gt; layout causing the kernel to “corrupt” itself while it copies the new kernel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git tag:&lt;/strong&gt; &lt;code&gt;uart-boot-fail-by-adding-function&lt;/code&gt; - &lt;a href="https://github.com/nicolasmesa/PiOS/tree/uart-boot-fail-by-adding-function"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;Before implementing a fix, let’s remove &lt;code&gt;my_test_function&lt;/code&gt; to get back into a “good” state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git tag:&lt;/strong&gt; &lt;code&gt;uart-boot-remove-test-function&lt;/code&gt; - &lt;a href="https://github.com/nicolasmesa/PiOS/tree/uart-boot-remove-test-function"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Options
&lt;/h4&gt;

&lt;p&gt;So, how do we fix this problem? Let’s consider these two options:&lt;/p&gt;

&lt;h5&gt;
  
  
  Option 1: Copy the kernel to a different location and jump there
&lt;/h5&gt;

&lt;p&gt;Using this option would not overwrite the kernel that is currently running, and we would jump to the new kernel in a different address. There’s a few drawbacks to this approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The kernel code will not start in address &lt;code&gt;0x00&lt;/code&gt;. The &lt;a href="https://github.com/s-matyukevich/raspberry-pi-os/"&gt;course&lt;/a&gt; might make some assumptions about the kernel being in address &lt;code&gt;0x00&lt;/code&gt;, and we would be breaking those assumptions.&lt;/li&gt;
&lt;li&gt;The course could use the address range that we choose to put our new kernel.&lt;/li&gt;
&lt;li&gt;We wouldn’t be able to send a kernel multiple times over UART in the same session (once we copy over the kernel and we’re running in the new address, we wouldn’t have a new place to copy another new kernel).&lt;/li&gt;
&lt;/ol&gt;

&lt;h5&gt;
  
  
  Option 2: Copy the current running kernel to a new address range, jump to it, copy the new kernel to the original address range, jump back to it
&lt;/h5&gt;

&lt;p&gt;To implement this option, we need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy the currently running kernel to a new memory location (let’s say &lt;code&gt;0x8000&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Jump to a function in the new address range.&lt;/li&gt;
&lt;li&gt;The function in the new memory location implements the protocol described above (our &lt;code&gt;copy_and_jump_to_kernel&lt;/code&gt; function).

&lt;ul&gt;
&lt;li&gt;It copies the kernel over UART starting at memory location &lt;code&gt;0x00&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Jump back to address &lt;code&gt;0x00&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Start running the new kernel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We treat the address range starting at &lt;code&gt;0x8000&lt;/code&gt; as temporary storage that we can use for other purposes once we jump back to address &lt;code&gt;0x00&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With this implementation, we’re able to keep all the assumptions that the course might be making and we’re able to copy the kernel multiple times over the same session! This approach is called chain loading. You can read more about &lt;a href="https://github.com/rust-embedded/rust-raspi3-OS-tutorials/tree/76b86a4997db57c37bfe12e7f2fb18e292069183/06_raspbootin64#chain-loading"&gt;chain loading here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fix implementation
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Position Independent Code
&lt;/h5&gt;

&lt;p&gt;Currently, the compiler compiles our kernel with the assumption that its code starts at address &lt;code&gt;0x00&lt;/code&gt;. The compiler can then hardcode the absolute addresses of every function using this. Absolute addresses become a problem once we start executing instructions in the kernel that starts at location &lt;code&gt;0x8000&lt;/code&gt; because it would still be referencing the old absolute memory locations.&lt;/p&gt;

&lt;p&gt;We can solve this issue by using &lt;a href="https://en.wikipedia.org/wiki/Position-independent_code"&gt;Position Independent Code&lt;/a&gt;, where the addresses are relative to the address held by the program counter.&lt;/p&gt;

&lt;p&gt;To enable this, we need to tweak our &lt;code&gt;Makefile&lt;/code&gt; to add the &lt;code&gt;-fPIC&lt;/code&gt; flag. You can read more about this flag in &lt;a href="https://stackoverflow.com/a/5311538"&gt;this Stack Overflow post&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# -fPIC makes the addresses relative instead of absolute allowing
# us to place the kernel anywhere in memory.
&lt;/span&gt;&lt;span class="nv"&gt;COPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-nostdlib&lt;/span&gt; &lt;span class="nt"&gt;-nostartfiles&lt;/span&gt; &lt;span class="nt"&gt;-ffreestanding&lt;/span&gt; &lt;span class="nt"&gt;-Iinclude&lt;/span&gt; &lt;span class="nt"&gt;-mgeneral-regs-only&lt;/span&gt;
&lt;span class="nv"&gt;ASMOPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-Iinclude&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This change is all that is needed to make our code position independent!&lt;/p&gt;

&lt;h5&gt;
  
  
  Determining current kernel size
&lt;/h5&gt;

&lt;p&gt;The kernel needs to know its size to be able to copy itself. We use the &lt;code&gt;bss_end&lt;/code&gt; section of the &lt;code&gt;linker.ld&lt;/code&gt; file to determine the size of the kernel. Let’s add a reference to that section in our &lt;code&gt;kernel.c&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include "utils.h"
&lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;bss_end&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We define this as an array, even though it technically isn’t (you can read more about why in &lt;a href="https://sourceware.org/binutils/docs/ld/Source-Code-Reference.html"&gt;this post&lt;/a&gt;). Now we can use &lt;code&gt;bss_end&lt;/code&gt; as a pointer to the address where the kernel ends (this includes the &lt;a href="https://en.wikipedia.org/wiki/.bss"&gt;.bss&lt;/a&gt;).&lt;/p&gt;

&lt;h5&gt;
  
  
  copy_current_kernel_and_jump
&lt;/h5&gt;

&lt;p&gt;Let’s implement a function that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copies the current kernel (starting in address &lt;code&gt;0x00&lt;/code&gt;) to the new address range (starting at &lt;code&gt;0x8000&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Jumps to the &lt;code&gt;copy_and_jump_to_kernel&lt;/code&gt; function, that we wrote before, in the new address range.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Make sure to define this function below the &lt;code&gt;copy_and_jump_to_kernel&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;copy_current_kernel_and_jump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;new_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bss_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Cast the function pointer to char* to deal with bytes.&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;original_function_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;copy_and_jump_to_kernel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Add the new address (we're assuming that the original kernel resides in&lt;/span&gt;
    &lt;span class="c1"&gt;// address 0). copied_function_address should now contain the address of the&lt;/span&gt;
    &lt;span class="c1"&gt;// original function but in the new location.&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;copied_function_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;original_function_address&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;new_address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Cast the address back to a function and call it.&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;call_function&lt;/span&gt;&lt;span class="p"&gt;)()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)())&lt;/span&gt;&lt;span class="n"&gt;copied_function_address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;call_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function copies the currently running kernel to the address range starting at &lt;code&gt;new_address&lt;/code&gt;. Then, it does some pointer math to determine the address of the &lt;code&gt;copy_and_jump_to_kernel&lt;/code&gt; function in the new address range. Finally, it calls that function in the new address range.&lt;/p&gt;

&lt;h5&gt;
  
  
  Call &lt;code&gt;copy_current_kernel_and_jump&lt;/code&gt; from &lt;code&gt;kernel_main&lt;/code&gt;
&lt;/h5&gt;

&lt;p&gt;All that remains is to call the &lt;code&gt;copy_current_kernel_and_jump&lt;/code&gt; from &lt;code&gt;kernel_main&lt;/code&gt; and, we should be ready to test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;kernel_main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"kernel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;copy_current_kernel_and_jump&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x8000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Git tag:&lt;/strong&gt; &lt;code&gt;uart-boot-fix-implementation&lt;/code&gt; - &lt;a href="https://github.com/nicolasmesa/PiOS/tree/uart-boot-fix-implementation"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the fix
&lt;/h3&gt;

&lt;p&gt;First, we need to build our kernel and copy it to the SD card. Refer to the Build the kernel and copy it to the SD card section.&lt;/p&gt;

&lt;p&gt;Let’s perform the same tests we ran before to make sure that we can still send the kernel over UART. Refer back to the following sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Booting test: sending the same kernel: This will help us make sure that the boot process works end-to-end.&lt;/li&gt;
&lt;li&gt;Booting test: making a small change: This test will help us make sure that everything is working at least as well as it was working before the fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Testing the previous error
&lt;/h5&gt;

&lt;p&gt;Now, the moment of truth! Let’s make a change that adds a function just like in the Adding a function section. Let’s test it out!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./build.sh
&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python boot_send.py 
&lt;span class="go"&gt;Sending kernel with size 2280 and checksum 223784
Kernel size confirmed. Sending kernel
Validating checksum...
Done!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This output is promising! At least our &lt;code&gt;boot_send&lt;/code&gt; script didn’t hang in the &lt;em&gt;Validating checksum…&lt;/em&gt; step like it did last time. The new kernel probably booted up and is stuck in the &lt;code&gt;readline&lt;/code&gt; function. Let’s press enter to send an empty line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Hello from a new kernel!!!
Sending a test message!
Got keyboard interrupt. Terminating...

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We did it! We were able to add a new function to the kernel, and it was still able to boot up!&lt;/p&gt;

&lt;h5&gt;
  
  
  Sending the same kernel multiple times
&lt;/h5&gt;

&lt;p&gt;Now, what if we try to send the same kernel over and over again? We would be able to send a new kernel that handles the next UART boot differently without having to put it in the SD card!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python boot_send.py 
&lt;span class="go"&gt;Sending kernel with size 2440 and checksum 234324
Kernel size confirmed. Sending kernel
Validating checksum...
Done!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Nothing surprising here, our kernel is stuck in the &lt;code&gt;readline&lt;/code&gt; function again. This time, instead of pressing enter, let’s press &lt;code&gt;ctrl-c&lt;/code&gt; to exit out of our &lt;code&gt;boot_send&lt;/code&gt; program and rerun it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Got keyboard interrupt. Terminating...
&lt;/span&gt;&lt;span class="gp"&gt;(rpi_os) $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python test.py 
&lt;span class="go"&gt;Sending kernel with size 2440 and checksum 234324
Kernel size confirmed. Sending kernel
Validating checksum...
Done!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We sent the kernel again in the same session! Let’s press enter to make sure that our new kernel booted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Hello from a new kernel!!!
Sending a test message!
Got keyboard interrupt. Terminating...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Git tag:&lt;/strong&gt; &lt;code&gt;uart-boot-succeeds-when-adding-function&lt;/code&gt; - &lt;a href="https://github.com/nicolasmesa/PiOS/tree/uart-boot-succeeds-when-adding-function"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we built a kernel that can be booted via UART to test, or from the SD card (for more permanent solutions). To do this, we came up with a protocol for the UART communication and implemented it. After a few tests, we noticed there was a problem when we tried to boot a kernel with an extra function. The problem was that the kernel was overwriting/corrupting its instructions. To overcome this problem, we made the kernel first copy itself to a new address range and perform the UART copy while executing from that address range. After the kernel finishes copying the new kernel over UART, it can jump back to the original start address (&lt;code&gt;0x00&lt;/code&gt;) and execute the new kernel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improvements
&lt;/h2&gt;

&lt;p&gt;Here is a small list of improvements that you can make to the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add arguments to the &lt;code&gt;boot_send&lt;/code&gt; script. I did this in &lt;a href="https://github.com/nicolasmesa/PiOS/blob/e567525eddccc22f55f4575052bddbacd3199e4d/boot_client/boot_send.py"&gt;my project&lt;/a&gt;, but this post is already long as it is.&lt;/li&gt;
&lt;li&gt;Clean the &lt;code&gt;kernel.c&lt;/code&gt; file and extract the functions to a helper file.&lt;/li&gt;
&lt;li&gt;Use the C preprocessor to exclude the UART boot section if you don’t pass a &lt;code&gt;UARTBoot&lt;/code&gt; flag.&lt;/li&gt;
&lt;li&gt;Make UART boot work with multiple CPUs. &lt;a href="https://github.com/nicolasmesa/PiOS#multiprocessor"&gt;I implemented this&lt;/a&gt; as well in a somewhat hacky way (I might write a post about it later).&lt;/li&gt;
&lt;li&gt;Add a better checksum (&lt;a href="https://en.wikipedia.org/wiki/Cyclic_redundancy_check"&gt;CRC&lt;/a&gt;, for example).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links / References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/s-matyukevich/raspberry-pi-os/"&gt;Learning operating system development using Linux kernel and Raspberry Pi&lt;/a&gt; (very recommended course!)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rust-embedded/rust-raspi3-OS-tutorials/tree/76b86a4997db57c37bfe12e7f2fb18e292069183/06_raspbootin64#chain-loading"&gt;Chain loading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/.bss"&gt;BSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Endianness"&gt;Endianness&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Position-independent_code"&gt;Position Independent Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/5311538"&gt;Position Independent Code Stack Overflow explanation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python-guide.org/dev/virtualenvs/"&gt;Python virtual environments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sourceware.org/binutils/docs/ld/Source-Code-Reference.html"&gt;Referencing linker script defined variable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/python-standard-library/0596000960/ch12s08.html"&gt;Setting terminal to “raw” mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/s-matyukevich/raspberry-pi-os/issues/115"&gt;UART Boot Github Issue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Cyclic_redundancy_check"&gt;CRC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>c</category>
      <category>kernel</category>
      <category>raspberrypi</category>
      <category>python</category>
    </item>
    <item>
      <title>SaaS Like Isolation in Django Rest Framework</title>
      <dc:creator>Nicolas Mesa</dc:creator>
      <pubDate>Mon, 08 Oct 2018 04:15:59 +0000</pubDate>
      <link>https://dev.to/nicolasmesa/saas-like-isolation-in-django-rest-framework-k96</link>
      <guid>https://dev.to/nicolasmesa/saas-like-isolation-in-django-rest-framework-k96</guid>
      <description>&lt;p&gt;Cross-posted from my personal blog &lt;a href="https://blog.nicolasmesa.co" rel="noopener noreferrer"&gt;https://blog.nicolasmesa.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hi there! In this post, we talk about how to add SaaS-like isolation to a Django Rest Framework service without bringing in third-party libraries.&lt;/p&gt;

&lt;p&gt;First, let’s start with why? I wanted to learn how to use Django Rest Framework by building a small SaaS service. I started googling to see if there were any resources available. Most of them suggested to use a third-party library such as &lt;a href="https://github.com/bennylope/django-organizations" rel="noopener noreferrer"&gt;Django Organizations&lt;/a&gt;, &lt;a href="https://django-tenant-schemas.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Django tenant schemas&lt;/a&gt; or use DB namespaces, all of which are only compatible with &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;Postgres&lt;/a&gt;. I didn’t want to rely on a third-party library for this, since this would mean, significant ramp-up time, another thing that could break, another thing to update, and another layer of abstraction that could end up getting in my way. I decided to do this myself.&lt;/p&gt;

&lt;p&gt;If you want to follow along, here’s what you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A computer with &lt;strong&gt;python 3&lt;/strong&gt; installed (I used python 3.6).&lt;/li&gt;
&lt;li&gt;A virtual environment already created and with Django (I used version 2.1.2) and Django rest framework (I used version 3.8.2).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We use SQLite for the database since it doesn’t make a difference for this example. Note that if you’re planning on using this for production, you should not use SQLite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use-cases
&lt;/h3&gt;

&lt;p&gt;For our sample project, we’re going to build the backend of a messaging API for a company. Here is a list of use-cases that our app needs to support:&lt;/p&gt;

&lt;p&gt;Users must be able to…&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;signup. A Company should be created automatically.&lt;/li&gt;
&lt;li&gt;create other users in the same company (we’re going to ignore admin users and permissions).&lt;/li&gt;
&lt;li&gt;see a list of users from the same company.&lt;/li&gt;
&lt;li&gt;send a message to another user in the same company.&lt;/li&gt;
&lt;li&gt;see the messages they sent or received.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Users must NOT be able to…&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;see the users from other companies.&lt;/li&gt;
&lt;li&gt;read messages from other companies.&lt;/li&gt;
&lt;li&gt;send messages to users in other companies.&lt;/li&gt;
&lt;li&gt;see messages from other users (even in the same company).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Start the project
&lt;/h3&gt;

&lt;p&gt;Let’s start our project. I name mine &lt;code&gt;saas_django&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;django-admin startproject saas_django
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;saas_django
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tree | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; pyc
&lt;span class="c"&gt;.
&lt;/span&gt;&lt;span class="go"&gt;├── manage.py
└── saas_django
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

1 directory, 5 files
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I usually commit all my changes every time I start a project or create a new app. This is an excellent way to provide checkpoints for yourself to be able to go back if needed. I’m going to skip the &lt;code&gt;git&lt;/code&gt; commands in here, but I encourage you to use version control to track your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  The accounts app
&lt;/h3&gt;

&lt;p&gt;Let’s create an app called &lt;code&gt;accounts&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py startapp accounts
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tree | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; pyc
&lt;span class="c"&gt;.
&lt;/span&gt;&lt;span class="go"&gt;├── accounts
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
└── saas_django
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

4 directories, 14 files
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s open &lt;code&gt;models.py&lt;/code&gt; in the &lt;code&gt;accounts&lt;/code&gt; folder and put in the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AbstractUser&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanyManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Manager for the Company model. Also handles the account creation&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="nd"&gt;@transaction.atomic&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Creates a Company along with the User and returns them both&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

        &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UUIDField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;editable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CompanyManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;db_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;companies&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractUser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UUIDField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;editable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%(class)s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;editable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;db_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;) - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code defines a &lt;code&gt;CompanyManager&lt;/code&gt;, a &lt;code&gt;Company&lt;/code&gt;, and a &lt;code&gt;User&lt;/code&gt;. Let’s dive into what each of these does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Company&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;This is the model that represents the SaaS account.&lt;/li&gt;
&lt;li&gt;Every other model should have a &lt;code&gt;ForeignKey&lt;/code&gt; that links back to this one.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;CompanyManager&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Provides a &lt;code&gt;create_account&lt;/code&gt; method that ensures that a &lt;code&gt;Company&lt;/code&gt; is always created with a &lt;code&gt;User&lt;/code&gt; assigned to it.&lt;/li&gt;
&lt;li&gt;Tom Christie recommends that we do this to be able to reason where changes to the DB are taking place (see &lt;a href="https://www.youtube.com/watch?v=3cSsbe-tA0E" rel="noopener noreferrer"&gt;this great video&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;User&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Custom User model. It is recommended not to use Django’s provided User model and create a custom one instead. Changing it afterward seems to be very painful.&lt;/li&gt;
&lt;li&gt;Defines the &lt;code&gt;__str__&lt;/code&gt; method to return the company name inside parentheses and the username. This will be useful later to be able to identify the company that a user belongs to.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : I also added the &lt;code&gt;db_table&lt;/code&gt; Meta field. This isn’t required, and Django will automatically name the DB table for you (for example the &lt;code&gt;Company&lt;/code&gt; table would have the name &lt;code&gt;accounts_company&lt;/code&gt;). I decided to add the &lt;code&gt;db_table&lt;/code&gt; to follow the advice from &lt;a href="https://blog.doordash.com/tips-for-building-high-quality-django-apps-at-scale-a5a25917b2b5" rel="noopener noreferrer"&gt;this blog post&lt;/a&gt; to manually name all of my database tables.&lt;/p&gt;

&lt;p&gt;Let’s open up our &lt;code&gt;settings.py&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;# Add these two lines
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rest_framework&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accounts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;AUTH_USER_MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accounts.User&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We add &lt;code&gt;rest_framework&lt;/code&gt; and our &lt;code&gt;accounts&lt;/code&gt; app to the &lt;code&gt;INSTALLED_APPS&lt;/code&gt; list. We also override the default User model and use our own instead by setting &lt;code&gt;AUTH_USER_MODEL&lt;/code&gt; to &lt;code&gt;accounts.User&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s create our migrations and migrate our database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py makemigrations
&lt;span class="go"&gt;Migrations for 'accounts':
  accounts/migrations/0001_initial.py
    - Create model User
    - Create model Company
    - Add field company to user
    - Add field groups to user
    - Add field user_permissions to user
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py migrate
&lt;span class="go"&gt;Operations to perform:
  Apply all migrations: accounts, admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0001_initial... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_log in_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying accounts.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying sessions.0001_initial... OK
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our database is now created along with the &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;companies&lt;/code&gt; tables. Let’s start working on our serializers. Create a new file called &lt;code&gt;serializers.py&lt;/code&gt; inside of the &lt;code&gt;accounts&lt;/code&gt; folder and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Company&lt;/span&gt;

&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HyperlinkedModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Make sure that the password field is never sent back to the client.
&lt;/span&gt;        &lt;span class="n"&gt;extra_kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;write_only&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;updated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# We save again the user if the password was specified to make sure it's properly hashed.
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;updated&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanySerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HyperlinkedModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Company&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccountSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Serializer that has two nested Serializers: company and user&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CompanySerializer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserSerializer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;company_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;user_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Call our CompanyManager method to create the Company and the User
&lt;/span&gt;        &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;company_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cannot call update() on an account&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create 3 serializers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;UserSerializer&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Serializes the &lt;code&gt;User&lt;/code&gt; model.&lt;/li&gt;
&lt;li&gt;Makes the &lt;code&gt;password&lt;/code&gt; field write-only to prevent our clients from ever seeing a password (even if it’s hashed).&lt;/li&gt;
&lt;li&gt;Overrides the &lt;code&gt;update&lt;/code&gt; method to properly handle a password update (not the most elegant solution since it involves two writes to the DB but it’s the only way I found that reuses the parent’s logic).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;CompanySerializer&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Serializes the &lt;code&gt;Company&lt;/code&gt; model.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;AccountsSerializer&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Uses the previously defined serializers.&lt;/li&gt;
&lt;li&gt;Calls the &lt;code&gt;create_account&lt;/code&gt; method that we added in &lt;code&gt;CompanyManager&lt;/code&gt; to create a new Company and User.&lt;/li&gt;
&lt;li&gt;Overrides the &lt;code&gt;update&lt;/code&gt; method to throw an exception if called. We do this because we only want this serializer to be used for account creation. After that, an edit can be made directly in the &lt;code&gt;/api/v1/users&lt;/code&gt; endpoint or in the &lt;code&gt;/api/v1/company&lt;/code&gt; endpoint (not implemented yet).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Let’s create the views for our accounts, users, and companies. Open the &lt;code&gt;views.py&lt;/code&gt; file in the &lt;code&gt;accounts&lt;/code&gt; directory and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;

&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccountCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;account-create&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccountSerializer&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListCreateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user-list&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserSerializer&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Ensure that the users belong to the company of the user that is making the request
&lt;/span&gt;        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetrieveUpdateDestroyAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user-detail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserSerializer&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Ensure that the user belongs to the company of the user that is making the request
&lt;/span&gt;        &lt;span class="c1"&gt;# Note that this method is identical to the one in `UserList`
&lt;/span&gt;        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanyDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetrieveUpdateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company-detail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompanySerializer&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Ensure that users can only see the company that they belong to
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define 4 views:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AccountCreate&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Only meant for account creation purposes.&lt;/li&gt;
&lt;li&gt;Inherits from &lt;code&gt;CreateAPIView&lt;/code&gt; so there won’t be a way to list or update the accounts.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;UserList&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Provides a list of users.&lt;/li&gt;
&lt;li&gt;Overrides the &lt;code&gt;get_queryset&lt;/code&gt; method to return only the results related to the company of the caller.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;UserDetail&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Provides a view for a single user.&lt;/li&gt;
&lt;li&gt;Overrides the &lt;code&gt;get_queryset&lt;/code&gt; method in the same way the &lt;code&gt;UserList&lt;/code&gt; view does (we’ll address this later). If you try to get a user from a different company, you will see a &lt;code&gt;404 Not Found&lt;/code&gt; response.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;CompanyDetail&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Provides the detailed view of a &lt;code&gt;Company&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Overrides the &lt;code&gt;get_object&lt;/code&gt; method to return the Company that the user belongs to.&lt;/li&gt;
&lt;li&gt;We don’t need to create a &lt;code&gt;CompanyList&lt;/code&gt; since there is no use-case to see a list of all the companies.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : We’re only checking for &lt;code&gt;IsAuthenticated&lt;/code&gt; permission (except for account creation). This allows a User in the same company to modify/delete any user in the company (including themselves). This can be fixed by creating custom &lt;code&gt;permissions&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;Let’s create our URLs. Create a file named &lt;code&gt;urls.py&lt;/code&gt; in the &lt;code&gt;accounts&lt;/code&gt; folder and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccountCreate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccountCreate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;users/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;users/&amp;lt;uuid:pk&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompanyDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompanyDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the main &lt;code&gt;urls.py&lt;/code&gt; located in the &lt;code&gt;django_saas&lt;/code&gt; folder and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;admin/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;api/v1/accounts/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accounts.urls&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;

    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;api/v1/auth/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rest_framework.urls&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define our URLs and include the URLs for authentication from rest_framework. The URLs for our API look like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/api/v1/accounts/&lt;/code&gt;: We can only &lt;code&gt;POST&lt;/code&gt; to this URL to create new account (company + user).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api/v1/users/&lt;/code&gt;: Can call &lt;code&gt;POST&lt;/code&gt; to create a new user for the company or &lt;code&gt;GET&lt;/code&gt; to get all the users in the company.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api/v1/users/&amp;lt;uuid&amp;gt;&lt;/code&gt;: Can call &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;PATCH&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt;. &lt;code&gt;GET&lt;/code&gt; returns a detailed view of the user with primary key &lt;code&gt;&amp;lt;uuid&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api/v1/company&lt;/code&gt;: Can call &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;PATCH&lt;/code&gt; to get/update the company of the user that made the request.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api/v1/auth/login&lt;/code&gt;: URL to log in using rest_framework’s built-in log in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is one more change I want to do before we test our accounts app. Open the &lt;code&gt;settings.py&lt;/code&gt; file and add the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ...
&lt;/span&gt;&lt;span class="n"&gt;LOGIN_REDIRECT_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/api/v1/accounts/users&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting the &lt;code&gt;LOGIN_REDIRECT_URL&lt;/code&gt; will redirect to this URL once a user has logged in successfully.&lt;/p&gt;

&lt;p&gt;Let’s fire up the server. Go to your terminal and type in the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py runserver
&lt;span class="go"&gt;Performing system checks...

System check identified no issues (0 silenced).
October 17, 2018 - 06:05:27
Django version 2.1.2, using settings 'saas_django.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our server is up! Now go to your favorite browser and navigate to &lt;code&gt;http://127.0.0.1:8000/api/v1/accounts/&lt;/code&gt;. You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Frest_framework_create_accounts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Frest_framework_create_accounts.png" alt="Account creation page in Django rest framework"&gt;&lt;/a&gt;Note that the &lt;code&gt;GET&lt;/code&gt; actually failed with a &lt;strong&gt;405 Method Not Allowed&lt;/strong&gt;. This is expected since this view should only be used for account creation. Note that the form clearly splits the Company and the User since we’re using the &lt;code&gt;AccountSerializer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s create two accounts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Account 1 information&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Company Name&lt;/strong&gt; : Company 1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Username&lt;/strong&gt; : user1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Account 2 information&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Company Name&lt;/strong&gt; : Company 2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Username&lt;/strong&gt; : user2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Input this information in the fields (select a password) and click the &lt;code&gt;POST&lt;/code&gt; button. If all goes well, you should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fcompany_2_creation.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fcompany_2_creation.png" alt="Company 2 creation is successful"&gt;&lt;/a&gt;Note that the password doesn’t show up in the returned JSON since we set it to be write-only in the &lt;code&gt;UserSerializer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s log in as &lt;code&gt;user1&lt;/code&gt;. Navigate to &lt;code&gt;http://127.0.0.1:8000/api/v1/auth/login&lt;/code&gt; and use the credentials to log in as &lt;code&gt;user1&lt;/code&gt;. You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fuser_list_right_after_logging_in_for_the_first_time.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fuser_list_right_after_logging_in_for_the_first_time.png" alt="User list after logging in for the first time. Only one user is displayed"&gt;&lt;/a&gt;We just see one user (&lt;code&gt;user1&lt;/code&gt;) even though we created two. This shows our &lt;code&gt;get_queryset&lt;/code&gt; defined in our views in action. Let’s add another user and make sure we can see that one. We’ll call this one &lt;code&gt;user3&lt;/code&gt;. After creating the user, click the &lt;code&gt;GET&lt;/code&gt; button and you should see both &lt;code&gt;user1&lt;/code&gt; and &lt;code&gt;user3&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "url": "http://127.0.0.1:8000/api/v1/accounts/users/962e4475-e213-4485-b8da-34cd0b34040a",
        "id": "962e4475-e213-4485-b8da-34cd0b34040a",
        "username": "user1"
    },
    {
        "url": "http://127.0.0.1:8000/api/v1/accounts/users/896b5d68-1215-43cd-9ad5-182518cf1dcd",
        "id": "896b5d68-1215-43cd-9ad5-182518cf1dcd",
        "username": "user3"
    }
]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take note of the URLs for the next experiment. Let’s log in as &lt;code&gt;user2&lt;/code&gt; and let’s try to visit one of the URLs of a user belonging to &lt;code&gt;Company 1&lt;/code&gt;. You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2F404_for_user_not_in_account.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2F404_for_user_not_in_account.png" alt="404 response code returned since user1 is not related to Company 2"&gt;&lt;/a&gt;This again shows our &lt;code&gt;get_queryset&lt;/code&gt; method in action. Even though a user with that &lt;code&gt;uuid&lt;/code&gt; exists, it isn’t related to the company that &lt;code&gt;user2&lt;/code&gt; belongs to, so our queryset filters it out.&lt;/p&gt;

&lt;p&gt;Let’s run one more experiment. Logged in as &lt;code&gt;user2&lt;/code&gt; point your browser to &lt;code&gt;http://127.0.0.1:8000/api/v1/accounts/company&lt;/code&gt;. You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fget_company_returns_the_users_company.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fget_company_returns_the_users_company.png" alt="The company returned is Company 2 (the company that user2 belongs to)"&gt;&lt;/a&gt;&lt;code&gt;Company 2&lt;/code&gt; is returned since that is the company that &lt;code&gt;user2&lt;/code&gt; belongs to. This shows our &lt;code&gt;get_object&lt;/code&gt; method in action in the &lt;code&gt;CompanyDetail&lt;/code&gt; view.&lt;/p&gt;

&lt;p&gt;While we’re logged in as &lt;code&gt;user2&lt;/code&gt;, let’s create &lt;code&gt;user4&lt;/code&gt; and &lt;code&gt;user6&lt;/code&gt; (let’s stick to even numbers for this company). Then, log in as either &lt;code&gt;user1&lt;/code&gt; or &lt;code&gt;user3&lt;/code&gt; and create &lt;code&gt;user5&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The User Messages App
&lt;/h3&gt;

&lt;p&gt;Let’s create another app called &lt;code&gt;user_messages&lt;/code&gt; (I tried to call it &lt;code&gt;messages&lt;/code&gt; earlier, but it conflicted with one of Django’s internal apps).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py startapp user_messages
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we start with our &lt;code&gt;UserMessage&lt;/code&gt; model, let’s create a model that handles the relationship with the &lt;code&gt;Company&lt;/code&gt; model. For this, let’s create a new directory named &lt;code&gt;core&lt;/code&gt; and let’s add a &lt;code&gt;models.py&lt;/code&gt; there. The structure should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tree | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; pyc
&lt;span class="c"&gt;.
&lt;/span&gt;&lt;span class="go"&gt;├── accounts
│   ├── __init__.py
│   ├── ...
├── core
│   ├── __init__.py
│   └── models.py
├── manage.py
├── saas_django
│   ├── __init__.py
│   ├── ...
└── user_messages
    ├── __init__.py
    ├── ...

9 directories, 38 files
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s add the following code to &lt;code&gt;core/models.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanyRelatedModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Abstract class used by models that belong to a Company&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UUIDField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;editable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accounts.Company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%(class)s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;editable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;abstract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we define an abstract class that has a foreign key to &lt;code&gt;accounts.Company&lt;/code&gt;. Let’s use this class by adding the following code to &lt;code&gt;user_messages/models.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;core.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CompanyRelatedModel&lt;/span&gt;

&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CompanyRelatedModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auto_now_add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;from_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sent_messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;to_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;received_messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;db_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;ordering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define a &lt;code&gt;UserMessage&lt;/code&gt; class that inherits from &lt;code&gt;CompanyRelatedModel&lt;/code&gt;. The model includes the following fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;: This field comes from the &lt;code&gt;CompanyRelatedModel&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;company&lt;/code&gt;: This field comes from the &lt;code&gt;CompanyRelatedModel&lt;/code&gt;. It relates a &lt;code&gt;user_message&lt;/code&gt; to a &lt;code&gt;company&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;text&lt;/code&gt;: The text of the user message.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;date&lt;/code&gt;: The date and time when the message was sent.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;from_user&lt;/code&gt;: A foreign key to the user that sent the message.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;to_user&lt;/code&gt;: A foreign key to the user that is the recipient of the message.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s open our &lt;code&gt;settings.py&lt;/code&gt; and add our app to the &lt;code&gt;INSTALLED_APPS&lt;/code&gt; list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accounts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;# Add this line
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s run the migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py makemigrations
&lt;span class="go"&gt;Migrations for 'user_messages':
  user_messages/migrations/0001_initial.py
    - Create model UserMessage
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py migrate
&lt;span class="go"&gt;Operations to perform:
  Apply all migrations: accounts, admin, auth, contenttypes, sessions, user_messages
Running migrations:
  Applying user_messages.0001_initial... OK
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s create a &lt;code&gt;serializers.py&lt;/code&gt; file in our &lt;code&gt;user_messages&lt;/code&gt; app and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessageSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HyperlinkedModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;from_user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;to_user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create a &lt;code&gt;UserMessageSerializer&lt;/code&gt; with the desired fields. We will make some modifications later.&lt;/p&gt;

&lt;p&gt;Let’s open our &lt;code&gt;views.py&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessageList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListCreateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;usermessage-list&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserMessageSerializer&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessageDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetrieveAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;usermessage-detail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserMessageSerializer&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define a &lt;code&gt;UserMessageList&lt;/code&gt; view and a &lt;code&gt;UserMessageDetail&lt;/code&gt; view. A few things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both views are guarded by the &lt;code&gt;IsAuthenticated&lt;/code&gt; permission.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;perform_create&lt;/code&gt; function ensures that the &lt;code&gt;UserMessage&lt;/code&gt; is related to the company that the current logged in user belongs to.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;UserMessageDetail&lt;/code&gt; extends the &lt;code&gt;generics.RetrieveAPIView&lt;/code&gt; class. This means that a &lt;code&gt;UserMessage&lt;/code&gt; is not editable or deletable (can only be viewed).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;get_queryset&lt;/code&gt; method is the same in both of these classes as well as in the &lt;code&gt;UserList&lt;/code&gt; and &lt;code&gt;UserDetail&lt;/code&gt; in the &lt;code&gt;accounts&lt;/code&gt; application. We’ll fix this later.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;get_queryset&lt;/code&gt; method makes sure that users can only see messages within their company. However, a user can still see messages from other users in their company. We’ll fix this later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s create the &lt;code&gt;urls.py&lt;/code&gt; for the &lt;code&gt;user_messages&lt;/code&gt; app and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserMessageList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserMessageList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;uuid:pk&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserMessageDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserMessageDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s include those urls in the main &lt;code&gt;urls.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;admin/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;api/v1/accounts/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accounts.urls&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="c1"&gt;# Add this line
&lt;/span&gt;    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;api/v1/user-messages/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_messages.urls&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;

    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;api/v1/auth/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rest_framework.urls&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After starting the server, navigate to &lt;code&gt;http://127.0.0.1:8000/api/v1/user-messages/&lt;/code&gt;. You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fempty_message_list.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fempty_message_list.png" alt="Empty message list since no messages have been created"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! We got it to work!&lt;/p&gt;

&lt;h3&gt;
  
  
  Refactoring the serializer
&lt;/h3&gt;

&lt;p&gt;Now, on to the bad news, expand the &lt;em&gt;From User&lt;/em&gt; select field. You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fusers_from_multiple_companies.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fusers_from_multiple_companies.png" alt="Multiple users from different companies showing up"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that we see users from both companies. To fix it, let’s create a &lt;code&gt;serializers.py&lt;/code&gt; in &lt;code&gt;core&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanySafeRelatedField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HyperlinkedRelatedField&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Ensures that the queryset only returns values for the company
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;request&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanySafeSerializerMixin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Mixin to be used with HyperlinkedModelSerializer to ensure that only company values are returned
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;serializer_related_field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CompanySafeRelatedField&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create two classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CompanySafeRelatedField&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Extends the default &lt;code&gt;HyperlinkedRelatedField&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Overrides the &lt;code&gt;get_queryset&lt;/code&gt; method to filter the results by the company of the logged in user.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;CompanySafeSerializerMixin&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Assigns the previously defined &lt;code&gt;CompanySafeRelatedField&lt;/code&gt; to the &lt;code&gt;serializer_related_field&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can read more about &lt;code&gt;serializer_related_field&lt;/code&gt; &lt;a href="https://www.django-rest-framework.org/api-guide/serializers/#serializer_related_field" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Open &lt;code&gt;user_messages/serializers.py&lt;/code&gt; and change it to be the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;
&lt;span class="c1"&gt;# Changed line (adds the import of CompanySafeSerializerMixin)
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;core.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CompanySafeSerializerMixin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;

&lt;span class="c1"&gt;# Changed line (adds the CompanySafeSerializerMixin)
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessageSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CompanySafeSerializerMixin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HyperlinkedModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;from_user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;to_user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s head back to our browser and refresh. Your user list should only display users from the same company:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fusers_only_from_same_company.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fusers_only_from_same_company.png" alt="Only users from the same company showing up"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have isolated users from other companies!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : A strange thing about this API is that the user needs to specify the &lt;em&gt;From user&lt;/em&gt;. This can lead to users sending messages on behalf of other users. Since the user that is sending the message is already logged in, there is no point for the &lt;em&gt;From user&lt;/em&gt; to be specified (the API should take care of this). We will fix this later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refactoring the views
&lt;/h3&gt;

&lt;p&gt;Let’s abstract the &lt;code&gt;Company&lt;/code&gt;-specific part of the views. Create &lt;code&gt;core/views.py&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;exceptions&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanySafeViewMixin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Mixin to be used with views that ensures that models are related to the company during creation and are querysets
    are filtered for read operations
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_authenticated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NotAuthenticated&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;queryset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code abstracts the &lt;code&gt;get_queryset&lt;/code&gt; and the &lt;code&gt;perform_create&lt;/code&gt; methods since they’re pretty similar for most views.&lt;/p&gt;

&lt;p&gt;Let’s add our mixin to our views. Open &lt;code&gt;accounts/views.py&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;

&lt;span class="c1"&gt;# New import
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;core.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CompanySafeViewMixin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;

&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccountCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;account-create&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccountSerializer&lt;/span&gt;

&lt;span class="c1"&gt;# Added CompanySafeViewMixin
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CompanySafeViewMixin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListCreateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user-list&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserSerializer&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Removed get_queryset and perform_create
&lt;/span&gt;
&lt;span class="c1"&gt;# Added CompanySafeViewMixin
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CompanySafeViewMixin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetrieveUpdateDestroyAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user-detail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserSerializer&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Removed get_queryset
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanyDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetrieveUpdateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company-detail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompanySerializer&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We inherit from the &lt;code&gt;CompanySafeViewMixin&lt;/code&gt; that we defined before to our &lt;code&gt;UserList&lt;/code&gt; and &lt;code&gt;UserDetail&lt;/code&gt; views. We also remove the &lt;code&gt;get_queryset&lt;/code&gt; and &lt;code&gt;perform_create&lt;/code&gt; since these are already implemented in the &lt;code&gt;CompanySafeViewMixin&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preventing user impersonation &amp;amp; protecting user privacy
&lt;/h3&gt;

&lt;p&gt;We could use the &lt;code&gt;CompanySafeViewMixin&lt;/code&gt; in our &lt;code&gt;user_messages&lt;/code&gt; app as well, and the current functionality would still work the same. However, we have two problems with the API right now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A user could impersonate another user because the &lt;em&gt;From user&lt;/em&gt; can be specified when we create a message.&lt;/li&gt;
&lt;li&gt;Users could read all of the messages related to their &lt;code&gt;Company&lt;/code&gt; even if they weren’t the senders or recipients.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To fix these two problems, we need to tune our own &lt;code&gt;perform_create&lt;/code&gt; and &lt;code&gt;get_queryset&lt;/code&gt; to meet our needs. Let’s make a few changes in our &lt;code&gt;UserMessage&lt;/code&gt; model first. Open &lt;code&gt;user_messages/models.py&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="c1"&gt;# New import
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;core.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CompanyRelatedModel&lt;/span&gt;

&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# New class
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessageManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_for_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Retrieves all messages that a user either sent or received&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CompanyRelatedModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auto_now_add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;from_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sent_messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;to_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;received_messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# New model manager
&lt;/span&gt;    &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserMessageManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;db_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;ordering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create a new model manager called &lt;code&gt;UserMessageManager&lt;/code&gt; and create a method &lt;code&gt;get_for_user&lt;/code&gt;. This method first filters by the &lt;code&gt;company_id&lt;/code&gt; to make sure nothing ever gets returned from other companies. Then, it filters to get messages that were sent from or to the user passed in as the argument.&lt;/p&gt;

&lt;p&gt;Let’s open &lt;code&gt;user_messages/serializers.py&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;core.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CompanySafeSerializerMixin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessageSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CompanySafeSerializerMixin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HyperlinkedModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;from_user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;to_user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# New read_only field
&lt;/span&gt;        &lt;span class="n"&gt;read_only_fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;from_user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We make the &lt;code&gt;from_user&lt;/code&gt; a read-only field. That way, our API will still return the sender of a message but won’t allow it to be edited. Since the &lt;code&gt;from_user&lt;/code&gt; field can’t be specified by the client, we need to make a change in the view. Open &lt;code&gt;user_messages/views.py&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessageList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListCreateAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;usermessage-list&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserMessageSerializer&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
        &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;
        &lt;span class="c1"&gt;# Added from_user
&lt;/span&gt;        &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;from_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Changed this to use the UserMessageManager's method
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_for_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMessageDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetrieveAPIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;usermessage-detail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserMessageSerializer&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Changed this to use the UserMessageManager's method
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_for_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This fixes the two issues mentioned above. We change the &lt;code&gt;perform_create&lt;/code&gt; function to include the &lt;code&gt;from_user&lt;/code&gt; in the &lt;code&gt;serializer.save&lt;/code&gt; call. We pass in the user that is currently logged in. We also change the &lt;code&gt;get_queryset&lt;/code&gt; method to only return messages that were either sent or received by the current user.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing it out
&lt;/h3&gt;

&lt;p&gt;Let’s log in as &lt;code&gt;user3&lt;/code&gt; and navigate to &lt;code&gt;http://127.0.0.1:8000/api/v1/user-messages/&lt;/code&gt;. Let’s send a message to &lt;code&gt;user1&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fsending_message_to_user1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fsending_message_to_user1.png" alt="Sending a message to user1"&gt;&lt;/a&gt;Note that there is no longer a choice to set the &lt;em&gt;From user&lt;/em&gt;. Let’s press the &lt;em&gt;POST&lt;/em&gt; button and verify that the message gets created with &lt;code&gt;from_user&lt;/code&gt; as &lt;code&gt;user3&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fmessage_sent_from_user3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fmessage_sent_from_user3.png" alt="Message has from_user from user3"&gt;&lt;/a&gt;Note that the &lt;code&gt;from_user&lt;/code&gt; field is a URL. Let’s click on that URL to make sure it’s &lt;code&gt;user3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fuser3_view.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fuser3_view.png" alt="User3 view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s log in as &lt;code&gt;user1&lt;/code&gt; in a different browser and reply to &lt;code&gt;user3&lt;/code&gt;. The messages should be visible for both &lt;code&gt;user1&lt;/code&gt; and &lt;code&gt;user3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fmessages_view_from_user1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fmessages_view_from_user1.png" alt="Messages view from user1"&gt;&lt;/a&gt;As expected, the messages can be seen by both &lt;code&gt;user1&lt;/code&gt; and &lt;code&gt;user3&lt;/code&gt;. Let’s log in as &lt;code&gt;user5&lt;/code&gt; and navigate to &lt;code&gt;http://127.0.0.1/api/v1/user-messages/&lt;/code&gt;. We shouldn’t be able to see any of the messages that we created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fuser5_cannot_see_other_messages.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fposts%2F2018%2F10%2Fuser5_cannot_see_other_messages.png" alt="User5 can't see other people's messages"&gt;&lt;/a&gt;As expected, &lt;code&gt;user5&lt;/code&gt; sees an empty list since no messages have been sent to/by this user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further improvements
&lt;/h2&gt;

&lt;p&gt;We’re now done with a simple use-case. Here are some ways to improve this further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add real &lt;a href="https://www.django-rest-framework.org/api-guide/versioning/#versioning-with-rest-framework" rel="noopener noreferrer"&gt;versioning support&lt;/a&gt; for the API.&lt;/li&gt;
&lt;li&gt;Improve the directory structure to have a more &lt;a href="https://github.com/pydanny/cookiecutter-django" rel="noopener noreferrer"&gt;cookiecutter&lt;/a&gt; approach.&lt;/li&gt;
&lt;li&gt;Remove SQLite and use &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;Postgres&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Prevent users from deleting themselves (can be done using &lt;a href="https://www.django-rest-framework.org/api-guide/permissions/" rel="noopener noreferrer"&gt;permissions&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Validate that users don’t message themselves.&lt;/li&gt;
&lt;li&gt;Prevent users from modifying other users (can be done using &lt;a href="https://www.django-rest-framework.org/api-guide/permissions/" rel="noopener noreferrer"&gt;permissions&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Add more models and views to use the &lt;code&gt;CompanyRelatedModel&lt;/code&gt; and &lt;code&gt;CompanySafeViewMixin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add filtering for user messages to be able to filter by &lt;code&gt;from_user&lt;/code&gt;, &lt;code&gt;to_user&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt;, etc (can be done using &lt;a href="https://django-filter.readthedocs.io/en/master/" rel="noopener noreferrer"&gt;django-filter&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Add the possibility to mark a message as read.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We went through the process of creating a SaaS messaging application that uses the same database schema for everybody. We went through incremental features and improvements to get to a final product that implemented all of our use-cases. We also abstracted out the repetitive code to make it more maintainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.nicolasmesa.co/posts/2018/10/saas-like-isolation-in-django-rest-framework/" rel="noopener noreferrer"&gt;Original Post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/2.1/topics/db/managers/" rel="noopener noreferrer"&gt;Model Managers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=3cSsbe-tA0E" rel="noopener noreferrer"&gt;Tom Christie about Django Rest Framework at Django: Under The Hood&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.doordash.com/tips-for-building-high-quality-django-apps-at-scale-a5a25917b2b5" rel="noopener noreferrer"&gt;Tips for building high quality django apps at scale from DoorDash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/serializers/#serializer_related_field" rel="noopener noreferrer"&gt;Serializer Related Field&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/versioning/#versioning-with-rest-framework" rel="noopener noreferrer"&gt;API Versioning in rest framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pydanny/cookiecutter-django" rel="noopener noreferrer"&gt;Cookiecutter project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;Postgres&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/permissions/" rel="noopener noreferrer"&gt;Permissions in rest framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bennylope/django-organizations" rel="noopener noreferrer"&gt;Django organizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://django-tenant-schemas.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Django tenant schemas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://django-filter.readthedocs.io/en/master/" rel="noopener noreferrer"&gt;django-filter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>saas</category>
      <category>rest</category>
    </item>
    <item>
      <title>How to Access Logged Objects in the Javascript Console</title>
      <dc:creator>Nicolas Mesa</dc:creator>
      <pubDate>Mon, 24 Sep 2018 04:54:51 +0000</pubDate>
      <link>https://dev.to/nicolasmesa/how-to-access-logged-objects-in-the-javascript-console-4ff2</link>
      <guid>https://dev.to/nicolasmesa/how-to-access-logged-objects-in-the-javascript-console-4ff2</guid>
      <description>&lt;p&gt;Cross-posted from my personal blog &lt;a href="https://blog.nicolasmesa.co"&gt;https://blog.nicolasmesa.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this short post, we go through the process of making a &lt;em&gt;console.logged&lt;/em&gt; Object available in Chrome’s javascript console.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;Right-click the Object you want to inspect and click &lt;strong&gt;Store as global variable&lt;/strong&gt;. This creates a variable with name &lt;code&gt;temp&amp;lt;n&amp;gt;&lt;/code&gt; where &lt;code&gt;&amp;lt;n&amp;gt;&lt;/code&gt; is a number (starts from &lt;code&gt;1&lt;/code&gt;). Use the variable to access the Object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explanation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Hack Version
&lt;/h3&gt;

&lt;p&gt;Sometimes when I’m debugging, I need to access an Object and its methods from the Javascript console. To do this, I have to fire up the debugger and step into the function until I get access to the object I want, or I have to come up with a hack like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;superNestedFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getObj&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// hack&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Do something interesting with obj&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For this discussion, let’s say the &lt;code&gt;getMyObj()&lt;/code&gt; function returns an object like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getObj&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Inside myObj.fn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, from the console, I can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;superNestedFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Logs: {prop: "Hello World", fn: ƒ}&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Logs: "Hello World"&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Logs: Inside myObj.fn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that this is a terrible hack! As much as I hate having a bunch of objects in my logs, I think it’s a lot worse to pollute the global namespace (especially when you forget to remove that hack). Let’s look at a better way of doing this.&lt;/p&gt;

&lt;h3&gt;
  
  
  The better version
&lt;/h3&gt;

&lt;p&gt;We’re going to use the same example that we had before (minus the hack). The entire code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;superNestedFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getObj&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// We're still logging the object&lt;/span&gt;

    &lt;span class="c1"&gt;// Do something interesting with obj&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getObj&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Inside myObj.fn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;superNestedFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Logs: {prop: "Hello World", fn: ƒ}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now right-click on the logged Object and select the &lt;strong&gt;Store as global variable&lt;/strong&gt; option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XNvAAsSt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/store_as_global_variable.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XNvAAsSt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/store_as_global_variable.png" alt='Right click on the Object an select "Store as global variable"'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chrome automatically creates a new global temporary variable (&lt;code&gt;temp1&lt;/code&gt; in this case) and assigns it the Object that you right-clicked:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hizKb8eK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/global_variable_created.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hizKb8eK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/global_variable_created.png" alt='Global variable "temp1" created by Chrome'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can use &lt;code&gt;temp1&lt;/code&gt; to access any field of that Object! Let’s see the whole thing in action:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/xR292-EaUZ0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We went through the steps to assign a logged object to a global variable and were able to access its properties and functions. Note that this is not a replacement for the debugger, it’s just a convenient way to explore an Object. Especially if the &lt;code&gt;console.log&lt;/code&gt; is already there.&lt;/p&gt;

&lt;p&gt;Happy debugging!&lt;/p&gt;

</description>
      <category>tips</category>
      <category>debugging</category>
      <category>javascript</category>
      <category>chrome</category>
    </item>
    <item>
      <title>How Does Traceroute Work</title>
      <dc:creator>Nicolas Mesa</dc:creator>
      <pubDate>Mon, 17 Sep 2018 03:50:26 +0000</pubDate>
      <link>https://dev.to/nicolasmesa/how-does-traceroute-work-8i9</link>
      <guid>https://dev.to/nicolasmesa/how-does-traceroute-work-8i9</guid>
      <description>

&lt;p&gt;Cross-posted from my personal blog &lt;a href="https://blog.nicolasmesa.co"&gt;https://blog.nicolasmesa.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post, we take a look at how the &lt;code&gt;traceroute&lt;/code&gt; command works. &lt;code&gt;traceroute&lt;/code&gt; is a utility command that prints the route (or hops) that a packet takes to reach another host. We start with an example of &lt;code&gt;traceroute&lt;/code&gt;. Then we go through what happened behind the scenes. Finally, we run the &lt;code&gt;traceroute&lt;/code&gt; command one more time while sniffing the traffic with &lt;code&gt;tcpdump&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;Traceroute example&lt;/h3&gt;

&lt;p&gt;Let’s look at an example:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~$&lt;/span&gt; ping &lt;span class="nt"&gt;-c&lt;/span&gt; 1 google.com
&lt;span class="go"&gt;PING google.com (172.217.14.206) 56(84) bytes of data.
64 bytes from sea30s01-in-f14.1e100.net. (172.217.14.206): icmp_seq=1 ttl=56 time=8.02 ms

--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 8.028/8.028/8.028/0.000 ms

&lt;/span&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~$&lt;/span&gt; traceroute &lt;span class="nt"&gt;-q&lt;/span&gt; 1 google.com
&lt;span class="go"&gt;traceroute to google.com (172.217.14.206), 64 hops max
  1 192.168.0.1 0.247ms
  2 67.218.102.107 11.667ms
  3 174.127.182.56 10.964ms
  4 174.127.141.190 12.403ms
  5 72.14.198.216 11.208ms
  6 74.125.243.177 13.321ms
  7 209.85.254.237 11.483ms
  8 172.217.14.206 12.060m
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First, we issue a &lt;code&gt;ping&lt;/code&gt; to &lt;code&gt;google.com&lt;/code&gt; to find out its IP address (&lt;code&gt;172.217.14.206&lt;/code&gt;). Then, we run a &lt;code&gt;traceroute&lt;/code&gt; command to &lt;code&gt;google.com&lt;/code&gt; (the &lt;code&gt;-q 1&lt;/code&gt; is to have &lt;code&gt;traceroute&lt;/code&gt; only send one packet instead of 3). In this example, we see that the packets have to traverse 8 hops to reach &lt;code&gt;google.com&lt;/code&gt;’s host.&lt;/p&gt;

&lt;h3&gt;IP Header&lt;/h3&gt;

&lt;p&gt;So, how does this work under the hood? To understand this, first, we need to talk about the Internet Protocol (IP). IP is responsible for delivering packets from the source host to the destination. Every IP packet has an IP header, which is used by routers to make routing decisions. The &lt;a href="https://en.wikipedia.org/wiki/IPv4#Header"&gt;IP header&lt;/a&gt; has a lot of information, but we’re going to focus on 3 fields:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Source IP (src)&lt;/strong&gt;: The IP address of the host that sent the packet (we’re going to ignore NATs for this discussion). In our case, it’s &lt;code&gt;192.168.0.250&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Destination IP (dst)&lt;/strong&gt;: IP address of the target host. In our case, it’s &lt;code&gt;google.com&lt;/code&gt;’s IP address: &lt;code&gt;172.217.14.206&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time to Live field (TTL)&lt;/strong&gt;: This field doesn’t contain a time, as the name suggests. It has the maximum number of hops that this packet should traverse before reaching its destination. If the maximum number of hops is reached, the packet is dropped, and an error message is sent to the sender. This field helps to prevent routing loops where a packet stays in a loop forever.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When a router receives an IP packet, it subtracts 1 from TTL field to determine if it should forward the packet or not. If the new TTL value is greater than 0, the router forwards the packet with the updated TTL value. If the new TTL is equal to 0, the router discards the packet and sends an ICMP error message to the source to let it know that the packet’s &lt;em&gt;time exceeded in-transit&lt;/em&gt; (the &lt;code&gt;TTL&lt;/code&gt; wasn’t large enough for the packet to reach the destination).&lt;/p&gt;

&lt;h3&gt;Traceroute introduction&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;traceroute&lt;/code&gt; takes advantage of the &lt;code&gt;TTL&lt;/code&gt; field and the &lt;code&gt;ICMP&lt;/code&gt; error message returned to trace the route to the target host. First, it sends a packet (usually UDP if in Linux) with &lt;code&gt;TTL = 1&lt;/code&gt;. When this packet reaches our router, the router decrements the &lt;code&gt;TTL&lt;/code&gt; and notices that the &lt;code&gt;TTL&lt;/code&gt; is equal to &lt;code&gt;0&lt;/code&gt;. Our router drops the packet and sends back an &lt;code&gt;ICMP&lt;/code&gt; error message. &lt;code&gt;traceroute&lt;/code&gt; uses the &lt;em&gt;source IP address&lt;/em&gt; in the &lt;code&gt;ICMP&lt;/code&gt; packet as the value of the first hop. &lt;code&gt;traceroute&lt;/code&gt; sends another datagram with &lt;code&gt;TTL = 2&lt;/code&gt;. Our router gets the packet, decrements the &lt;code&gt;TTL&lt;/code&gt; and forwards the packet since the &lt;code&gt;TTL&lt;/code&gt; is greater than &lt;code&gt;0&lt;/code&gt;. The second hop receives the packet, decrements the &lt;code&gt;TTL&lt;/code&gt; and notices that it is equal to &lt;code&gt;0&lt;/code&gt;. The router drops the packet and sends back an &lt;code&gt;ICMP&lt;/code&gt; error message which &lt;code&gt;traceroute&lt;/code&gt; uses to get the value for the second hop. &lt;code&gt;traceroute&lt;/code&gt; keeps incrementing the &lt;code&gt;TTL&lt;/code&gt; by one until it actually reaches the server. The server responds typically with an ICMP error stating that the &lt;code&gt;UDP&lt;/code&gt; port is unreachable. At that point, &lt;code&gt;traceroute&lt;/code&gt; is done.&lt;/p&gt;

&lt;h3&gt;Capturing the traceroute traffic&lt;/h3&gt;

&lt;p&gt;Let’s use &lt;code&gt;tcpdump&lt;/code&gt; to capture this exchange. First, we open a new terminal window and execute the following &lt;code&gt;tcpdump&lt;/code&gt; command:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~$&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;tcpdump &lt;span class="nt"&gt;-vv&lt;/span&gt; &lt;span class="nt"&gt;-nn&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; eth0 &lt;span class="s2"&gt;"(udp and ip[8] &amp;lt; 10) or icmp"&lt;/span&gt;
&lt;span class="go"&gt;tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s go over the arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-vv&lt;/code&gt;: To make the output verbose. We need this to be able to see the packet’s &lt;code&gt;TTL&lt;/code&gt; value.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-nn&lt;/code&gt;: We don’t want &lt;code&gt;tcpdump&lt;/code&gt; to resolve the IP addresses to hostnames or ports to service names.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-i eth0&lt;/code&gt;: The interface to listen on.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"(udp and ip[8] &amp;lt; 10) or icmp"&lt;/code&gt;: Filter to display either UDP packets with a &lt;code&gt;TTL&lt;/code&gt; value of less than 10 (adjust this number to meet your needs) or ICMP packets (to see the errors coming back from the routers).

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;ip[8]&lt;/code&gt; notation means the 8th byte (starting from 0) of the &lt;a href="https://en.wikipedia.org/wiki/IPv4#Header"&gt;IP Header&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In another terminal window, we run the &lt;code&gt;traceroute&lt;/code&gt; command:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~$&lt;/span&gt; traceroute &lt;span class="nt"&gt;-q&lt;/span&gt; 1 google.com
&lt;span class="go"&gt;traceroute to google.com (172.217.14.206), 64 hops max
  1 192.168.0.1 0.247ms
  2 67.218.102.107 11.667ms
  3 174.127.182.56 10.964ms
  4 174.127.141.190 12.403ms
  5 72.14.198.216 11.208ms
  6 74.125.243.177 13.321ms
  7 209.85.254.237 11.483ms
  8 172.217.14.206 12.060m
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we go back to the &lt;code&gt;tcpdump&lt;/code&gt; window, we see something like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~$&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;tcpdump &lt;span class="nt"&gt;-vv&lt;/span&gt; &lt;span class="nt"&gt;-nn&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; eth0 &lt;span class="s2"&gt;"(udp and ip[8] &amp;lt; 10) or icmp"&lt;/span&gt;
&lt;span class="go"&gt;tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
21:48:11.140870 IP (tos 0x0, ttl 1, id 34332, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33434: &lt;span class="o"&gt;[&lt;/span&gt;bad udp &lt;span class="nb"&gt;cksum &lt;/span&gt;0x7d6c -&amp;gt; 0x0386!] UDP, length 9
&lt;span class="go"&gt;21:48:11.141090 IP (tos 0xc0, ttl 64, id 59363, offset 0, flags [none], proto ICMP (1), length 65)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.1 &amp;gt;&lt;/span&gt; 192.168.0.250: ICMP &lt;span class="nb"&gt;time &lt;/span&gt;exceeded &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="nt"&gt;-transit&lt;/span&gt;, length 45
&lt;span class="go"&gt;        IP (tos 0x0, ttl 1, id 34332, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33434: &lt;span class="o"&gt;[&lt;/span&gt;udp &lt;span class="nb"&gt;sum &lt;/span&gt;ok] UDP, length 9
&lt;span class="go"&gt;21:48:11.141236 IP (tos 0x0, ttl 2, id 34333, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33435: &lt;span class="o"&gt;[&lt;/span&gt;bad udp &lt;span class="nb"&gt;cksum &lt;/span&gt;0x7d6c -&amp;gt; 0x0385!] UDP, length 9
&lt;span class="go"&gt;21:48:11.152912 IP (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto ICMP (1), length 56)
&lt;/span&gt;&lt;span class="gp"&gt;    67.218.102.107 &amp;gt;&lt;/span&gt; 192.168.0.250: ICMP &lt;span class="nb"&gt;time &lt;/span&gt;exceeded &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="nt"&gt;-transit&lt;/span&gt;, length 36
&lt;span class="go"&gt;        IP (tos 0x0, ttl 1, id 34333, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33435: UDP, length 9
&lt;span class="go"&gt;21:48:11.152943 IP (tos 0x0, ttl 3, id 34335, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33436: &lt;span class="o"&gt;[&lt;/span&gt;bad udp &lt;span class="nb"&gt;cksum &lt;/span&gt;0x7d6c -&amp;gt; 0x0384!] UDP, length 9
&lt;span class="go"&gt;21:48:11.163898 IP (tos 0x0, ttl 253, id 26888, offset 0, flags [none], proto ICMP (1), length 96)
&lt;/span&gt;&lt;span class="gp"&gt;    174.127.182.56 &amp;gt;&lt;/span&gt; 192.168.0.250: ICMP &lt;span class="nb"&gt;time &lt;/span&gt;exceeded &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="nt"&gt;-transit&lt;/span&gt;, length 76
&lt;span class="go"&gt;        IP (tos 0x0, ttl 1, id 34335, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33436: &lt;span class="o"&gt;[&lt;/span&gt;udp &lt;span class="nb"&gt;sum &lt;/span&gt;ok] UDP, length 9
&lt;span class="go"&gt;21:48:11.163934 IP (tos 0x0, ttl 4, id 34336, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33437: &lt;span class="o"&gt;[&lt;/span&gt;bad udp &lt;span class="nb"&gt;cksum &lt;/span&gt;0x7d6c -&amp;gt; 0x0383!] UDP, length 9
&lt;span class="go"&gt;21:48:11.176324 IP (tos 0x0, ttl 252, id 59054, offset 0, flags [none], proto ICMP (1), length 96)
&lt;/span&gt;&lt;span class="gp"&gt;    174.127.141.190 &amp;gt;&lt;/span&gt; 192.168.0.250: ICMP &lt;span class="nb"&gt;time &lt;/span&gt;exceeded &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="nt"&gt;-transit&lt;/span&gt;, length 76
&lt;span class="go"&gt;        IP (tos 0x0, ttl 1, id 34336, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33437: &lt;span class="o"&gt;[&lt;/span&gt;udp &lt;span class="nb"&gt;sum &lt;/span&gt;ok] UDP, length 9
&lt;span class="go"&gt;21:48:11.176368 IP (tos 0x0, ttl 5, id 34339, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33438: &lt;span class="o"&gt;[&lt;/span&gt;bad udp &lt;span class="nb"&gt;cksum &lt;/span&gt;0x7d6c -&amp;gt; 0x0382!] UDP, length 9
&lt;span class="go"&gt;21:48:11.187557 IP (tos 0x0, ttl 251, id 0, offset 0, flags [none], proto ICMP (1), length 56)
&lt;/span&gt;&lt;span class="gp"&gt;    72.14.198.216 &amp;gt;&lt;/span&gt; 192.168.0.250: ICMP &lt;span class="nb"&gt;time &lt;/span&gt;exceeded &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="nt"&gt;-transit&lt;/span&gt;, length 36
&lt;span class="go"&gt;        IP (tos 0x0, ttl 1, id 34339, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33438: UDP, length 9
&lt;span class="go"&gt;21:48:11.187622 IP (tos 0x0, ttl 6, id 34340, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33439: &lt;span class="o"&gt;[&lt;/span&gt;bad udp &lt;span class="nb"&gt;cksum &lt;/span&gt;0x7d6c -&amp;gt; 0x0381!] UDP, length 9
&lt;span class="go"&gt;21:48:11.200912 IP (tos 0x0, ttl 249, id 45260, offset 0, flags [none], proto ICMP (1), length 96)
&lt;/span&gt;&lt;span class="gp"&gt;    74.125.243.177 &amp;gt;&lt;/span&gt; 192.168.0.250: ICMP &lt;span class="nb"&gt;time &lt;/span&gt;exceeded &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="nt"&gt;-transit&lt;/span&gt;, length 76
&lt;span class="go"&gt;        IP (tos 0x80, ttl 1, id 34340, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33439: &lt;span class="o"&gt;[&lt;/span&gt;udp &lt;span class="nb"&gt;sum &lt;/span&gt;ok] UDP, length 9
&lt;span class="go"&gt;21:48:11.201012 IP (tos 0x0, ttl 7, id 34341, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33440: &lt;span class="o"&gt;[&lt;/span&gt;bad udp &lt;span class="nb"&gt;cksum &lt;/span&gt;0x7d6c -&amp;gt; 0x0380!] UDP, length 9
&lt;span class="go"&gt;21:48:11.212452 IP (tos 0x0, ttl 248, id 36434, offset 0, flags [none], proto ICMP (1), length 96)
&lt;/span&gt;&lt;span class="gp"&gt;    209.85.254.237 &amp;gt;&lt;/span&gt; 192.168.0.250: ICMP &lt;span class="nb"&gt;time &lt;/span&gt;exceeded &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="nt"&gt;-transit&lt;/span&gt;, length 76
&lt;span class="go"&gt;        IP (tos 0x80, ttl 1, id 34341, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33440: &lt;span class="o"&gt;[&lt;/span&gt;udp &lt;span class="nb"&gt;sum &lt;/span&gt;ok] UDP, length 9
&lt;span class="go"&gt;21:48:11.212596 IP (tos 0x0, ttl 8, id 34342, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33441: &lt;span class="o"&gt;[&lt;/span&gt;bad udp &lt;span class="nb"&gt;cksum &lt;/span&gt;0x7d6c -&amp;gt; 0x037f!] UDP, length 9
&lt;span class="go"&gt;21:48:11.224616 IP (tos 0x0, ttl 56, id 0, offset 0, flags [none], proto ICMP (1), length 56)
&lt;/span&gt;&lt;span class="gp"&gt;    172.217.14.206 &amp;gt;&lt;/span&gt; 192.168.0.250: ICMP 172.217.14.206 udp port 33441 unreachable, length 36
&lt;span class="go"&gt;        IP (tos 0x80, ttl 1, id 34342, offset 0, flags [DF], proto UDP (17), length 37)
&lt;/span&gt;&lt;span class="gp"&gt;    192.168.0.250.50475 &amp;gt;&lt;/span&gt; 172.217.14.206.33441: UDP, length 9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;Traceroute traffic deep dive&lt;/h3&gt;

&lt;p&gt;Let’s break this down. Line number 3 in the &lt;code&gt;traceroute&lt;/code&gt; command shows that the first hop is &lt;code&gt;192.168.0.1&lt;/code&gt; (my router). Take a look at the following line:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21:48:11.140870 IP (tos 0x0, ttl 1, id 34332, offset 0, flags [DF], proto UDP (17), length 37)
    192.168.0.250.50475 &amp;gt; 172.217.14.206.33434: [bad udp cksum 0x7d6c -&amp;gt; 0x0386!] UDP, length 9
21:48:11.141090 IP (tos 0xc0, ttl 64, id 59363, offset 0, flags [none], proto ICMP (1), length 65)
    192.168.0.1 &amp;gt; 192.168.0.250: ICMP time exceeded in-transit, length 45
        IP (tos 0x0, ttl 1, id 34332, offset 0, flags [DF], proto UDP (17), length 37)
    192.168.0.250.50475 &amp;gt; 172.217.14.206.33434: [udp sum ok] UDP, length 9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;ttl 1&lt;/code&gt; value. We can also see the &lt;code&gt;time exceeded in-transit&lt;/code&gt; message coming back with source IP &lt;code&gt;192.168.0.1&lt;/code&gt;. That corresponds with the first hop!&lt;/p&gt;

&lt;p&gt;The second hop in the &lt;code&gt;traceroute&lt;/code&gt; command is &lt;code&gt;67.218.102.107&lt;/code&gt; (line 4). This also corresponds to the following lines:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21:48:11.141236 IP (tos 0x0, ttl 2, id 34333, offset 0, flags [DF], proto UDP (17), length 37)
    192.168.0.250.50475 &amp;gt; 172.217.14.206.33435: [bad udp cksum 0x7d6c -&amp;gt; 0x0385!] UDP, length 9
21:48:11.152912 IP (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto ICMP (1), length 56)
    67.218.102.107 &amp;gt; 192.168.0.250: ICMP time exceeded in-transit, length 36
        IP (tos 0x0, ttl 1, id 34333, offset 0, flags [DF], proto UDP (17), length 37)
    192.168.0.250.50475 &amp;gt; 172.217.14.206.33435: UDP, length 9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here we see the &lt;code&gt;ttl 2&lt;/code&gt; value. Note that the source IP (&lt;code&gt;192.168.0.250&lt;/code&gt;) and destination IP (&lt;code&gt;172.217.14.206&lt;/code&gt;) haven’t changed (the target port increases by 1 every message, but this doesn’t affect our discussion). The ICMP error message has source IP &lt;code&gt;67.218.102.107&lt;/code&gt; which also aligns with what we see in our traceroute command! Let’s go all the way to the end!&lt;/p&gt;

&lt;p&gt;The last hop in the &lt;code&gt;traceroute&lt;/code&gt; command is &lt;code&gt;172.217.14.206&lt;/code&gt;, one of the IP addresses of &lt;code&gt;google.com&lt;/code&gt;. Let’s examine our &lt;code&gt;tcpdump&lt;/code&gt; output for that hop.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21:48:11.212596 IP (tos 0x0, ttl 8, id 34342, offset 0, flags [DF], proto UDP (17), length 37)
    192.168.0.250.50475 &amp;gt; 172.217.14.206.33441: [bad udp cksum 0x7d6c -&amp;gt; 0x037f!] UDP, length 9
21:48:11.224616 IP (tos 0x0, ttl 56, id 0, offset 0, flags [none], proto ICMP (1), length 56)
    172.217.14.206 &amp;gt; 192.168.0.250: ICMP 172.217.14.206 udp port 33441 unreachable, length 36
        IP (tos 0x80, ttl 1, id 34342, offset 0, flags [DF], proto UDP (17), length 37)
    192.168.0.250.50475 &amp;gt; 172.217.14.206.33441: UDP, length 9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We now see a &lt;code&gt;ttl 8&lt;/code&gt; value. Note that there isn’t a &lt;code&gt;time exceeded in-transit&lt;/code&gt; ICMP error message. Instead, the server responded with an ICMP message saying &lt;code&gt;udp port 33441 unreachable&lt;/code&gt;. This error is coming from the host since it is the only one who knows if that port is open or not. This message tells &lt;code&gt;traceroute&lt;/code&gt; that the last packet it sent reached the host and there are no more hops in the way.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;We covered how &lt;code&gt;traceroute&lt;/code&gt; works under the hood. We saw how this command uses the TTL field to control the number of hops that the packet travels before it is dropped and an error message is sent back to us. We also saw that the source IP address of the ICMP error message is also the IP address of the hop that dropped the packet. Some routers are configured to drop the packet silently and not send an ICMP error message (this shows up as a &lt;code&gt;*&lt;/code&gt; entry in the &lt;code&gt;traceroute&lt;/code&gt; output).&lt;/p&gt;

&lt;p&gt;One thing we didn’t talk about is the IP header checksum. The checksum is used to verify the contents of the IP header (not the IP body). This checksum is validated on every hop and needs to be recalculated after decrementing the &lt;code&gt;TTL&lt;/code&gt; value.&lt;/p&gt;

&lt;h2&gt;Links&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.nicolasmesa.co/posts/2018/09/how-does-traceroute-work/"&gt;Original Post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linux.die.net/man/8/traceroute"&gt;Traceroute man page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Internet_Protocol"&gt;Internet Protocol (IP)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/IPv4#Header"&gt;IP header&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Time_to_live"&gt;Time to live (TTL)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


</description>
      <category>commandline</category>
      <category>linux</category>
      <category>networks</category>
      <category>udp</category>
    </item>
    <item>
      <title>Serve Your Current Directory With Python and HTTP</title>
      <dc:creator>Nicolas Mesa</dc:creator>
      <pubDate>Mon, 03 Sep 2018 18:08:26 +0000</pubDate>
      <link>https://dev.to/nicolasmesa/serve-your-current-directory-with-python-and-http-2m3p</link>
      <guid>https://dev.to/nicolasmesa/serve-your-current-directory-with-python-and-http-2m3p</guid>
      <description>

&lt;p&gt;Cross-posted from my personal blog &lt;a href="https://blog.nicolasmesa.co"&gt;https://blog.nicolasmesa.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is going to be a short post showing how to run an HTTP server to serve your current working directory.&lt;/p&gt;

&lt;h2&gt;TLDR&lt;/h2&gt;

&lt;p&gt;For Python 3 run:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;python3 -m http.server
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For Python 2 run:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;python -m SimpleHTTPServer
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.bashrc&lt;/code&gt; alias:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;serve&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python3 -m http.server"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;Explanation&lt;/h2&gt;

&lt;p&gt;Sometimes at work, I’ve had the need to spin up a quick HTTP server to serve my current working directory. I usually need this for two use cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Share a quick link to have people download something from my computer.&lt;/li&gt;
&lt;li&gt;I have an &lt;code&gt;index.html&lt;/code&gt; file in another computer along with a bunch of static resources and don’t feel like copying the whole folder to be able to see the page in my browser. This use case happens a lot when I’m running unit tests on another computer and need to look at coverage reports (which are rendered in HTML).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It turns out that serving your current directory with an HTTP server is easy. You only need &lt;code&gt;python&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Setup&lt;/h2&gt;

&lt;p&gt;Before we get started, let’s create some sample files.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; &lt;span class="nb"&gt;echo &lt;/span&gt;file1 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; file1.txt
&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; &lt;span class="nb"&gt;echo &lt;/span&gt;file2 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; file2.txt
&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; &lt;span class="nb"&gt;mkdir &lt;/span&gt;dir1 dir2
&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; &lt;span class="nb"&gt;echo &lt;/span&gt;file3 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; dir1/file3.txt
&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; &lt;span class="nb"&gt;echo &lt;/span&gt;file4 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; dir2/file4.txt
&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; tree
&lt;span class="c"&gt;.
&lt;/span&gt;&lt;span class="go"&gt;├── dir1
│   └── file3.txt
├── dir2
│   └── file4.txt
├── file1.txt
└── file2.txt

2 directories, 4 files
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We created two files and two directories in the root, and one file in each of the directories.&lt;/p&gt;

&lt;h2&gt;Find out your python version&lt;/h2&gt;

&lt;p&gt;The command to spin up the HTTP server varies depending on the version of python that you have. Run &lt;code&gt;python --version&lt;/code&gt; to get your current version of &lt;code&gt;python&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; python &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="go"&gt;Python 3.5.2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you see &lt;code&gt;Python 3.x.x&lt;/code&gt;, use the Python 3 command. If you see &lt;code&gt;Python 2.x.x&lt;/code&gt;, use the Python 2 command.&lt;/p&gt;

&lt;p&gt;In this case, I’m using Python 3.&lt;/p&gt;

&lt;h2&gt;Python 3 command&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; python3 &lt;span class="nt"&gt;-m&lt;/span&gt; http.server
&lt;span class="go"&gt;Serving HTTP on 0.0.0.0 port 8000 ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;Python 2 command&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; python &lt;span class="nt"&gt;-m&lt;/span&gt; SimpleHTTPServer
&lt;span class="go"&gt;Serving HTTP on 0.0.0.0 port 8000 ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;Test it out&lt;/h2&gt;

&lt;p&gt;The previous commands spun up an HTTP server listening on port &lt;code&gt;8000&lt;/code&gt;. Let’s point our web browser to the server’s IP address on port &lt;code&gt;8000&lt;/code&gt; (&lt;code&gt;192.168.0.250:8000&lt;/code&gt; in this case). The page should look like this:&lt;/p&gt;

&lt;h3&gt;Root directory&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LHO_Y7sX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/sample_root_directory_listing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LHO_Y7sX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/sample_root_directory_listing.png" alt="Sample root directory listing"&gt;&lt;/a&gt;Sample root directory listing. This is the equivalent of running an &lt;code&gt;ls&lt;/code&gt; on the directory where the server is running.&lt;/p&gt;

&lt;h3&gt;Child directory&lt;/h3&gt;

&lt;p&gt;Let’s click the &lt;code&gt;dir1/&lt;/code&gt; link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CvR7BV6f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/dir1_directory_listing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CvR7BV6f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/dir1_directory_listing.png" alt="dir1 directory listing"&gt;&lt;/a&gt;&lt;code&gt;dir1&lt;/code&gt; directory listing.&lt;/p&gt;

&lt;h3&gt;File&lt;/h3&gt;

&lt;p&gt;Let’s click the &lt;code&gt;file3.txt&lt;/code&gt; link.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0CV5DSuV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/file3_file_contents.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0CV5DSuV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.nicolasmesa.co/posts/2018/09/file3_file_contents.png" alt="file3.txt contents"&gt;&lt;/a&gt;&lt;code&gt;file3.txt&lt;/code&gt; contents. Note that this file rendered in the browser. This is because the HTTP server is smart enough to add a content type to the HTTP response. This becomes handy when you need to serve HTML along with CSS, JS, and images.&lt;/p&gt;

&lt;h2&gt;Update (Oct 21, 2018)&lt;/h2&gt;

&lt;p&gt;I’ve been using this a lot at work to serve test coverage reports. To save some typing, let’s add the following alias to our &lt;code&gt;.bashrc&lt;/code&gt; (&lt;code&gt;.bash_profile&lt;/code&gt; in Mac) file:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;serve&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python3 -m http.server"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s test it out by running &lt;code&gt;serve&lt;/code&gt; from our target directory (note that you will need to run &lt;code&gt;source ~/.bashrc&lt;/code&gt; or start a new terminal for this to work):&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; serve
&lt;span class="go"&gt;Serving HTTP on 0.0.0.0 port 8000 ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can also specify a different port:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/serve-cwd$&lt;/span&gt; serve 9000
&lt;span class="go"&gt;Serving HTTP on 0.0.0.0 port 9000 ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command starts the web server in port &lt;code&gt;9000&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Python makes it easy to spin up an HTTP server to share your current working directory. Please don’t forget to kill the server once you’re done and be careful with what you share.&lt;/p&gt;

&lt;h2&gt;Links / Further reading&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.nicolasmesa.co/posts/2018/09/serve-your-current-directory-with-python-and-http/"&gt;Original Post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/python/cpython/blob/3.7/Lib/http/server.py#L627"&gt;SimpleHTTPRequestHandler source code (python 3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/python/cpython/blob/2.7/Lib/SimpleHTTPServer.py#L28"&gt;SimpleHTTPRequestHandler source code (python 2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.linfo.org/alias.html"&gt;alias command&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


</description>
      <category>commandline</category>
      <category>python</category>
      <category>http</category>
      <category>tips</category>
    </item>
    <item>
      <title>Container Creation Using Namespaces and Bash</title>
      <dc:creator>Nicolas Mesa</dc:creator>
      <pubDate>Fri, 24 Aug 2018 04:30:27 +0000</pubDate>
      <link>https://dev.to/nicolasmesa/container-creation-using-namespaces-and-bash-6g</link>
      <guid>https://dev.to/nicolasmesa/container-creation-using-namespaces-and-bash-6g</guid>
      <description>&lt;p&gt;Cross-posted from my personal blog &lt;a href="https://blog.nicolasmesa.co"&gt;https://blog.nicolasmesa.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A few weeks ago, I saw a great video explaining how Docker works under the hood (see video below). The video ends with a demo where Jérôme Petazzoni creates a container using nothing but bash. I found many of the commands that he used pretty cryptic, so I decided to explain what he did and the purpose of each command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/sK5i-N34im8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;(The demo starts around minute 41)&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminology
&lt;/h2&gt;

&lt;p&gt;Before we dive into the demo, let’s get some terminology out of the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Container
&lt;/h3&gt;

&lt;p&gt;A container is a combination of a few technologies including namespaces, cgroups, and capabilities. In this post, we’re going to focus on namespaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  Namespaces
&lt;/h3&gt;

&lt;p&gt;From &lt;a href="https://lwn.net/Articles/531114/"&gt;Namespaces in operation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The purpose of each namespace is to wrap a particular global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are six types of namespaces in Linux:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pid: Isolates process identifiers. For example, two processes in different namespaces can have the same &lt;em&gt;PID&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;User: Isolates user ids and group ids. Two users in two different user namespaces can have the same user ids. This is pretty useful because it allows mapping an unprivileged user id outside of the namespace to be root inside of the namespace.&lt;/li&gt;
&lt;li&gt;Net: This namespace provides network isolation. Processes running in a separate net namespace don’t see the network interfaces of other namespaces.&lt;/li&gt;
&lt;li&gt;Mnt: The mount namespace allows containers to have their own mount points without polluting the global namespace. It also provides a way to hide the global mount points from the container.&lt;/li&gt;
&lt;li&gt;Uts: This allows a container to have its own hostname for the processes running in the container.&lt;/li&gt;
&lt;li&gt;Ipc: Gives containers their own inter-process communication namespace.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : There is a lot more to namespaces than this. If you want to learn more, take a look at &lt;a href="https://lwn.net/Articles/531114/"&gt;Namespaces in operation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Btrfs
&lt;/h3&gt;

&lt;p&gt;From the &lt;a href="https://btrfs.wiki.kernel.org/index.php/Main_Page"&gt;Btrfs wiki&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Btrfs is a modern copy on write (CoW) filesystem for Linux aimed at implementing advanced features while also focusing on fault tolerance, repair, and easy administration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  System
&lt;/h3&gt;

&lt;p&gt;For this demo, I used a computer running Ubuntu 16.04. To be more specific:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/containers$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;span class="gp"&gt;Linux desktop-nicolas 4.13.0-39-generic #&lt;/span&gt;44~16.04.1-Ubuntu SMP Thu Apr 5 16:43:10 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We also need &lt;em&gt;docker&lt;/em&gt; for two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To extract the &lt;em&gt;alpine&lt;/em&gt; docker image.&lt;/li&gt;
&lt;li&gt;To use the bridge provided by &lt;em&gt;docker&lt;/em&gt; for networking.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the version of &lt;em&gt;docker&lt;/em&gt; that I had installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker version
&lt;span class="go"&gt;Client:
 Version: 18.06.0-ce
 API version: 1.38
 Go version: go1.10.3
 Git commit: 0ffa825
 Built: Wed Jul 18 19:11:02 2018
 OS/Arch: linux/amd64
 Experimental: false

Server:
 Engine:
  Version: 18.06.0-ce
  API version: 1.38 (minimum version 1.12)
  Go version: go1.10.3
  Git commit: 0ffa825
  Built: Wed Jul 18 19:09:05 2018
  OS/Arch: linux/amd64
  Experimental: false
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  System setup
&lt;/h3&gt;

&lt;p&gt;Before we start to follow along with the video, we to need setup our environment into the same state as Jérôme’s computer. We need to have a &lt;em&gt;btrfs&lt;/em&gt; filesystem mounted in &lt;em&gt;/btrfs&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create the disk image
&lt;/h4&gt;

&lt;p&gt;We start by creating an empty disk image (from the &lt;a href="https://btrfs.wiki.kernel.org/index.php/Getting_started#Basic_Filesystem_Commands"&gt;btrfs wiki&lt;/a&gt;, the image should be at least 1GB in size).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/containers$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;dd &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/zero &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;disk.img &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;512 &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4194304
&lt;span class="go"&gt;4194304+0 records in
4194304+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 4.60753 s, 466 MB/s

&lt;/span&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/containers$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-alh&lt;/span&gt; disk.img
&lt;span class="go"&gt;-rw-rw-r-- 1 nmesa nmesa 2.0G Aug 23 22:06 disk.img
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We use the &lt;code&gt;dd&lt;/code&gt; command to create a 2GB empty image. The &lt;code&gt;dd&lt;/code&gt; command receives four arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;if&lt;/code&gt;: The file/device to use as the input. In this case, &lt;code&gt;/dev/zero&lt;/code&gt;, which outputs a bunch of zeroes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;of&lt;/code&gt;: The output file/device. In this case, &lt;code&gt;disk.img&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bs&lt;/code&gt;: This is the block size in bytes (512 bytes in this case).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count&lt;/code&gt;: The number of &lt;code&gt;bs&lt;/code&gt; blocks to read from &lt;code&gt;/dev/zero&lt;/code&gt; and write to &lt;code&gt;disk.img&lt;/code&gt;. In this case, 4194304 (2 * 1024 * 1024 * 1024 / 512) to make the image 2GB.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Format disk image
&lt;/h4&gt;

&lt;p&gt;Let’s format our new image with the &lt;em&gt;btrfs&lt;/em&gt; filesystem by using the &lt;code&gt;mkfs.btrfs&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/containers$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mkfs.btrfs disk.img
&lt;span class="go"&gt;btrfs-progs v4.4
See http://btrfs.wiki.kernel.org for more information.

Label: (null)
UUID: 772f0676-ec96-448d-b58c-31d4c10b5c3a
Node size: 16384
Sector size: 4096
Filesystem size: 2.00GiB
Block group profiles:
  Data: single 8.00MiB
  Metadata: DUP 110.38MiB
  System: DUP 12.00MiB
SSD detected: no
Incompat features: extref, skinny-metadata
Number of devices: 1
Devices:
   ID SIZE PATH
    1 2.00GiB disk.img
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Mount the disk image
&lt;/h4&gt;

&lt;p&gt;Great! We have formatted the filesystem! We need to mount the image to &lt;em&gt;/btrfs&lt;/em&gt; using the &lt;code&gt;mount&lt;/code&gt; command (note that you have to be &lt;strong&gt;root&lt;/strong&gt; ).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/home/nmesa/demos/containers#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /btrfs
&lt;span class="gp"&gt;root@desktop-nicolas:/home/nmesa/demos/containers#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; btrfs disk.img /btrfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are ready to follow along with the video!&lt;/p&gt;

&lt;h2&gt;
  
  
  Video breakdown
&lt;/h2&gt;

&lt;p&gt;In this section, we follow along with the video, and I describe what each command does. Most commands require that you run them as &lt;strong&gt;root&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make mount private
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mount &lt;span class="nt"&gt;--make-rprivate&lt;/span&gt; /
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this command, we make the mounts that our container is going to make private. This prevents any mounts that our container does, from being visible by the host system. The &lt;code&gt;r&lt;/code&gt; in &lt;code&gt;--make-rprivate&lt;/code&gt; stands for &lt;em&gt;recursive&lt;/em&gt; which means it makes all mount points private.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create container image
&lt;/h3&gt;

&lt;p&gt;Let’s create two directories, one to hold the source images and one to hold the container images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;images containers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then we use the &lt;code&gt;btrfs subvol create&lt;/code&gt; command to create a new image called &lt;em&gt;alpine&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;btrfs subvol create images/alpine
&lt;span class="go"&gt;Create subvolume 'images/alpine'
&lt;/span&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;images/alpine/
&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;btrfs&lt;/code&gt; command is used to control &lt;em&gt;btrfs&lt;/em&gt; filesystems. The &lt;code&gt;subvolume&lt;/code&gt; subcommand is used to manage &lt;em&gt;btrfs subvolumes&lt;/em&gt;. We use the &lt;code&gt;create&lt;/code&gt; subcommand to create a subvolume named &lt;em&gt;alpine&lt;/em&gt; in the &lt;em&gt;images&lt;/em&gt; directory.&lt;/p&gt;

&lt;p&gt;We have an image, but it’s empty. We use &lt;code&gt;docker&lt;/code&gt; to get the &lt;em&gt;alpine&lt;/em&gt; image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; alpine &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$CID&lt;/span&gt;
&lt;span class="go"&gt;9b290758c1734811c85445640c985fed9803121891d6604b4260e985c2647404
&lt;/span&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;$CID&lt;/span&gt; | &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; images/alpine/ &lt;span class="nt"&gt;-xf-&lt;/span&gt;
&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;images/alpine/
&lt;span class="go"&gt;bin dev etc home lib media mnt proc root run sbin srv sys tmp usr var
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We run &lt;code&gt;docker run -d alpine true&lt;/code&gt; and assign its output (the container id) to the &lt;code&gt;CID&lt;/code&gt; variable. Here’s a better explanation of the &lt;code&gt;docker&lt;/code&gt; command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;run&lt;/code&gt;: runs a container.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt;: Detaches the container and prints the container id. Our terminal doesn’t wait for the container to finish its execution.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alpine&lt;/code&gt;: The image that the container should use.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;true&lt;/code&gt;: The command to run in the container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We use the &lt;code&gt;docker export&lt;/code&gt; command to export the image. We pipe that image to the &lt;code&gt;tar&lt;/code&gt; command which decompresses it and puts the files in &lt;em&gt;images/alpine&lt;/em&gt;. Then we run &lt;code&gt;ls images/alpine&lt;/code&gt; to see the contents of the image.&lt;/p&gt;

&lt;p&gt;The next step is to take a &lt;em&gt;snapshot&lt;/em&gt; of this image and put it in our containers folder. The snapshot’s name is &lt;a href="https://en.wikipedia.org/wiki/Tupperware"&gt;tupperware&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;btrfs subvol snapshot images/alpine/ containers/tupperware
&lt;span class="go"&gt;Create a snapshot of 'images/alpine/' in 'containers/tupperware'
&lt;/span&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;containers/tupperware/
&lt;span class="go"&gt;bin dev etc home lib media mnt proc root run sbin srv sys tmp usr var
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We used the &lt;code&gt;snapshot&lt;/code&gt; subcommand to create a snapshot of the subvolume &lt;em&gt;alpine&lt;/em&gt; with the name &lt;em&gt;tupperware&lt;/em&gt; in the &lt;em&gt;containers&lt;/em&gt; directory. Snapshots are very efficient. They don’t copy the data from the source subvolume making them space efficient and very fast to create. If a snapshot is modified, the original subvolume won’t be affected. We can see this in the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;containers/tupperware/NICK_WAS_HERE
&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;containers/tupperware/
&lt;span class="go"&gt;bin dev etc home lib media mnt NICK_WAS_HERE proc root run sbin srv sys tmp usr var
&lt;/span&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;images/alpine/
&lt;span class="go"&gt;bin dev etc home lib media mnt proc root run sbin srv sys tmp usr var
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this example, we add a file called &lt;em&gt;NICK_WAS_HERE&lt;/em&gt; to the snapshot. Then we prove that it is visible in the snapshot but not in the original &lt;em&gt;alpine subvolume&lt;/em&gt;. More information about the &lt;code&gt;btrfs&lt;/code&gt; command can be found in &lt;a href="https://www.linux.com/learn/how-create-and-manage-btrfs-snapshots-and-rollbacks-linux-part-2"&gt;this post&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing using chroot
&lt;/h3&gt;

&lt;p&gt;Let’s use the &lt;code&gt;chroot&lt;/code&gt; command to run &lt;code&gt;sh&lt;/code&gt; inside the &lt;em&gt;tupperware snapshot&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;chroot &lt;/span&gt;containers/tupperware/ sh
&lt;span class="gp"&gt;/ #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /
&lt;span class="go"&gt;NICK_WAS_HERE dev home media proc run srv tmp var
bin etc lib mnt root sbin sys usr
&lt;/span&gt;&lt;span class="gp"&gt;/ #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apk
&lt;span class="go"&gt;apk-tools 2.10.0, compiled for x86_64.

Installing and removing packages:
  add Add PACKAGEs to 'world' and install (or upgrade) them, while ensuring that all dependencies are met
  del Remove PACKAGEs from 'world' and uninstall them

System maintenance:
  fix Repair package or upgrade it without modifying main dependencies
  update Update repository indexes from all remote repositories
  upgrade Upgrade currently installed packages to match repositories
  cache Download missing PACKAGEs to cache and/or delete unneeded files from cache

Querying information about packages:
  info Give detailed information about PACKAGEs or repositories
  list List packages by PATTERN and other criteria
  dot Generate graphviz graphs
  policy Show repository policy for packages

Repository maintenance:
  index Create repository index file from FILEs
  fetch Download PACKAGEs from global repositories to a local directory
  verify Verify package integrity and signature
  manifest Show checksums of package contents

&lt;/span&gt;&lt;span class="gp"&gt;Use apk &amp;lt;command&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--help&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;command-specific help.
&lt;span class="go"&gt;Use apk --help --verbose for a full command listing.

This apk has coffee making abilities.
&lt;/span&gt;&lt;span class="gp"&gt;/ #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;chroot&lt;/code&gt; is used to change the root directory of a program. In the example above, the &lt;em&gt;/btrfs/container/tupperware&lt;/em&gt; directory becomes the root of the filesystem. We execute &lt;code&gt;apk&lt;/code&gt;, which is only available in &lt;em&gt;alpine&lt;/em&gt;, and then we exit the container.&lt;/p&gt;

&lt;p&gt;Note that we didn’t use namespaces in this “container.” Let’s change that!&lt;/p&gt;

&lt;h3&gt;
  
  
  Using namespaces
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;unshare &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nt"&gt;--uts&lt;/span&gt; &lt;span class="nt"&gt;--ipc&lt;/span&gt; &lt;span class="nt"&gt;--net&lt;/span&gt; &lt;span class="nt"&gt;--pid&lt;/span&gt; &lt;span class="nt"&gt;--fork&lt;/span&gt; bash
&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We use the &lt;code&gt;unshare&lt;/code&gt; command to run a program (&lt;em&gt;bash&lt;/em&gt;) in different &lt;em&gt;mount&lt;/em&gt;, &lt;em&gt;uts&lt;/em&gt;, &lt;em&gt;ipc&lt;/em&gt;, &lt;em&gt;net&lt;/em&gt; and &lt;em&gt;pid&lt;/em&gt; namespaces. We also pass in the &lt;code&gt;--fork&lt;/code&gt; flag to create a new process as a child of the &lt;code&gt;unshare&lt;/code&gt; command. It may seem like nothing happened from the command output, but we’re using namespaces and are somewhat isolated from the global namespace. Let’s change the &lt;em&gt;hostname&lt;/em&gt; to prove that we are in an isolated &lt;em&gt;uts&lt;/em&gt; namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;hostname &lt;/span&gt;tupperware
&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec &lt;/span&gt;bash
&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that after executing &lt;code&gt;bash&lt;/code&gt;, our hostname switched to &lt;em&gt;tupperware&lt;/em&gt;. Running &lt;code&gt;hostname&lt;/code&gt; from another terminal shows that the global namespace still has the same &lt;em&gt;hostname&lt;/em&gt; (&lt;em&gt;desktop-nicolas&lt;/em&gt; in this case).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;from a different terminal
&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/containers$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt;
&lt;span class="go"&gt;desktop-nicolas
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s do some experiments with the &lt;em&gt;pid namespace&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;span class="go"&gt;  PID TTY TIME CMD
24506 pts/26 00:00:00 bash
24551 pts/26 00:00:00 unshare
24552 pts/26 00:00:00 bash
24961 pts/26 00:00:00 ps
28780 pts/26 00:00:00 sudo
28781 pts/26 00:00:00 su
28782 pts/26 00:00:00 bash
&lt;/span&gt;&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pidof unshare
&lt;span class="go"&gt;24551
&lt;/span&gt;&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;pidof unshare&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;bash: kill: (24551) - No such process
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We see a lot more processes than expected. The &lt;em&gt;PIDs&lt;/em&gt; are also those of the main system. What is going on? It turns out that the &lt;em&gt;/proc&lt;/em&gt; of the global namespace is mounted, and the &lt;code&gt;ps&lt;/code&gt; command uses &lt;em&gt;/proc&lt;/em&gt; to get some of its information. (You can verify this by running &lt;code&gt;strace ps&lt;/code&gt;.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Mount proc
&lt;/h3&gt;

&lt;p&gt;Let’s mount &lt;em&gt;/proc&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; proc proc /proc
&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;span class="go"&gt;  PID TTY TIME CMD
    1 pts/26 00:00:00 bash
   30 pts/26 00:00:00 ps
&lt;/span&gt;&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;umount /proc
&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After we mount &lt;em&gt;proc&lt;/em&gt;, &lt;code&gt;ps&lt;/code&gt; only shows the processes running in our container with the correct &lt;em&gt;PIDs&lt;/em&gt;. We unmount &lt;em&gt;/proc&lt;/em&gt; again for now.&lt;/p&gt;

&lt;p&gt;We’ve used &lt;code&gt;mount&lt;/code&gt; before. Let’s go over what it does.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mount&lt;/code&gt; command is used to mount filesystems and usually has the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;mount -t &amp;lt;type&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;device&amp;gt; &amp;lt;directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;From the &lt;a href="https://linux.die.net/man/8/mount"&gt;mount man page&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;this tells the kernel to attach the filesystem found on &lt;code&gt;&amp;lt;device&amp;gt;&lt;/code&gt; (which is of type &lt;code&gt;&amp;lt;type&amp;gt;&lt;/code&gt;) at the directory &lt;code&gt;&amp;lt;directory&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s the argument breakdown for our specific case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-t proc&lt;/code&gt;: The type of filesystem to use is &lt;em&gt;proc&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;proc&lt;/code&gt;: The &lt;em&gt;/proc&lt;/em&gt; filesystem is not attached to a device. Any keyword here would work.

&lt;ul&gt;
&lt;li&gt;Note that in the video Jérôme uses &lt;em&gt;none&lt;/em&gt; instead of &lt;em&gt;proc&lt;/em&gt; for this value. I changed this to be &lt;em&gt;proc&lt;/em&gt; because the &lt;a href="https://linux.die.net/man/8/mount"&gt;mount man page&lt;/a&gt; discourages the use of &lt;em&gt;none&lt;/em&gt; for this (“The customary choice &lt;em&gt;none&lt;/em&gt; is less fortunate: the error message ‘none busy’ from umount can be confusing.“).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/proc&lt;/code&gt;: The directory where we want to mount the &lt;em&gt;proc&lt;/em&gt; filesystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pivot root
&lt;/h3&gt;

&lt;p&gt;Let’s make &lt;em&gt;/btrfs/containers/tupperware&lt;/em&gt; the root of our filesystem by using &lt;code&gt;mount&lt;/code&gt; and &lt;code&gt;pivot_root&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /btrfs/containers/tupperware/oldroot
&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /btrfs/containers/tupperware /btrfs
&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /btrfs/
&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="go"&gt;bin dev etc home lib media mnt NICK_WAS_HERE oldroot proc root run sbin srv sys tmp usr var
&lt;/span&gt;&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pivot_root &lt;span class="nb"&gt;.&lt;/span&gt; oldroot
&lt;span class="gp"&gt;root@tupperware:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /
&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="go"&gt;NICK_WAS_HERE dev home media oldroot root sbin sys usr
bin etc lib mnt proc run srv tmp var
&lt;/span&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;oldroot/
&lt;span class="go"&gt;bin cdrom hello lib media root srv usr
boot core home lib32 mnt run sys var
bt dev initrd.img lib64 opt sbin tes vmlinuz
btrfs etc initrd.img.old lost+found proc snap tmp vmlinuz.old
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s break this down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We create a directory called &lt;em&gt;oldroot&lt;/em&gt; where our current root filesystem will be mounted. As Jérôme explained in the video, to be able to run &lt;code&gt;pivot_root&lt;/code&gt; successfully, you need to be close to the top of the filesystem (&lt;em&gt;/&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;We use &lt;code&gt;mount --bind&lt;/code&gt; to get the container filesystem to &lt;em&gt;/btrfs&lt;/em&gt;. (Jérôme splits this into two steps, and I didn’t understand why. I decided to try it this way to see if it would work and it did). The &lt;code&gt;mount --bind&lt;/code&gt; command is useful to mount a directory somewhere else (in our case we’re mounting &lt;em&gt;/btrfs/containers/tupperware&lt;/em&gt; to &lt;em&gt;/btrfs&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;We go to &lt;em&gt;/btrfs&lt;/em&gt; and run &lt;code&gt;ls&lt;/code&gt; to make sure that our container filesystem is mounted there.&lt;/li&gt;
&lt;li&gt;We execute &lt;code&gt;pivot_root&lt;/code&gt; which switches the current directory (&lt;em&gt;/btrfs&lt;/em&gt;) to be the new root and mounts the current root in &lt;em&gt;oldroot&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;We move to the new root and check that it is mounted correctly by running &lt;code&gt;ls&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We verify that &lt;em&gt;oldroot&lt;/em&gt; has the old root mount point.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : I didn’t understand why we needed to do a &lt;code&gt;pivot_root&lt;/code&gt; instead of doing a bind mount point to &lt;code&gt;/&lt;/code&gt;. &lt;a href="https://yarchive.net/comp/linux/pivot_root.html"&gt;This email by Linus Torvalds himself&lt;/a&gt; helped me understand. In a nutshell, &lt;code&gt;/&lt;/code&gt; points to the &lt;strong&gt;process’ root of the filesystem&lt;/strong&gt;. By doing a bind mount to root (&lt;code&gt;/&lt;/code&gt;), the process would still point to the old version of &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing the mount points
&lt;/h3&gt;

&lt;p&gt;Let’s take a look at our mount points.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; proc proc /proc
&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mount | &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;span class="go"&gt;/dev/sda2 on /oldroot type ext4 (rw,relatime,errors=remount-ro,data=ordered)
/dev/sda2 on /oldroot type ext4 (rw,relatime,errors=remount-ro,data=ordered)
udev on /oldroot/dev type devtmpfs (rw,nosuid,relatime,size=16404692k,nr_inodes=4101173,mode=755)
devpts on /oldroot/dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /oldroot/dev/shm type tmpfs (rw,nosuid,nodev)
mqueue on /oldroot/dev/mqueue type mqueue (rw,relatime)
hugetlbfs on /oldroot/dev/hugepages type hugetlbfs (rw,relatime,pagesize=2M)
tmpfs on /oldroot/run type tmpfs (rw,nosuid,noexec,relatime,size=3286976k,mode=755)
tmpfs on /oldroot/run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
cgmfs on /oldroot/run/cgmanager/fs type tmpfs (rw,relatime,size=100k,mode=755)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We mount &lt;em&gt;/proc&lt;/em&gt; first since &lt;code&gt;mount&lt;/code&gt; relies on it. (You can verify this by running &lt;code&gt;strace mount&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : The mount point list was pretty, big so I piped it to &lt;code&gt;head&lt;/code&gt; to show the first 10 lines.&lt;/p&gt;

&lt;p&gt;Most of these mounts shouldn’t be part of our container so let’s unmount everything and mount &lt;em&gt;/proc&lt;/em&gt; again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;umount &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;span class="go"&gt;umount: can't unmount /oldroot/btrfs: Resource busy
umount: can't unmount /oldroot: Resource busy
umount: can't unmount /oldroot: Resource busy
&lt;/span&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; proc proc /proc
&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mount
&lt;span class="go"&gt;/dev/sda2 on /oldroot type ext4 (rw,relatime,errors=remount-ro,data=ordered)
/dev/sda2 on /oldroot type ext4 (rw,relatime,errors=remount-ro,data=ordered)
/dev/loop0 on /oldroot/btrfs type btrfs (ro,relatime,space_cache,subvolid=5,subvol=/)
/dev/loop0 on / type btrfs (ro,relatime,space_cache,subvolid=258,subvol=/containers/tupperware)
proc on /proc type proc (rw,relatime)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;umount&lt;/code&gt; failed for &lt;em&gt;/oldroot&lt;/em&gt; because the resource was busy. This is why &lt;em&gt;/oldroot&lt;/em&gt; still shows up when we run &lt;code&gt;mount&lt;/code&gt;. Let’s fix that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;umount &lt;span class="nt"&gt;-l&lt;/span&gt; /oldroot
&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mount
&lt;span class="go"&gt;/dev/loop0 on / type btrfs (ro,relatime,space_cache,subvolid=258,subvol=/containers/tupperware)
/dev/loop0 on / type btrfs (ro,relatime,space_cache,subvolid=258,subvol=/containers/tupperware)
proc on /proc type proc (rw,relatime)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-l&lt;/code&gt; flag in the &lt;code&gt;umount&lt;/code&gt; command stands for lazy. According to the &lt;a href="https://linux.die.net/man/8/umount"&gt;umount man page&lt;/a&gt;, this flag will “detach the filesystem from the file hierarchy now, and clean up all references to this filesystem as soon as it is not busy anymore.” As a result, we don’t see any references to &lt;em&gt;/oldroot&lt;/em&gt; when we rerun &lt;code&gt;mount&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Networking
&lt;/h3&gt;

&lt;p&gt;Let’s verify that we don’t have access to the network.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ping 8.8.8.8
&lt;span class="go"&gt;PING 8.8.8.8 (8.8.8.8): 56 data bytes
ping: sendto: Network unreachable
&lt;/span&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ifconfig &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;span class="go"&gt;lo Link encap:Local Loopback
          LOOPBACK MTU:65536 Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Good! We don’t have network access, and we only have the loopback interface. Let’s fix that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : We run the following commands from a separate terminal (not in our container).&lt;/p&gt;

&lt;p&gt;We need the process id of our container (the &lt;em&gt;PID&lt;/em&gt; of &lt;code&gt;unshare&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/home/nmesa#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CPID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pidof unshare&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;root@desktop-nicolas:/home/nmesa#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$CPID&lt;/span&gt;
&lt;span class="go"&gt;24551
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We assign the &lt;em&gt;PID&lt;/em&gt; to the &lt;code&gt;CPID&lt;/code&gt; variable to make it easier to copy/paste commands if you are following along. Let’s create a pair of virtual network interfaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/home/nmesa#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip &lt;span class="nb"&gt;link &lt;/span&gt;add name h&lt;span class="nv"&gt;$CPID&lt;/span&gt; &lt;span class="nb"&gt;type &lt;/span&gt;veth peer name c&lt;span class="nv"&gt;$CPID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ip link add&lt;/code&gt; command creates two interfaces of type &lt;code&gt;veth&lt;/code&gt; (virtual ethernet interface). One with name &lt;em&gt;h24551&lt;/em&gt; and the other one with name &lt;em&gt;c24551&lt;/em&gt;. &lt;em&gt;h&lt;/em&gt; stands for host, &lt;em&gt;c&lt;/em&gt; stands for container and &lt;em&gt;24551&lt;/em&gt; is the &lt;em&gt;PID&lt;/em&gt; of our container.&lt;/p&gt;

&lt;p&gt;Let’s move the &lt;em&gt;c24551&lt;/em&gt; interface to our container (note this command is also executed from the host).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/home/nmesa#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;c&lt;span class="nv"&gt;$CPID&lt;/span&gt; netns &lt;span class="nv"&gt;$CPID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ip link set&lt;/code&gt; command sets configuration attributes to interfaces. In this case, it sets the &lt;em&gt;netns&lt;/em&gt; (network namespace) to be the same as the process id stored in &lt;em&gt;$CPID&lt;/em&gt; (&lt;em&gt;24551&lt;/em&gt; in our case).&lt;/p&gt;

&lt;p&gt;Let’s get back to our container terminal to verify that it got the new interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ifconfig &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;span class="go"&gt;c24551 Link encap:Ethernet HWaddr 96:18:F1:61:12:A2
          BROADCAST MULTICAST MTU:1500 Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

lo Link encap:Local Loopback
          LOOPBACK MTU:65536 Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Great! We have the interface inside our container! Let’s get back to our host terminal and attach the &lt;em&gt;h24551&lt;/em&gt; interface to the docker bridge (&lt;em&gt;docker0&lt;/em&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@desktop-nicolas:/home/nmesa#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;h&lt;span class="nv"&gt;$CPID&lt;/span&gt; master docker0 up
&lt;span class="gp"&gt;root@desktop-nicolas:/home/nmesa#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ifconfig docker0
&lt;span class="go"&gt;docker0 Link encap:Ethernet HWaddr 02:42:ac:03:c8:91
          inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe03:c891/64 Scope:Link
          UP BROADCAST MULTICAST MTU:1500 Metric:1
          RX packets:77485 errors:0 dropped:0 overruns:0 frame:0
          TX packets:77624 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:6199951 (6.1 MB) TX bytes:164681776 (164.6 MB)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We use the &lt;code&gt;ip link set&lt;/code&gt; command to attach the interface to the &lt;em&gt;docker0&lt;/em&gt; bridge. We also grab the ip address of our &lt;em&gt;docker0&lt;/em&gt; interface: &lt;em&gt;172.17.0.1&lt;/em&gt; (write it down as you’ll need this later).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : Jérôme didn’t do this last step, and I suspect this is why the demo didn’t work as expected for him.&lt;/p&gt;

&lt;p&gt;Let’s go back to our container terminal and configure the network interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;lo up
&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;c24551 name eth0 up
&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip addr add 172.17.42.3/16 dev eth0
&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip route add default via 172.17.0.1
&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ifconfig
&lt;span class="go"&gt;eth0 Link encap:Ethernet HWaddr 96:18:F1:61:12:A2
          inet addr:172.17.42.3 Bcast:0.0.0.0 Mask:255.255.0.0
          inet6 addr: fe80::9418:f1ff:fe61:12a2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
          RX packets:35 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:3789 (3.7 KiB) TX bytes:936 (936.0 B)

lo Link encap:Local Loopback
          inet addr:127.0.0.1 Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING MTU:65536 Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s break this down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We bring up the loopback interface.&lt;/li&gt;
&lt;li&gt;We bring up the &lt;em&gt;c24551&lt;/em&gt; interface and rename it to &lt;em&gt;eth0&lt;/em&gt;. Note that this command can’t be copied and pasted since your interface probably has a different name.&lt;/li&gt;
&lt;li&gt;We assign the ip address of &lt;em&gt;172.17.42.3&lt;/em&gt; to our &lt;em&gt;eth0&lt;/em&gt; interface. Note that this ip address has to be within the range that we got back from the &lt;em&gt;docker0&lt;/em&gt; interface (172.17.0.0/16 in our case).&lt;/li&gt;
&lt;li&gt;We set the default gateway of our container to be &lt;em&gt;172.17.0.1&lt;/em&gt; (this should be the ip address that we got from &lt;em&gt;docker0&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;We run a quick &lt;code&gt;ifconfig&lt;/code&gt; to make sure everything is setup correctly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, the moment of truth. Let’s ping &lt;em&gt;8.8.8.8&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 8.8.8.8
&lt;span class="go"&gt;PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=121 time=11.045 ms
64 bytes from 8.8.8.8: seq=1 ttl=121 time=10.981 ms
64 bytes from 8.8.8.8: seq=2 ttl=121 time=10.508 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 10.508/10.844/11.045 ms
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our container has network connectivity!&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s finish the job
&lt;/h3&gt;

&lt;p&gt;As Jérôme noted in the video, we are still running &lt;em&gt;bash&lt;/em&gt; inside the container, but the &lt;em&gt;alpine&lt;/em&gt; image doesn’t have &lt;em&gt;bash&lt;/em&gt;. Up until this point, we’ve been doing the container runtime’s job. To finish the container handoff, we run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@tupperware:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec chroot&lt;/span&gt; / sh
&lt;span class="gp"&gt;/ #&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;exec&lt;/code&gt; command is a built-in utility in &lt;em&gt;bash&lt;/em&gt; (who knew?). It replaces the shell with the command (&lt;code&gt;chroot&lt;/code&gt; in our case) without starting a new process. Once this command is executed, we’re officially in a container. Let’s run a few commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;/ #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apk
&lt;span class="go"&gt;apk-tools 2.10.0, compiled for x86_64.

Installing and removing packages:
  add Add PACKAGEs to 'world' and install (or upgrade) them, while ensuring that all dependencies are met
  del Remove PACKAGEs from 'world' and uninstall them

System maintenance:
  fix Repair package or upgrade it without modifying main dependencies
  update Update repository indexes from all remote repositories
  upgrade Upgrade currently installed packages to match repositories
  cache Download missing PACKAGEs to cache and/or delete unneeded files from cache

Querying information about packages:
  info Give detailed information about PACKAGEs or repositories
  list List packages by PATTERN and other criteria
  dot Generate graphviz graphs
  policy Show repository policy for packages

Repository maintenance:
  index Create repository index file from FILEs
  fetch Download PACKAGEs from global repositories to a local directory
  verify Verify package integrity and signature
  manifest Show checksums of package contents

&lt;/span&gt;&lt;span class="gp"&gt;Use apk &amp;lt;command&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--help&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;command-specific help.
&lt;span class="go"&gt;Use apk --help --verbose for a full command listing.

This apk has coffee making abilities.
&lt;/span&gt;&lt;span class="gp"&gt;/ #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="go"&gt;NICK_WAS_HERE dev home media oldroot root sbin sys usr
bin etc lib mnt proc run srv tmp var
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;

&lt;p&gt;Here are some cleanup steps commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;/ #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="gp"&gt;root@desktop-nicolas:/btrfs#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /
&lt;span class="gp"&gt;root@desktop-nicolas:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;umount /btrfs
&lt;span class="gp"&gt;root@desktop-nicolas:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="go"&gt;exit
&lt;/span&gt;&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/containers$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; disk.img
&lt;span class="gp"&gt;nmesa@desktop-nicolas:~/demos/containers$&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : I didn’t have to delete my &lt;em&gt;veth&lt;/em&gt; interfaces. I’m not sure if they are automatically removed once the network namespace dies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A lot goes on under the hood to provision containers! This was only covering the namespaces part. There’s also &lt;em&gt;cgroups&lt;/em&gt;, &lt;em&gt;capabilities&lt;/em&gt;, &lt;em&gt;devices&lt;/em&gt;, etc. As Jérôme suggests, don’t create your own container runtime and use &lt;a href="https://www.docker.com/"&gt;docker&lt;/a&gt; instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links / Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.nicolasmesa.co/posts/2018/08/container-creation-using-namespaces-and-bash/"&gt;Original Post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://btrfs.wiki.kernel.org/index.php/Main_Page"&gt;BTRFS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://btrfs.wiki.kernel.org/index.php/Getting_started#Basic_Filesystem_Commands"&gt;Getting started with BTRFS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linux.com/learn/how-manage-btrfs-storage-pools-subvolumes-and-snapshots-linux-part-1"&gt;BTRFS tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linux.die.net/man/8/mount"&gt;mount man page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linux.die.net/man/8/umount"&gt;umount man page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/"&gt;docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://containersummit.io/events/nyc-2016/videos/building-containers-in-pure-bash-and-c"&gt;Building containers in pure bash and C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lwn.net/Articles/531114/"&gt;Namespaces in operation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>containers</category>
      <category>namespaces</category>
      <category>linux</category>
    </item>
    <item>
      <title>Var vs Let vs Const</title>
      <dc:creator>Nicolas Mesa</dc:creator>
      <pubDate>Sat, 18 Aug 2018 21:06:09 +0000</pubDate>
      <link>https://dev.to/nicolasmesa/var-vs-let-vs-const-a2</link>
      <guid>https://dev.to/nicolasmesa/var-vs-let-vs-const-a2</guid>
      <description>

&lt;p&gt;Cross-posted from my personal blog &lt;a href="https://blog.nicolasmesa.co"&gt;https://blog.nicolasmesa.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hi there!&lt;/p&gt;

&lt;p&gt;In this post, we’re going to talk about &lt;code&gt;javascript&lt;/code&gt;. We’ll start by looking at some examples of &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; variable declarations and their properties. Then we’re going to go through my recommendations of when to use each one.&lt;/p&gt;

&lt;h2&gt;var&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;var&lt;/code&gt; is the original way to do variable declaration in javascript. Here’s an example of how you can declare a variable using &lt;code&gt;var&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;var is function-scoped&lt;/h3&gt;

&lt;p&gt;Variables defined using &lt;code&gt;var&lt;/code&gt; are function scoped. This means that the variable is available anywhere within its enclosing function. For example:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;functionScopedExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: 10 15 undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are a few things happening in this example. First, &lt;code&gt;a&lt;/code&gt; is available everywhere in this function (like in most programming languages). Second, &lt;code&gt;b&lt;/code&gt; is also available everywhere even though we declared and assigned it inside an &lt;code&gt;if&lt;/code&gt; block. Third, &lt;code&gt;c&lt;/code&gt; is also available everywhere in the function (even though our execution path doesn’t go into the &lt;code&gt;else&lt;/code&gt; statement)! One thing to note here is that the value of &lt;code&gt;c&lt;/code&gt; is &lt;code&gt;undefined&lt;/code&gt; (since the code in the &lt;code&gt;else&lt;/code&gt; statement is not executed), but &lt;code&gt;c&lt;/code&gt; was still declared. To understand why this happened, we’ll need to learn about Variable Hoisting.&lt;/p&gt;

&lt;p&gt;Here is another example of &lt;em&gt;function-scoped&lt;/em&gt; variables:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;functionScopedExample2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;innerFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: 10&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;innerFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: 10&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught ReferenceError: b is not defined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This example shows that &lt;code&gt;a&lt;/code&gt; is available in its enclosing function (&lt;code&gt;functionScopedExample2&lt;/code&gt;). This includes other functions defined within it (for example the &lt;code&gt;innerFunction&lt;/code&gt; function). &lt;code&gt;b&lt;/code&gt;, however, can only be referenced from its enclosing function (&lt;code&gt;innerFunction&lt;/code&gt;) and not from outside.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Function-scoped&lt;/em&gt; declarations can have weird effects:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;functionScopedExample3&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myNumberArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;myNumberArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// wait until all timeouts have executed.&lt;/span&gt;
    &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myNumberArray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The example above looks pretty weird. Most programmers would expect &lt;code&gt;myNumberArray&lt;/code&gt; to have numbers from 0 - 9. Instead the array contains the number &lt;code&gt;10&lt;/code&gt; 10 times! This happens because the variable &lt;code&gt;i&lt;/code&gt; is in scope for the whole function (&lt;code&gt;functionScopedExample3&lt;/code&gt;). By the time the functions in the &lt;code&gt;setTimeout&lt;/code&gt; execute, &lt;code&gt;i&lt;/code&gt; already has a value of &lt;code&gt;10&lt;/code&gt;. One way to fix this issue is to create another function that receives &lt;code&gt;i&lt;/code&gt; as an argument and executes the &lt;code&gt;setTimeout&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fixedFunctionScopedExample3&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myNumberArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="c1"&gt;// a new scope is created every time this function is called.&lt;/span&gt;
    &lt;span class="c1"&gt;// As a result, newI is isolated.&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;executeTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;myNumberArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;executeTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// wait until all timeouts have executed.&lt;/span&gt;
    &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myNumberArray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Later, we’ll see how to solve this problem by using &lt;code&gt;let&lt;/code&gt; instead of &lt;code&gt;var&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;Variable hoisting&lt;/h3&gt;

&lt;p&gt;When we define a variable using &lt;code&gt;var&lt;/code&gt;, the variable declaration (not the assignment) is &lt;em&gt;hoisted&lt;/em&gt; up to the beginning of the function. After the &lt;em&gt;hoisting&lt;/em&gt; process, &lt;code&gt;functionScopedExample&lt;/code&gt; (defined above) would end up looking like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;varHoistingExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// variables are hoisted to the top and all of them start&lt;/span&gt;
    &lt;span class="c1"&gt;// with the value of undefined.&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// a gets its value here.&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// b gets its value here.&lt;/span&gt;
        &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// c never gets its value so it remains undefined.&lt;/span&gt;
        &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: 10 15 undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Hoisting&lt;/em&gt; can cause a lot of confusion. Take a look a the following example:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;weirdHoisting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'yellow'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'My favorite color is'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: My favorite color is yellow&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wait, what? How did that work? Remember, first the variables defined with &lt;code&gt;var&lt;/code&gt; are &lt;em&gt;hoisted&lt;/em&gt; and then the function code is executed. In this example, the code after variable &lt;em&gt;hoisting&lt;/em&gt; would look something like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;weirdHoisting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// variable declaration is hoisted to the top of its enclosing function.&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'yellow'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'My favorite color is'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: My favorite color is yellow&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Variable &lt;code&gt;color&lt;/code&gt;’s declaration is &lt;em&gt;hoisted&lt;/em&gt; and thus prevents any reference errors.&lt;/p&gt;

&lt;p&gt;Named function declarations are &lt;em&gt;hoisted&lt;/em&gt; as well (there are some &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function#Conditionally_created_functions"&gt;edge-cases if you’re doing conditionals&lt;/a&gt;). Here’s an example:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;functionHoisting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hoisted&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// logs: I am hoisted&lt;/span&gt;
    &lt;span class="nx"&gt;notHoisted&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught TypeError: notHoisted is not a function&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;notHoisted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'This will not work'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;hoisted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'I am hoisted'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this example, we see that the &lt;em&gt;hoisted&lt;/em&gt; function can be called before it is declared. The &lt;code&gt;notHoisted&lt;/code&gt; variable, however, hasn’t been assigned the &lt;code&gt;function&lt;/code&gt; by the time it is called. Note that the function doesn’t fail because the &lt;code&gt;notHoisted&lt;/code&gt; name hasn’t been declared, but because it doesn’t point to a function (yet). After the hoisting process, this function would end up looking something like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;functionHoisting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// variable and function declaration are hoisted.&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;notHoisted&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;hoisted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'I am hoisted'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;hoisted&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// logs: I am hoisted&lt;/span&gt;
    &lt;span class="nx"&gt;notHoisted&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught TypeError: notHoisted is not a function&lt;/span&gt;

    &lt;span class="c1"&gt;// function would be assigned here but we never reach this.&lt;/span&gt;
    &lt;span class="nx"&gt;notHoisted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'This will not work'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;let and const&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;let&lt;/code&gt; is a newer way to define variables in javascript. Here’s an example of a variable definition using &lt;code&gt;let&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;const&lt;/code&gt; is a way to define constants in javascript. Here’s an example of a constant defined using &lt;code&gt;const&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myConstant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;let and const are block-scoped&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; are both block-scoped. This means that the variable/constant is available anywhere in the block &lt;strong&gt;after it has been declared&lt;/strong&gt;. &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt; definitions are &lt;strong&gt;NOT&lt;/strong&gt; &lt;em&gt;hoisted&lt;/em&gt;. Let’s go through a few examples:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;blockScopedExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: 10&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught ReferenceError: b is not defined&lt;/span&gt;

    &lt;span class="c1"&gt;// we would never reach this since the code fails in the line before&lt;/span&gt;
    &lt;span class="c1"&gt;// but this would be the output if it had been executed&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught ReferenceError: c is not defined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This example shows that &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt; are block-scoped. This is the reason why they’re not available outside of the &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt; block. &lt;code&gt;a&lt;/code&gt; was defined at the beginning of the function, making it available anywhere inside the function &lt;strong&gt;block&lt;/strong&gt;. Declaring something with &lt;code&gt;let&lt;/code&gt; at the beginning of a function is analogous to defining it with &lt;code&gt;var&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Remember the example where our array ended up with the same values? Well, this problem is easily solvable by using &lt;code&gt;let&lt;/code&gt; instead of &lt;code&gt;var&lt;/code&gt; to define &lt;code&gt;i&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;blockScopedExample2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myNumberArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="c1"&gt;// let makes the variable i block-scoped&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;myNumberArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// wait until all timeouts have executed.&lt;/span&gt;
    &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myNumberArray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since the variable &lt;code&gt;i&lt;/code&gt; is block-scoped instead of function-scoped, its value remains the same for the whole block execution.&lt;/p&gt;

&lt;p&gt;Here’s another example showing that variables defined with &lt;code&gt;let&lt;/code&gt; are not &lt;em&gt;hoisted&lt;/em&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;noHoisting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'yellow'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught ReferenceError: color is not defined&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// this is never reached.&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'My favorite color is'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The output of this function is what most programmers coming from other languages expect (having to declare a variable before using it).&lt;/p&gt;

&lt;p&gt;So far, every example (except for &lt;code&gt;blockScopedExample2&lt;/code&gt;) we’ve covered using &lt;code&gt;let&lt;/code&gt; would have the same outcome if we had used &lt;code&gt;const&lt;/code&gt; instead. So, what does &lt;code&gt;const&lt;/code&gt; give us?&lt;/p&gt;

&lt;h3&gt;Constants&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;const&lt;/code&gt; is how constants can be declared in javascript. After a constant has been defined using &lt;code&gt;const&lt;/code&gt;, the constant can’t have another value assigned. Here’s an example:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cantReassignConstants&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myConstant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;myConstant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught TypeError: Assignment to constant variable&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Constants defined with &lt;code&gt;const&lt;/code&gt; also have to be assigned at declaration time (unlike &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;var&lt;/code&gt;). For example, the following piece of code would fail during parsing (not at run-time).&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;constantsCantBeDeclaredAndNotDefined&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myConstant&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;myConstant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you try to define this function, you would see an error like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Uncaught SyntaxError: Missing initializer in const declaration
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since this error occurs during parsing, the declaration of the function fails and we can’t even call it.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;constantsCantBeDeclaredAndNotDefined&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught ReferenceError: constantsCantBeDeclaredAndNotDefined is not defined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;One thing to note about constants defined with &lt;code&gt;const&lt;/code&gt; is that only the assignment is constant. The object assigned to a constant doesn’t become immutable. For example, the following code runs with no errors:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;constDoesntMakeObjectsImmutable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myObjectConstant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;myKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'myValue'&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;myObjectConstant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'something else'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'myObjectConstant.myKey ='&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myObjectConstant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: myObjectConstant.myKey = something else&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;Object.freeze()&lt;/h4&gt;

&lt;p&gt;If you want to make the object immutable, you can use &lt;code&gt;Object.freeze()&lt;/code&gt; before assigning the object:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;freezingObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;myKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'This value cannot be changed'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'something else'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'myFrozenObject.myKey = '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: myFrozenObject.myKey = This value cannot be changed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Even though the value of &lt;code&gt;myKey&lt;/code&gt; didn’t change, the assignment didn’t fail either (it failed silently). If you want it to fail, use the &lt;code&gt;'use strict;'&lt;/code&gt; at the beginning of the function like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;freezingObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'use strict'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;myKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'This value cannot be changed'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'something else'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught TypeError: Cannot assign to read only property 'myKey' of object '#&amp;lt;Object&amp;gt;'&lt;/span&gt;

    &lt;span class="c1"&gt;// never executed&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'myFrozenObject.myKey = '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Object.freeze&lt;/code&gt; will only freeze the &lt;code&gt;object&lt;/code&gt; that we pass as an argument. If the &lt;code&gt;object&lt;/code&gt; contains references to other objects, those can still be modified unless we freeze them as well. For example:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;objectFreezeIsShallow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;reassignable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reassign me'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;key2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;notReassignable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'This value cannot change'&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reassignable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'reassigned'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notReassignable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'this will not work'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'myFrozenObject.key1.reassignable ='&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reassignable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: myFrozenObject.key1.reassignable = reassigned&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'myFrozenObject.key2.notReassignable ='&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myFrozenObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notReassignable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// logs: myFrozenObject.key2.notReassignable = This value cannot change&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this case, neither &lt;code&gt;key1&lt;/code&gt; or &lt;code&gt;key2&lt;/code&gt; can be reassigned since they’re frozen. The inner object of &lt;code&gt;key1&lt;/code&gt; however, is not frozen and the &lt;code&gt;reassignable&lt;/code&gt; key is set to a different value. Note that the &lt;code&gt;notReassignable&lt;/code&gt; key didn’t have its value reassigned since the object was frozen.&lt;/p&gt;

&lt;h2&gt;Recommendations&lt;/h2&gt;

&lt;p&gt;So, which one(s) should we use and why?&lt;/p&gt;

&lt;p&gt;There are lots of reasons to use one over the other, so I divide this into a section per reason. Note that these are my preferences and it’s perfectly fine for other programmers to think differently :)&lt;/p&gt;

&lt;h4&gt;Never use the three of them in the same project&lt;/h4&gt;

&lt;p&gt;Decide which ones you want to use and stick to those. Using all three of them will be confusing. It will be difficult to know which one to pick and the code will be harder to understand. Be nice to the future readers of your code (including yourself).&lt;/p&gt;

&lt;h4&gt;Prefer consistency&lt;/h4&gt;

&lt;p&gt;If you’re working on an old project that is using &lt;code&gt;var&lt;/code&gt;, keep using &lt;code&gt;var&lt;/code&gt;. This will keep the project consistent.&lt;/p&gt;

&lt;h4&gt;Put variable declarations at the top if using var&lt;/h4&gt;

&lt;p&gt;If you’re using &lt;code&gt;var&lt;/code&gt;, place all variable declarations at the top of the function. This will help you see which variables are available in the function and there won’t be any &lt;em&gt;hoisting&lt;/em&gt; surprises.&lt;/p&gt;

&lt;h4&gt;Consider older browser support&lt;/h4&gt;

&lt;p&gt;If your code needs to support older browsers that don’t have &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt;, consider using &lt;code&gt;var&lt;/code&gt; instead. Alternatively, use a transpiler that converts all &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; declarations to &lt;code&gt;var&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;Prefer let over var&lt;/h4&gt;

&lt;p&gt;If you’re starting a new project, I would encourage you to use &lt;code&gt;let&lt;/code&gt; over &lt;code&gt;var&lt;/code&gt;. &lt;code&gt;let&lt;/code&gt; is more predictable, especially for developers coming from a different language.&lt;/p&gt;

&lt;h4&gt;Prefer const over let when possible&lt;/h4&gt;

&lt;p&gt;I am a firm believer that everything should be a constant except for very special cases in loops or things like that (in those cases, fall-back to &lt;code&gt;let&lt;/code&gt;). I’ll probably write another post on why using &lt;code&gt;const&lt;/code&gt; (&lt;code&gt;final&lt;/code&gt; in Java) is a good choice, but the gist is:&lt;/p&gt;

&lt;h5&gt;Debugging&lt;/h5&gt;

&lt;p&gt;It will ease debugging. For instance, consider the following code:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useConstWhenPossible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myOtherObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myOtherObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getMyObject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// 100 lines of code&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="nx"&gt;myObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// error: Uncaught TypeError: Cannot read property 'doSomething' of undefined&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// 100 lines of code&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When you see the error, you go to the constant declaration. You can immediately tell that &lt;code&gt;myOtherObject.getMyObject()&lt;/code&gt; returned &lt;code&gt;undefined&lt;/code&gt;. There is no need to look through the other 100 lines of code to find if &lt;code&gt;myObject&lt;/code&gt; ever gets reassigned.&lt;/p&gt;

&lt;h5&gt;Variable naming&lt;/h5&gt;

&lt;p&gt;You will have to come up with good names for your constants because you won’t be able to reuse them. This will make your code easier to read and more self-documenting.&lt;/p&gt;

&lt;h5&gt;Helps prevent bugs&lt;/h5&gt;

&lt;p&gt;Another developer (or maybe even you) won’t have a chance to define an existing variable and break the whole function.&lt;/p&gt;

&lt;h4&gt;Use named functions&lt;/h4&gt;

&lt;p&gt;This will save you a lot of headaches, especially when moving code around. You won’t need to make sure that that your function calls are after the function declarations and everything will work consistently.&lt;/p&gt;


</description>
      <category>javascript</category>
      <category>bestpractices</category>
    </item>
    <item>
      <title>What Happens When You Type a Url in Your Browser and Press Enter</title>
      <dc:creator>Nicolas Mesa</dc:creator>
      <pubDate>Fri, 10 Aug 2018 05:24:55 +0000</pubDate>
      <link>https://dev.to/nicolasmesa/what-happens-when-you-type-a-url-in-your-browser-and-press-enter-1iif</link>
      <guid>https://dev.to/nicolasmesa/what-happens-when-you-type-a-url-in-your-browser-and-press-enter-1iif</guid>
      <description>&lt;p&gt;Cross-posted from my personal blog &lt;a href="https://blog.nicolasmesa.co"&gt;https://blog.nicolasmesa.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; Hello! This is my first blog post! I’m super excited to share it with the world but should also warn you that it’s a bit long and repetitive. Hopefully, I’ll become a better writer as I blog more. I hope you enjoy it :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I’ve heard this question many times during my career and want to try to answer it. I’m going to dive deep into the networking part of the question since this is the part that I find the most interesting.&lt;/p&gt;

&lt;p&gt;A lot of stuff happens under the hood in the network to get an HTTP request from the browser to the server and then an HTTP response from the server back to the browser. To be able to explain what happens, I’m going to make some assumptions about the network setup and the status of the network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assumptions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Network status
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Our computer is connected to the network via Ethernet.&lt;/li&gt;
&lt;li&gt;Our computer already has an IP address (more on what the IP address is later).&lt;/li&gt;
&lt;li&gt;Our computer sits behind a NAT (this is the case in many home networks).&lt;/li&gt;
&lt;li&gt;Our ARP cache is clear.&lt;/li&gt;
&lt;li&gt;Our DNS cache is clear.&lt;/li&gt;
&lt;li&gt;Our router’s ARP cache contains an entry for its default gateway.&lt;/li&gt;
&lt;li&gt;Our network is &lt;code&gt;192.168.0.0/24&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The URL we’re going to use is &lt;code&gt;http://www.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The DNS server’s cache has an entry for &lt;code&gt;www.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We’re going to ignore TCP sequence numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Our computer (computer making the HTTP request)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;IP Address: &lt;code&gt;192.168.0.10&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Default gateway: &lt;code&gt;192.168.0.1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;DNS Server: &lt;code&gt;8.8.8.8&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;MAC Address: &lt;code&gt;AA:AA:AA:AA:AA:AA&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;TCP source port: &lt;code&gt;9999&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;DNS source port: &lt;code&gt;3333&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Our router / NAT
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Internal IP Address: &lt;code&gt;192.168.0.1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;External IP address: &lt;code&gt;51.0.0.20&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;External TCP source port: &lt;code&gt;15000&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;External DNS source port: &lt;code&gt;10000&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;External net mask: &lt;code&gt;255.255.255.0&lt;/code&gt; (or &lt;code&gt;/24&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Internal MAC address: &lt;code&gt;BB:BB:BB:BB:BB:BB&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;External MAC address: &lt;code&gt;CC:CC:CC:CC:CC:CC&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Default gateway: &lt;code&gt;51.0.0.1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Default gateway’s MAC address: &lt;code&gt;DD:DD:DD:DD:DD:DD&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt; server
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The IP address of &lt;code&gt;www.example.com&lt;/code&gt; is &lt;code&gt;93.184.216.34&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step by step
&lt;/h2&gt;

&lt;p&gt;To get this process started we type the URL &lt;code&gt;http://www.example.com&lt;/code&gt; in the web browser and press enter. This will instruct our browser to create an HTTP request to send to &lt;code&gt;www.example.com&lt;/code&gt;. The HTTP request will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET / HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;HTTP request to &lt;code&gt;www.example.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our computer will now try to connect to &lt;code&gt;www.example.com&lt;/code&gt; in TCP port &lt;code&gt;80&lt;/code&gt; (the default HTTP port). First, it needs to create a TCP &lt;code&gt;SYN&lt;/code&gt; segment to initiate the TCP connection. The &lt;code&gt;SYN&lt;/code&gt; segment contains information to establish the connection including a random source port (&lt;code&gt;9999&lt;/code&gt; from our assumptions), destination port (&lt;code&gt;80&lt;/code&gt;) and a flag (&lt;code&gt;SYN&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This TCP segment is then encapsulated in an IP packet that contains the source IP (&lt;code&gt;192.168.0.10&lt;/code&gt;) and the destination IP. For the destination IP, our computer goes to its DNS cache and looks for an entry containing &lt;code&gt;www.example.com&lt;/code&gt;. Since its cache is empty, the creation of the IP packet needs to wait until we can get the IP address of &lt;code&gt;www.example.com&lt;/code&gt;. So far our incomplete IP packet looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP[
    SourceIp=192.168.0.10,
    DestIp=????,
    TCP[
        SourcePort=9999,
        DestPort=80,
        Flags=[SYN]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Incomplete SYN IP packet (note the &lt;code&gt;????&lt;/code&gt; in the &lt;code&gt;DestIP&lt;/code&gt; field).&lt;/p&gt;

&lt;p&gt;To get the IP address of &lt;code&gt;www.example.com&lt;/code&gt;, we need to use a service called DNS. DNS stands for Domain Name System and is the system responsible for translating human-readable names (such as &lt;code&gt;www.example.com&lt;/code&gt;) into IP addresses. Our computer creates a DNS request that includes the type of request (&lt;code&gt;A&lt;/code&gt;) and the domain name to resolve (&lt;code&gt;www.example.com&lt;/code&gt;). This DNS request is then encapsulated in a UDP datagram whose header contains a random source port (&lt;code&gt;3333&lt;/code&gt; from our assumptions) and the destination port (&lt;code&gt;53&lt;/code&gt; is DNS’s well-known port). This datagram is then placed inside an IP packet whose header has the source IP address (&lt;code&gt;192.168.0.10&lt;/code&gt;) and the destination IP address (&lt;code&gt;8.8.8.8&lt;/code&gt;). Note that the DNS server was configured beforehand in our computer so we already know what its IP address is.&lt;/p&gt;

&lt;p&gt;We now want to send this IP packet but our computer doesn’t know where to send it. The computer looks at its route table to see which route matches the &lt;code&gt;8.8.8.8&lt;/code&gt; IP address. The route table looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destination Netmask Gateway Interface
0.0.0.0 0.0.0.0 192.168.0.1 eth0
192.168.0.0 255.255.255.0 0.0.0.0 eth0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Route table of our computer.&lt;/p&gt;

&lt;p&gt;Our computer uses the &lt;a href="https://en.wikipedia.org/wiki/Longest_prefix_match"&gt;longest prefix match&lt;/a&gt; to select who to send the packet to. In this case, it selects the first route which is our default gateway (&lt;code&gt;192.168.0.1&lt;/code&gt;). This means that the IP packet will be sent to our router and the router will take care of forwarding it to the next hop (which is hopefully closer to the DNS server). The routers in the path will keep forwarding the packet based on their routing tables until it reaches the DNS server (&lt;code&gt;8.8.8.8&lt;/code&gt;). This process happens every time our computer needs to send an IP packet and, in our case, it will always choose to send the packet to our default gateway (&lt;code&gt;192.168.0.1&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Now that the IP packet is ready, it is wrapped in an Ethernet frame. The Ethernet header contains the source MAC address (&lt;code&gt;AA:AA:AA:AA:AA:AA&lt;/code&gt;) and the destination MAC address (this would be the router’s MAC address in this case). To get the router’s MAC address, our computer looks in its ARP table to see if it has an entry to convert the router’s IP address (&lt;code&gt;192.168.0.1&lt;/code&gt;) to the router’s MAC address. Since the ARP cache is empty, we need to find out what is the MAC address before we can send the IP packet. This is how our incomplete Ethernet frame looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=AA:AA:AA:AA:AA:AA,
    DestMac=????,
    IP[
        SourceIp=192.168.0.10,
        DestIp=8.8.8.8,
        UDP[
            SourcePort=3333,
            DestPort=53,
            DNS[
                Query=A,
                Domain=www.example.com
            ]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Incomplete Ethernet frame for the DNS query (note the &lt;code&gt;????&lt;/code&gt; in the &lt;code&gt;DestMac&lt;/code&gt; field).&lt;/p&gt;

&lt;p&gt;To convert IP addresses to MAC addresses, the ARP protocol is used. ARP stands for Address Resolution Protocol. The ARP packet contains a question asking &lt;code&gt;who-has 192.168.0.1 tell 192.168.0.10&lt;/code&gt; along with the source MAC address (&lt;code&gt;AA:AA:AA:AA:AA:AA&lt;/code&gt;), the destination MAC address (&lt;code&gt;FF:FF:FF:FF:FF:FF&lt;/code&gt; which is the broadcast address), the source IP address (&lt;code&gt;192.168.0.10&lt;/code&gt;), and the destination IP (&lt;code&gt;192.168.0.1&lt;/code&gt; which is the IP we’re asking about). The ARP packet is then wrapped in an Ethernet frame containing the source MAC address (&lt;code&gt;AA:AA:AA:AA:AA:AA&lt;/code&gt;) and for the destination MAC address, the broadcast address is used (&lt;code&gt;FF:FF:FF:FF:FF:FF&lt;/code&gt;). The frame is sent over our private network and looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=AA:AA:AA:AA:AA:AA,
    DestMac=FF:FF:FF:FF:FF:FF,
    ARP[
        Type=Request,
        SourceIp=192.168.0.10,
        DestIp=192.168.0.1,
        SourceMac=AA:AA:AA:AA:AA:AA,
        DestMac=FF:FF:FF:FF:FF:FF
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;ARP packet to find out our router’s MAC address.&lt;/p&gt;

&lt;p&gt;There is something worth noting at this point. This is the first interaction that our computer has had with the network!&lt;/p&gt;

&lt;p&gt;Since the broadcast MAC address (&lt;code&gt;FF:FF:FF:FF:FF:FF&lt;/code&gt;) was used, this frame will reach every node on our private network. Every node (except for our router) will end up discarding the packet since the destination IP address (&lt;code&gt;192.168.0.1&lt;/code&gt;) is not their IP.&lt;/p&gt;

&lt;p&gt;When our router receives this packet, it will see that &lt;code&gt;192.168.0.10&lt;/code&gt; is asking for its MAC address. It can also see in the ARP packet the source MAC address of our computer. The router saves this information in its ARP table (&lt;code&gt;192.168.0.10 -&amp;gt; AA:AA:AA:AA:AA:AA&lt;/code&gt;) and creates an ARP reply saying &lt;code&gt;192.168.0.1 is-at BB:BB:BB:BB:BB:BB&lt;/code&gt;. This ARP reply is then wrapped in an Ethernet frame with the source MAC address (&lt;code&gt;BB:BB:BB:BB:BB:BB&lt;/code&gt;) and destination MAC address (&lt;code&gt;AA:AA:AA:AA:AA:AA&lt;/code&gt;). The Ethernet frame is now sent over the network. One thing to note here is that the destination MAC address is no longer the broadcast MAC address so only our computer will process it. From now on, our router will be able to convert our computer’s IP address (&lt;code&gt;192.168.0.10&lt;/code&gt;) to its MAC address (&lt;code&gt;AA:AA:AA:AA:AA:AA&lt;/code&gt;) by referring to its ARP cache. The Ethernet frame containing this reply looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=BB:BB:BB:BB:BB:BB,
    DestMac=AA:AA:AA:AA:AA:AA,
    ARP[
        Type=Reply,
        SourceIp=192.168.0.1,
        DestIp=192.168.0.10,
        SourceMac=BB:BB:BB:BB:BB:BB,
        DestMac=AA:AA:AA:AA:AA:AA
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;ARP reply where our router tells its MAC address to our computer.&lt;/p&gt;

&lt;p&gt;Our computer receives the Ethernet frame, sees the ARP reply and saves the MAC address of our router in its ARP table (&lt;code&gt;192.168.0.1 -&amp;gt; BB:BB:BB:BB:BB:BB&lt;/code&gt;). From now on, any time our computer needs to convert our router’s IP address (&lt;code&gt;192.168.0.1&lt;/code&gt;) to its MAC address (&lt;code&gt;BB:BB:BB:BB:BB:BB&lt;/code&gt;), it simply needs to refer to its ARP cache. We’re making progress! We now have the MAC address of our router, which we need to send the IP packet with the DNS query to get the IP of &lt;code&gt;www.example.com&lt;/code&gt;, which we need to send a TCP &lt;code&gt;SYN&lt;/code&gt; packet, to establish a TCP connection over port &lt;code&gt;80&lt;/code&gt;, which we need to send the HTTP request.&lt;/p&gt;

&lt;p&gt;Since our computer now knows the MAC address of the router, it fills in the blanks of the Ethernet frame containing our DNS query and sends it over the network to (&lt;code&gt;BB:BB:BB:BB:BB:BB&lt;/code&gt;). This happens with every Ethernet frame that needs to be sent to our router. The frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=AA:AA:AA:AA:AA:AA,
    DestMac=BB:BB:BB:BB:BB:BB,
    IP[
        SourceIp=192.168.0.10,
        DestIp=8.8.8.8,
        UDP[
            SourcePort=3333,
            DestPort=53,
            DNS[
                Query=A,
                Domain=www.example.com
            ]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Complete Ethernet frame for the DNS query.&lt;/p&gt;

&lt;p&gt;One thing to note is that the &lt;code&gt;DestIp&lt;/code&gt; field is not the router’s IP address; it’s still &lt;code&gt;8.8.8.8&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The router receives this frame and looks at the destination IP (&lt;code&gt;8.8.8.8&lt;/code&gt;) in the IP header. It also uses the &lt;a href="https://en.wikipedia.org/wiki/Longest_prefix_match"&gt;longest prefix match&lt;/a&gt; to select where to forward this packet and ends up selecting its default Gateway (&lt;code&gt;51.0.0.1&lt;/code&gt;). This decision is made every time the router needs to forward a packet to an IP address in the public Internet such as &lt;code&gt;8.8.8.8&lt;/code&gt; (and later &lt;code&gt;93.184.216.34&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Based on our assumptions our router is also a NAT. This means that our router needs to translate the packet before it can be forwarded. NAT stands for Network Address Translation. It is widely deployed to have multiple devices share a single public IP address. Our internal (or private) network uses private IP addresses (&lt;code&gt;192.168.0.1&lt;/code&gt; and &lt;code&gt;192.168.0.10&lt;/code&gt;) but the public Internet uses public IP addresses. When we need to send a packet to the public Internet, the NAT takes care of replacing the private IP address with the public IP address (&lt;code&gt;51.0.0.20&lt;/code&gt;). The NAT uses 5 values to identify a connection: protocol (&lt;code&gt;UDP&lt;/code&gt; / &lt;code&gt;TCP&lt;/code&gt;), source IP, internal source port, destination IP and external source port. The external source port is chosen randomly to make sure the connection identifier is unique. Based on our assumptions, the router decides to use port &lt;code&gt;10000&lt;/code&gt;. The entry in the NAT table looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UDP 192.168.0.10 3333 -&amp;gt; 8.8.8.8 10000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;NAT table. Note that the destination port (&lt;code&gt;53&lt;/code&gt;) is not used to identify the connection.&lt;/p&gt;

&lt;p&gt;Our router uses the information in the NAT table to replace the source IP address of the packet (&lt;code&gt;192.168.0.10&lt;/code&gt;) with the public IP address (&lt;code&gt;51.0.0.20&lt;/code&gt;), and the internal source port (&lt;code&gt;3333&lt;/code&gt;) with the external source port (&lt;code&gt;10000&lt;/code&gt;). This makes that IP packet routable in the public Internet. Our router performs this translation for any packet that needs to go out to the public Internet including TCP/IP packets. We’ll call this process &lt;strong&gt;internal-to-external translation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Our router wraps the packet in a new Ethernet frame with the source MAC address of &lt;code&gt;CC:CC:CC:CC:CC:CC&lt;/code&gt;, and a destination MAC address of &lt;code&gt;DD:DD:DD:DD:DD:DD&lt;/code&gt; (we assumed this value was already cached so there’s no need for ARP). Every packet that our router forwards to the public Internet goes through the same process so we won’t bring this up again. The Ethernet frame ends up looking something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=CC:CC:CC:CC:CC:CC,
    DestMac=DD:DD:DD:DD:DD:DD,
    IP[
        SourceIp=51.0.0.20,
        DestIp=8.8.8.8,
        UDP[
            SourcePort=10000,
            DestPort=53,
            DNS[
                Query=A,
                Domain=www.example.com
            ]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Publicly routable packet with DNS query (note the change in &lt;code&gt;SourceIp&lt;/code&gt; and &lt;code&gt;SourcePort&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The Ethernet frame is sent to the default gateway which is most likely a router owned by our ISP and it is up to the ISP to get our packet to &lt;code&gt;8.8.8.8&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once our packet reaches &lt;code&gt;8.8.8.8&lt;/code&gt; (Google’s DNS server), the server takes a look at the query (&lt;code&gt;A&lt;/code&gt; for &lt;code&gt;www.example.com&lt;/code&gt;) and searches its cache. We’re assuming that the cache entry exists, so it knows that &lt;code&gt;www.example.com&lt;/code&gt; maps to &lt;code&gt;93.184.216.34&lt;/code&gt;. The DNS server creates a new DNS response message containing this information as the answer to the query. The response is wrapped in a UDP datagram with source port &lt;code&gt;53&lt;/code&gt; and destination port &lt;code&gt;10000&lt;/code&gt;. The UDP datagram is then wrapped in an IP packet with source IP &lt;code&gt;8.8.8.8&lt;/code&gt; and destination IP &lt;code&gt;51.0.0.20&lt;/code&gt; (our public IP). The packet is finally wrapped in an Ethernet frame (we’ll ignore this part) and sent through the network. The IP packet ends up looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP[
    SourceIp=8.8.8.8,
    DestIp=51.0.0.20,
    UDP[
        SourcePort=53,
        DestPort=10000,
        DNS[
            Answer=93.184.216.34,
            Domain=www.example.com
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;IP packet containing the DNS reply.&lt;/p&gt;

&lt;p&gt;The packet traverses the network and eventually reaches our router. Our router needs to translate this packet before it forwards it into our private network. The router looks at the protocol (&lt;code&gt;UDP&lt;/code&gt;), source IP (&lt;code&gt;8.8.8.8&lt;/code&gt;) and the destination port (&lt;code&gt;10000&lt;/code&gt;) to find an entry in the NAT table with those values. With the values from the table, the router translates the destination IP to be our computer’s IP (&lt;code&gt;192.168.0.10&lt;/code&gt;) and the destination port to be our computer’s source port (&lt;code&gt;3333&lt;/code&gt;). This makes that IP packet routable in our private network. The same process occurs for any packet coming from the public Internet including TCP/IP packets (only packets whose properties can be found in the NAT table are translated, the others are dropped). We’ll call this process &lt;strong&gt;external-to-internal translation&lt;/strong&gt;. After this, the router wraps the packet in an Ethernet frame with source MAC &lt;code&gt;BB:BB:BB:BB:BB:BB&lt;/code&gt; and destination MAC &lt;code&gt;AA:AA:AA:AA:AA:AA&lt;/code&gt; and sends it over the private network (this happens every time our router forwards a packet to our computer so we won’t bring it up again). The Ethernet frame with the translated IP packet looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=BB:BB:BB:BB:BB:BB,
    DestMac=AA:AA:AA:AA:AA:AA,
    IP[
        SourceIp=8.8.8.8,
        DestIp=192.168.0.10,
        UDP[
            SourcePort=53,
            DestPort=3333,
            DNS[
                Answer=93.184.216.34,
                Domain=www.example.com
            ]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Privately routable packet containing the DNS reply (note the change in &lt;code&gt;DestIp&lt;/code&gt; and &lt;code&gt;DestPort&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;With the IP address of &lt;code&gt;www.example.com&lt;/code&gt;, our computer fills in the destination IP in our incomplete &lt;code&gt;SYN&lt;/code&gt; packet. The IP header is wrapped in an Ethernet frame and sent through the private network. The Ethernet frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=AA:AA:AA:AA:AA:AA,
    DestMac=BB:BB:BB:BB:BB:BB,
    IP[
        SourceIp=192.168.0.10,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=9999,
            DestPort=80,
            Flags=[SYN]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Privately routable packet containing the TCP SYN packet.&lt;/p&gt;

&lt;p&gt;Our router receives the packet and extracts the protocol (&lt;code&gt;TCP&lt;/code&gt;), the source IP (&lt;code&gt;192.168.0.10&lt;/code&gt;), the source port (&lt;code&gt;9999&lt;/code&gt;), the destination IP (&lt;code&gt;93.184.216.34&lt;/code&gt;) and generates a random number to be used as the external source port (&lt;code&gt;15000&lt;/code&gt; from the assumptions). These values identify the TCP connection and are saved in the router’s NAT table. Our router can reference the NAT table to identify packets that need to be translated and what values to use for the translation. The entry in the NAT table looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TCP 192.168.0.10 9999 -&amp;gt; 93.184.216.34 15000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our router uses our public IP address (&lt;code&gt;51.0.0.20&lt;/code&gt;) to replace the source IP and the port generated in the previous step (&lt;code&gt;15000&lt;/code&gt;) to replace the source port. It then wraps the translated IP packet in an Ethernet frame and sends it over the network. The Ethernet frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=CC:CC:CC:CC:CC:CC,
    DestMac=DD:DD:DD:DD:DD:DD,
    IP[
        SourceIp=51.0.0.20,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=15000,
            DestPort=80,
            Flags=[SYN]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Publicly routable SYN segment (note the changes to &lt;code&gt;SourceIp&lt;/code&gt; and &lt;code&gt;SourcePort&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;When the packet reaches &lt;code&gt;93.184.216.34&lt;/code&gt; (the IP address of &lt;code&gt;www.example.com&lt;/code&gt;), the server looks at the destination port of the TCP header (&lt;code&gt;80&lt;/code&gt;) and checks if an application is listening on that port. Since there is an HTTP server running on that port, the server needs to reply with a &lt;code&gt;SYN&lt;/code&gt;/&lt;code&gt;ACK&lt;/code&gt;. The server creates a &lt;code&gt;TCP&lt;/code&gt; segment and sets its source port to &lt;code&gt;80&lt;/code&gt;, the destination port to &lt;code&gt;15000&lt;/code&gt; (the source port of the &lt;code&gt;SYN&lt;/code&gt; packet that was just received), and &lt;code&gt;SYN&lt;/code&gt;/&lt;code&gt;ACK&lt;/code&gt; for the flags. It then wraps the segment in an IP packet with source IP of &lt;code&gt;93.184.216.34&lt;/code&gt; and destination IP of &lt;code&gt;51.0.0.20&lt;/code&gt;. Finally, it wraps the IP packet in an Ethernet frame (we’re going to ignore this part). The packet is then sent out to the network and looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP[
    SourceIp=93.184.216.34,
    DestIp=51.0.0.20,
    TCP[
        SourcePort=80,
        DestPort=15000,
        Flags=[SYN, ACK]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;IP packet containing the TCP SYN / ACK.&lt;/p&gt;

&lt;p&gt;When the packet reaches our router, it performs an external-to-internal translation. The translated packet is wrapped in an Ethernet frame and sent over the private network. The Ethernet frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=BB:BB:BB:BB:BB:BB,
    DestMac=AA:AA:AA:AA:AA:AA,
    IP[
        SourceIp=93.184.216.34,
        DestIp=192.168.0.10,
        TCP[
            SourcePort=80,
            DestPort=9999,
            Flags=[SYN, ACK]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Privately routable packet containing the TCP SYN / ACK.&lt;/p&gt;

&lt;p&gt;Our computer looks at the destination port (&lt;code&gt;9999&lt;/code&gt;) and the TCP flags (&lt;code&gt;SYN&lt;/code&gt;/&lt;code&gt;ACK&lt;/code&gt;) and checks the state of this connection. The only thing missing to establish this connection is to send an &lt;code&gt;ACK&lt;/code&gt; back to the server (&lt;code&gt;93.184.216.34&lt;/code&gt;). Our computer creates a new TCP segment with source port &lt;code&gt;9999&lt;/code&gt;, destination port &lt;code&gt;80&lt;/code&gt; and &lt;code&gt;ACK&lt;/code&gt; as its only flag. This segment is then wrapped in an IP packet with source IP &lt;code&gt;192.168.0.10&lt;/code&gt; and destination IP &lt;code&gt;93.184.216.34&lt;/code&gt;. The IP packet is wrapped in an Ethernet frame and sent over the private network. The Ethernet frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=AA:AA:AA:AA:AA:AA,
    DestMac=BB:BB:BB:BB:BB:BB,
    IP[
        SourceIp=192.168.0.10,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=9999,
            DestPort=80,
            Flags=[ACK]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Privately routable packet containing the ACK to complete the three-way handshake.&lt;/p&gt;

&lt;p&gt;Our router receives this frame and uses the information in the NAT table to perform an internal-to-external translation. Then, it wraps the translated IP packet in an Ethernet frame and sends it over the public network. The Ethernet frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=CC:CC:CC:CC:CC:CC,
    DestMac=DD:DD:DD:DD:DD:DD,
    IP[
        SourceIp=50.0.0.20,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=15000,
            DestPort=80,
            Flags=[ACK]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Publicly routable packet containing the ACK to complete the three-way handshake.&lt;/p&gt;

&lt;p&gt;The packet traverses the Internet until it gets to &lt;code&gt;93.184.216.34&lt;/code&gt;. The server uses the source port (&lt;code&gt;15000&lt;/code&gt;) and the source IP (&lt;code&gt;50.0.0.20&lt;/code&gt;) to check the connection state and marks the connection as ESTABLISHED. Note that the server doesn’t return an &lt;code&gt;ACK&lt;/code&gt; for the &lt;code&gt;ACK&lt;/code&gt; it just received.&lt;/p&gt;

&lt;p&gt;Our computer is now ready to send the actual HTTP request. It wraps the HTTP request in a &lt;code&gt;TCP&lt;/code&gt; segment with source port &lt;code&gt;9999&lt;/code&gt;, destination port &lt;code&gt;80&lt;/code&gt; and sets the flags to &lt;code&gt;ACK&lt;/code&gt;/&lt;code&gt;PUSH&lt;/code&gt;. This TCP segment is then wrapped in an IP packet with source IP &lt;code&gt;192.168.0.10&lt;/code&gt; and destination IP &lt;code&gt;93.184.216.34&lt;/code&gt;. Then, it wraps the IP packet in an Ethernet frame and sends it through the private network. The frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=AA:AA:AA:AA:AA:AA,
    DestMac=BB:BB:BB:BB:BB:BB,
    IP[
        SourceIp=192.168.0.10,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=9999,
            DestPort=80,
            Flags=[ACK, PUSH],
            HTTP[
                GET / HTTP/1.1
                Host: www.example.com
                ...
            ]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Privately routable packet containing the HTTP request.&lt;/p&gt;

&lt;p&gt;Our router receives the frame and does an internal-to-external translation to the IP packet. It then wraps the translated packet in an Ethernet frame and sends it over the public network. The Ethernet frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=CC:CC:CC:CC:CC:CC,
    DestMac=DD:DD:DD:DD:DD:DD,
    IP[
        SourceIp=50.0.0.20,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=15000,
            DestPort=80,
            Flags=[ACK, PUSH],
            HTTP[
                GET / HTTP/1.1
                Host: www.example.com
                ...
            ]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Publicly routable packet containing HTTP request.&lt;/p&gt;

&lt;p&gt;The packet reaches &lt;code&gt;93.184.216.3&lt;/code&gt; (&lt;code&gt;www.example.com&lt;/code&gt;) and the server uses the source IP (&lt;code&gt;51.0.0.20&lt;/code&gt;) and source port (&lt;code&gt;15000&lt;/code&gt;) to verify that the connection exists and is ESTABLISHED. The &lt;code&gt;PUSH&lt;/code&gt; flag in the TCP segment instructs the server to send the body of the TCP segment (the HTTP request) to the application listening on port &lt;code&gt;80&lt;/code&gt; (the HTTP server). The HTTP server processes the HTTP request and generates an HTTP response. An HTTP response from &lt;code&gt;www.example.com&lt;/code&gt; looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: max-age=604800
Content-Type: text/html
Date: Sat, 11 Aug 2018 20:45:46 GMT
Etag: "1541025663"
Expires: Sat, 18 Aug 2018 20:45:46 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (oxr/830D)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 606

&amp;lt;!doctype html&amp;gt;
&amp;lt;html&amp;gt;
...
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Sample HTTP response from &lt;code&gt;www.example.com&lt;/code&gt; (snipped almost all of the body).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The server should have sent and ACK to acknowledge that this TCP segment was received. However, this ACK can also be sent along with the HTTP response, so in the interest of not being even more repetitive, we’ll assume this is the case.&lt;/p&gt;

&lt;p&gt;The HTTP response is wrapped in a TCP segment with source port &lt;code&gt;80&lt;/code&gt;, destination port &lt;code&gt;15000&lt;/code&gt; and flags &lt;code&gt;ACK&lt;/code&gt;/&lt;code&gt;PUSH&lt;/code&gt;. Then, the TCP segment is wrapped in an IP packet with source IP &lt;code&gt;93.184.216.34&lt;/code&gt; and destination IP &lt;code&gt;50.0.0.20&lt;/code&gt;. The packet is then wrapped in an Ethernet frame (that we are also going to ignore) and sent through the public network. The IP packet looks something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP[
    SourceIp=93.184.216.34,
    DestIp=50.0.0.20,
    TCP[
        SourcePort=80,
        DestPort=15000,
        Flags=[ACK, PUSH],
        HTTP[
            HTTP/1.1 200 OK
            Accept-Ranges: bytes
            ...
            &amp;lt;!doctype html&amp;gt;
            ...
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;IP packet containing the HTTP response.&lt;/p&gt;

&lt;p&gt;Our router receives the packet and performs an external-to-internal translation. After that, the IP packet is wrapped with an Ethernet frame and sent over the private network. The Ethernet frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=BB:BB:BB:BB:BB:BB,
    DestMac=AA:AA:AA:AA:AA:AA,
    IP[
        SourceIp=93.184.216.34,
        DestIp=192.168.0.10,
        TCP[
            SourcePort=80,
            DestPort=9999,
            Flags=[ACK, PUSH],
            HTTP[
                HTTP/1.1 200 OK
                Accept-Ranges: bytes
                ...
                &amp;lt;!doctype html&amp;gt;
                ...
            ]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Privately routable packet with the HTTP response.&lt;/p&gt;

&lt;p&gt;Our computer receives the packet and looks up the connection information. The &lt;code&gt;PUSH&lt;/code&gt; flag instructs our computer to send the TCP body (the HTTP response) to the application that opened the connection (our web browser). Our web browser now has the HTTP response and can use it to render the web page. From the networking side, however, we’re not done. The server doesn’t know that we received the TCP segment since we haven’t acknowledged it (sent an ACK back). Since the browser is not going to send more requests to &lt;code&gt;www.example.com&lt;/code&gt;, it will also close the connection. These two actions can be combined into one by sending the &lt;code&gt;ACK&lt;/code&gt; and the &lt;code&gt;FIN&lt;/code&gt; flags in the same TCP segment (we’re going to assume this happened to avoid even more repetition).&lt;/p&gt;

&lt;p&gt;Our computer creates a new TCP segment with source port &lt;code&gt;9999&lt;/code&gt;, destination port &lt;code&gt;80&lt;/code&gt; and &lt;code&gt;FIN&lt;/code&gt;/&lt;code&gt;ACK&lt;/code&gt; as its flags. It places this segment in an IP packet with source IP &lt;code&gt;192.168.0.10&lt;/code&gt; and destination IP &lt;code&gt;93.184.216.34&lt;/code&gt;. The IP packet is wrapped with an Ethernet frame and is sent over the network. The Ethernet frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=AA:AA:AA:AA:AA:AA,
    DestMac=BB:BB:BB:BB:BB:BB,
    IP[
        SourceIp=192.168.0.10,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=9999,
            DestPort=80,
            Flags=[ACK, FIN]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Privately routable packet containing the ACK for the HTTP response and the FIN to close the TCP connection.&lt;/p&gt;

&lt;p&gt;The router gets this frame and performs an internal-to-external translation. Then, it wraps the IP packet in an Ethernet frame and sends the frame to the public network. The frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=CC:CC:CC:CC:CC:CC,
    DestMac=DD:DD:DD:DD:DD:DD,
    IP[
        SourceIp=50.0.0.20,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=15000,
            DestPort=80,
            Flags=[ACK, FIN]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Publicly routable packet with the ACK for the HTTP response and the FIN to close the TCP connection.&lt;/p&gt;

&lt;p&gt;When the server receives this packet, it now knows that the HTTP response was received. From the flags, it can also tell that our computer wants to close the connection. The server creates a new TCP segment with source port &lt;code&gt;80&lt;/code&gt;, destination port &lt;code&gt;15000&lt;/code&gt; and flags &lt;code&gt;FIN&lt;/code&gt;/&lt;code&gt;ACK&lt;/code&gt;. It wraps this TCP segment in an IP packet with source IP &lt;code&gt;93.184.216.34&lt;/code&gt; and destination IP &lt;code&gt;50.0.0.20&lt;/code&gt;. The IP packet is sent over the network. The IP packet looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP[
    SourceIp=93.184.216.34,
    DestIp=50.0.0.20,
    TCP[
        SourcePort=80,
        DestPort=15000,
        Flags=[ACK, FIN]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;IP packet containing the FIN to close the connection.&lt;/p&gt;

&lt;p&gt;When our router receives the packet, it performs an external-to-internal translation and then wraps the packet in an Ethernet frame. It then sends the frame through our private network. The frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=BB:BB:BB:BB:BB:BB,
    DestMac=AA:AA:AA:AA:AA:AA,
    IP[
        SourceIp=93.184.216.34,
        DestIp=192.168.0.10,
        TCP[
            SourcePort=80,
            DestPort=9999,
            Flags=[ACK, FIN]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Privately routable packet containing the FIN to close the connection.&lt;/p&gt;

&lt;p&gt;Our computer receives this packet and finds a FIN in the flags. The connection is now closed, all that remains is for our computer to send an acknowledgement to the server that it received the &lt;code&gt;FIN&lt;/code&gt;/&lt;code&gt;ACK&lt;/code&gt; packet. It creates a TCP segment with source port &lt;code&gt;9999&lt;/code&gt; and destination port &lt;code&gt;80&lt;/code&gt;. The segment is wrapped in an IP packet with source IP &lt;code&gt;192.168.0.10&lt;/code&gt; and destination IP &lt;code&gt;93.184.216.34&lt;/code&gt;. The IP packet is wrapped in an Ethernet frame and sent over the private network. The frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=AA:AA:AA:AA:AA:AA,
    DestMac=BB:BB:BB:BB:BB:BB,
    IP[
        SourceIp=192.168.0.10,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=9999,
            DestPort=80,
            Flags=[ACK]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Privately routable packet containing last ACK to acknowledge that the connection has been closed.&lt;/p&gt;

&lt;p&gt;The router receives this frame and performs an internal-to-external translation. The IP packet is wrapped in an Ethernet frame sent over the public network. The Ethernet frame looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet[
    SourceMac=CC:CC:CC:CC:CC:CC,
    DestMac=DD:DD:DD:DD:DD:DD,
    IP[
        SourceIp=50.0.0.20,
        DestIp=93.184.216.34,
        TCP[
            SourcePort=15000,
            DestPort=80,
            Flags=[ACK]
        ]
    ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Publicly routable packet with translated packet with last ACK.&lt;/p&gt;

&lt;p&gt;When the server gets this packet, it looks at the flags and confirms that our computer got the FIN TCP segment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Wow, that was a long post! I think we can all agree that a lot happens at the network layer from the time you type a URL in the browser and press enter until you get to see your web page. There are a few important things to call out though:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;This was just &lt;strong&gt;one&lt;/strong&gt; HTTP request! Usually, a page that has external scripts, images, stylesheets, etc, makes tens or hundreds of requests!&lt;/li&gt;
&lt;li&gt;With only one request, we were able to see the value of caching. We only had to ask for the MAC address of the router once and then we were able to fetch that MAC address from the cache. If we had made more requests, DNS caching would have also played a role since we would have cached the IP address of &lt;code&gt;www.example.com&lt;/code&gt; and wouldn’t have had to ask our DNS server for it.&lt;/li&gt;
&lt;li&gt;Caching plays a big role in HTTP as well. If our browser had cached this page before, we wouldn’t have had to make any network calls!&lt;/li&gt;
&lt;li&gt;There is some overhead while establishing the TCP connection. HTTP clients try to keep the connection alive (with the &lt;code&gt;Connection: Keep-Alive&lt;/code&gt; HTTP header) to avoid this overhead and reuse the same connection. A problem with this header is that HTTP clients can only make one request a time (per TCP connection). &lt;a href="https://en.wikipedia.org/wiki/HTTP/2"&gt;HTTP/2&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/QUIC"&gt;QUIC&lt;/a&gt; solve this problem by multiplexing the connection.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thanks for reading! I hope you enjoyed it and learned something!&lt;/p&gt;

</description>
      <category>networks</category>
      <category>tcp</category>
      <category>dns</category>
      <category>ip</category>
    </item>
    <item>
      <title>About</title>
      <dc:creator>Nicolas Mesa</dc:creator>
      <pubDate>Tue, 07 Aug 2018 06:17:59 +0000</pubDate>
      <link>https://dev.to/nicolasmesa/about-1g7p</link>
      <guid>https://dev.to/nicolasmesa/about-1g7p</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fabout%2Fnicolas_amalia_elisa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.nicolasmesa.co%2Fabout%2Fnicolas_amalia_elisa.jpg" alt="Nicolas, Amalia and Elisa"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hi and welcome to my blog!&lt;/p&gt;

&lt;p&gt;I am a Software Development Engineer working for Amazon on the &lt;a href="https://www.amazon.com/go" rel="noopener noreferrer"&gt;Amazon Go&lt;/a&gt; and &lt;a href="https://www.amazon.com/amazonbooks" rel="noopener noreferrer"&gt;Amazon Books&lt;/a&gt; team. Currently, I live in Seattle with my wife, Elisa, and my daughter, Amalia. My interests are in Web technologies, Javascript, Python, Networking, AWS, Docker, and Linux.&lt;/p&gt;

&lt;p&gt;Before joining Amazon, I was in New York City pursuing my Master’s degree in Computer Science at &lt;a href="https://www.columbia.edu" rel="noopener noreferrer"&gt;Columbia University&lt;/a&gt;. Prior to that, I worked at &lt;a href="https://alegra.com" rel="noopener noreferrer"&gt;Alegra&lt;/a&gt;, a startup in Colombia to help small and medium-sized companies with their accounting and bookkeeping.&lt;/p&gt;

&lt;p&gt;I am also a water skier and did it competitively for a while.&lt;/p&gt;

&lt;p&gt;The purpose of this blog is to publish my notes about stuff that I find interesting or about something new that I learned. Hopefully, I’ll look back in a few years and will see how much I’ve learned.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
