<?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: Fatima Qaisar</title>
    <description>The latest articles on DEV Community by Fatima Qaisar (@fatimaaqaisar).</description>
    <link>https://dev.to/fatimaaqaisar</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3831162%2F8077186d-e02d-4c57-a5b4-1ea2186e7525.jpg</url>
      <title>DEV Community: Fatima Qaisar</title>
      <link>https://dev.to/fatimaaqaisar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fatimaaqaisar"/>
    <language>en</language>
    <item>
      <title>What My Terminal Taught Me About the Web</title>
      <dc:creator>Fatima Qaisar</dc:creator>
      <pubDate>Mon, 27 Jul 2026 04:23:06 +0000</pubDate>
      <link>https://dev.to/fatimaaqaisar/what-my-terminal-taught-me-about-the-web-533o</link>
      <guid>https://dev.to/fatimaaqaisar/what-my-terminal-taught-me-about-the-web-533o</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ceitc8fzvw9wb0bacio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ceitc8fzvw9wb0bacio.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: This isn’t written by someone who has taken a formal networking course yet, so a few rough edges should be expected.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One thing I’ve realised during my computer science journey is that the deeper you go, the more fundamental questions you start asking.&lt;/p&gt;

&lt;p&gt;I’d heard the acronyms — HTTP, TCP, DNS, TLS — countless times. I’d even spent time digging into Apache Tomcat’s codebase. But if someone had asked me what actually happens after typing a URL into a browser and pressing Enter…&lt;/p&gt;

&lt;p&gt;I wouldn’t have had a good answer.&lt;/p&gt;

&lt;p&gt;For me, this journey began with Apache Tomcat. It was one of the first open-source projects I explored — I had just learned Java OOP, and figured, how hard could a Java web server be? (Spoiler: VERY). It made me actually curious about how web infrastructure really works though.&lt;/p&gt;

&lt;p&gt;So instead of jumping straight into networking textbooks, I decided to follow a single browser request from start to finish, asking &lt;strong&gt;&lt;em&gt;why?&lt;/em&gt;&lt;/strong&gt; at every step. This article is my attempt to document that journey — not as an expert teaching networking, but as a computer science student trying to understand it one protocol at a time.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Map
&lt;/h3&gt;

&lt;p&gt;Before I dive in, here’s roughly the shape of the trip: your browser has to find an address, connect to it, secure that connection, then finally ask for the page. Five words, five stops. I’m not going to hand you a diagram of it here — I’d rather you actually watch each stop happen, the way I did, and see the shape for yourself by the end.&lt;/p&gt;

&lt;p&gt;Every browser request you make follows this journey in some form. I just decided to stop taking it for granted and follow it myself.&lt;/p&gt;

&lt;p&gt;I started at the beginning: &lt;strong&gt;DNS (Domain Name System)&lt;/strong&gt;. Because before your browser can talk to a server at all, it first has to figure out where that server actually &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: DNS — Finding the Address
&lt;/h3&gt;

&lt;p&gt;Humans remember names. Computers only understand numbers — addresses like &lt;code&gt;142.250.186.238&lt;/code&gt;. So before anything else can happen, something has to translate the name you typed into the number a computer can actually use. That something is DNS — also known as the &lt;strong&gt;&lt;em&gt;phonebook&lt;/em&gt;&lt;/strong&gt; of the internet.&lt;/p&gt;

&lt;p&gt;I wanted to &lt;em&gt;see&lt;/em&gt; this happen instead of just reading about it, so I opened a terminal and ran:&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="go"&gt;nslookup google.com
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, curious whether the result would be the same every time, I ran it a few more times in a row. Here’s exactly what I got back, run after run:&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="go"&gt;Server: UnKnown
Address: fe80::1
DNS request timed out.
 timeout was 2 seconds.
Name: google.com
Address: 2a00:1450:4018:80d::200e
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick note on those first couple of lines, since they look a little cryptic:&lt;/strong&gt; &lt;em&gt;fe80::1&lt;/em&gt; is a &lt;strong&gt;link-local IPv6 address&lt;/strong&gt; —an address that's only valid on your local network. On many home networks, it belongs to your router, though that's not guaranteed. &lt;em&gt;UnKnown&lt;/em&gt; simply means a reverse DNS lookup (asking "what hostname is associated with this IP address?") didn't return a name. That's fairly common and isn't a problem by itself.&lt;/p&gt;

&lt;p&gt;In plain terms, my computer was querying the DNS resolver reachable at &lt;em&gt;fe80::1&lt;/em&gt;. Exactly what happened after that depended on how my local network was configured—I was only seeing my side of the conversation.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Server: UnKnown
Address: fe80::1
Non-authoritative answer:
DNS request timed out.
 timeout was 2 seconds.
Name: google.com
Address: 142.250.186.238

Server: UnKnown
Address: fe80::1
Non-authoritative answer:
Name: google.com
Addresses: 2a00:1450:4018:80d::200e
 142.250.186.238
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three runs, three different results. My first reaction was: wait, why did it keep &lt;em&gt;timing out&lt;/em&gt;? I just asked for an address, not something complicated.&lt;/p&gt;

&lt;p&gt;That’s when I noticed something I’d glossed over at first — Across the three runs, I eventually saw &lt;strong&gt;two different addresses&lt;/strong&gt; for google.com:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-&lt;/strong&gt;  &lt;strong&gt;&lt;code&gt;142.250.186.238&lt;/code&gt;&lt;/strong&gt;  — this is an &lt;strong&gt;IPv4&lt;/strong&gt; address, the older, more familiar style you’ve probably seen before&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-&lt;/strong&gt;  &lt;strong&gt;&lt;code&gt;2a00:1450:4018:80d::200e&lt;/code&gt;&lt;/strong&gt;  — this is an &lt;strong&gt;IPv6&lt;/strong&gt; address, a newer, much longer format, built because the internet was running out of IPv4 addresses to hand out.&lt;/p&gt;

&lt;p&gt;A single website can have both, and your computer can reach it using either one. Looking back at the three runs, I noticed that I eventually received both an IPv4 and an IPv6 address for the same domain. Exactly why the earlier lookups timed out isn’t something I can conclude from this output alone — there are several possible explanations, from packet loss to resolver behaviour. What I &lt;em&gt;could&lt;/em&gt; see was that Google publishes both address families, and that my machine eventually learned about &lt;em&gt;both&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I hadn’t planned on stumbling into &lt;strong&gt;IPv4 vs IPv6&lt;/strong&gt; today — I was just trying to understand why the same command kept behaving differently every time I ran it. But that turned out to be the theme of this whole exercise: asking why something looks inconsistent usually leads somewhere real.&lt;/p&gt;

&lt;p&gt;Also notice the phrase “ &lt;strong&gt;Non-authoritative answer.”&lt;/strong&gt; That confused me at first — non-authoritative from &lt;em&gt;what?&lt;/em&gt; It turns out this means the answer didn’t come directly from Google’s own servers. It came from a resolver that already had it saved. Which raised the obvious next question: saved how, and for how long?&lt;/p&gt;

&lt;p&gt;To actually find out what was going on, I ran a more detailed version of the 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="go"&gt;nslookup -debug google.com
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Buried in the output was 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="go"&gt;ANSWERS:
&lt;/span&gt;&lt;span class="gp"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;google.com
&lt;span class="go"&gt; internet address = 142.250.186.238
 ttl = 260 (4 mins 20 secs)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;TTL &lt;/strong&gt; &lt;em&gt;— &lt;/em&gt; &lt;strong&gt;&lt;em&gt;time to live.&lt;/em&gt;&lt;/strong&gt; That number, &lt;strong&gt;260&lt;/strong&gt; , is literally a countdown. It means: you’re allowed to remember this answer for 260 seconds before you have to ask again. That’s why my second lookup was instant — I was still inside that 260-second window, so my computer just reused the answer it already had, instead of going out and asking again. It’s less like calling someone to ask their address every time, and more like writing it down on a sticky note and checking the note first.&lt;/p&gt;

&lt;p&gt;That one number explained everything I’d just seen: the timeout, the instant retry, all of it.&lt;/p&gt;

&lt;p&gt;It’s not just a fun fact, either — TTL is the reason “I updated my DNS record and nothing changed” is a real, common problem developers hit. If you point a domain at a new server, old TTLs mean some visitors keep getting routed to the old one until their cache expires. This is why the standard advice is just “wait” — there’s a literal countdown running somewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Quick Detour: Who Actually Decided This?
&lt;/h3&gt;

&lt;p&gt;Finding that number made me wonder something I’d never thought about before: who actually decided that DNS answers should be cacheable, and that there should be a specific countdown attached to them? Is this just something engineers agreed on informally somewhere, or is it written down officially?&lt;/p&gt;

&lt;p&gt;Turns out the internet does have something like a &lt;strong&gt;rulebook&lt;/strong&gt;. Whenever a protocol like DNS gets built, someone writes an actual specification document describing exactly how it’s supposed to behave — down to the individual bits. These documents are called &lt;strong&gt;&lt;em&gt;RFCs&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;(Request for Comments)&lt;/em&gt;&lt;/strong&gt;. DNS’s was RFC 1034 and RFC 1035, written by Paul Mockapetris in 1987.&lt;/p&gt;

&lt;p&gt;I went and skimmed it. Most of it looked like alien language, but I found something interesting: a little inconsistency in the document related to TTL. One section describes the TTL field as a 32-bit signed integer; another section, later in the same document, describes it as 32-bit unsigned.&lt;/p&gt;

&lt;p&gt;It was a neat realization: one of the internet’s most load-bearing systems started with subtle ambiguities right in its core specification. The IETF didn’t tear down and rewrite RFC 1035 when these edge cases surfaced; instead, they published update documents years later — like RFC 2181 — to formally standardize behaviors like TTL values and CNAME rules, while keeping the original wire format running.&lt;/p&gt;

&lt;p&gt;That quietly changed how I think about “infrastructure.” It’s not a perfect, static machine sitting underneath everything, finished once and for all. It’s an evolving stack of pragmatic decisions made by people, patched and refined over time, that the internet simply agreed to keep building on top of.&lt;/p&gt;

&lt;h3&gt;
  
  
  One More Thing I Tried
&lt;/h3&gt;

&lt;p&gt;Since I was already poking at DNS, I tried looking up something that doesn’t exist:&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="go"&gt;nslookup nonexistentwebsite123456.com

Server: UnKnown
Address: fe80::1
*** UnKnown can’t find nonexistentwebsite123456.com: Non-existent domain
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No timeout, no delay — just an immediate, clean “this domain doesn’t exist.” That was actually useful to see side by side with the earlier timeouts, because they &lt;em&gt;feel&lt;/em&gt; similar as a user (nothing loads, something’s wrong) but they’re completely different problems under the hood: one is “the answer is slow to arrive,” the other is “there is no answer, and DNS knows that immediately.” A plain browser error alone often can’t tell you which one you’re looking at — though a browser’s dev tools, if you actually open the Network tab, usually can. The terminal just handed it to me directly, without needing to dig.&lt;/p&gt;

&lt;p&gt;One more small thing I didn’t fully chase down earlier: back in the DNS section, the first run never said “Non-authoritative answer,” while the second and third both did. I’m not certain why the very first attempt was missing that label.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: TCP — Making Sure the Connection Actually Holds
&lt;/h3&gt;

&lt;p&gt;DNS gets you an address. But having an address doesn’t mean you’re connected to anything — it’s just a location, like knowing someone’s house number without having knocked on the door yet.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;TCP (Transmission Control Protocol)&lt;/strong&gt; comes in. Its job is to actually establish a reliable connection to that address, and then make sure whatever gets sent over it arrives complete and in order — no missing pieces, nothing scrambled.&lt;/p&gt;

&lt;p&gt;I tested this by just checking whether a real TCP connection could actually be established, on port 443 (the standard port for HTTPS, secure web traffic):&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="go"&gt;Test-NetConnection google.com -Port 443
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what came back:&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="go"&gt;WARNING: TCP connect to (2a00:1450:4018:80d::200e : 443) failed
ComputerName : google.com
RemoteAddress : 142.250.186.238
RemotePort : 443
InterfaceAlias : Wi-Fi
SourceAddress : 192.168.18.9
TcpTestSucceeded : True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line was the interesting one: my computer tried connecting over &lt;strong&gt;IPv6&lt;/strong&gt; first — the same &lt;strong&gt;&lt;code&gt;2a00:…&lt;/code&gt;&lt;/strong&gt; address from the DNS section earlier — and it &lt;strong&gt;&lt;em&gt;failed&lt;/em&gt;&lt;/strong&gt;. But the overall result still says &lt;strong&gt;&lt;code&gt;TcpTestSucceeded : True&lt;/code&gt;&lt;/strong&gt; , because it then tried the &lt;strong&gt;IPv4&lt;/strong&gt; address ( &lt;strong&gt;&lt;code&gt;142.250.186.238&lt;/code&gt;&lt;/strong&gt; ) instead, and that one worked.&lt;/p&gt;

&lt;p&gt;I didn’t have to do anything for that fallback to happen. My computer tried the newer address type, noticed it wasn’t working, and quietly tried the older one instead — all inside a single command. It turns out this kind of behavior has an actual name: &lt;strong&gt;Happy Eyeballs&lt;/strong&gt; , described in RFC 8305. The general idea is that when a client has both an IPv6 and an IPv4 address to try, it doesn’t just gamble on one — it attempts connections and uses whichever one actually succeeds first, so a broken or slow IPv6 path doesn’t leave you stuck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did IPv6 fail for me specifically?&lt;/strong&gt; I could probably spend an afternoon debugging that — router config, ISP support, something in between — but that’s actually a different question from the one I was chasing. The useful thing here isn’t &lt;em&gt;why&lt;/em&gt; IPv6 failed. It’s that the internet has a built-in way of not caring when it does.&lt;/p&gt;

&lt;p&gt;This is also, I think, the kind of thing worth knowing before you’re stuck debugging it under pressure — “site works for some people, not others” or “works on my laptop, not my phone” can genuinely trace back to exactly this: one address family failing silently while the other quietly saves the connection.&lt;/p&gt;

&lt;p&gt;Conceptually, once a working address and route are found, what TCP actually does before any of your data goes anywhere is a &lt;strong&gt;three-step handshake&lt;/strong&gt;  —  &lt;strong&gt;SYN:&lt;/strong&gt; one side says “can we talk.” &lt;strong&gt;SYN-ACK:&lt;/strong&gt; the other says “yes, can you hear me,” and finally &lt;strong&gt;ACK:&lt;/strong&gt; the first side confirms “yes, let’s go.” Only after that does actual data start moving, with TCP keeping track of what’s been sent and what’s been confirmed received, so nothing arrives missing or out of order.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: TLS — Making the Conversation Private
&lt;/h3&gt;

&lt;p&gt;Once you’re connected, there’s still a problem: that connection is readable by anyone who can see the traffic. &lt;strong&gt;TLS (Transport Layer Security)&lt;/strong&gt; is what wraps the conversation so that even if someone intercepts it, all they see is scrambled noise.&lt;/p&gt;

&lt;p&gt;This section is different from the two before it because capturing a real handshake is a rabbit hole that probably deserves its own article someday.&lt;/p&gt;

&lt;p&gt;Before any of your actual data moves, your browser and the server negotiate an &lt;strong&gt;encryption method&lt;/strong&gt; , the server proves its identity using a &lt;strong&gt;certificate&lt;/strong&gt; , and both sides land on a shared secret key without ever sending that key over the wire — some genuinely clever math makes that possible. The padlock icon next to your address bar is the visible result of that negotiation having just succeeded, fresh, every single time you connect — not a badge that’s checked once and reused.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: HTTP — Finally Asking for the Page
&lt;/h3&gt;

&lt;p&gt;After all of that — the address found, the connection made, the channel secured — HTTP finally does the part everyone actually associates with “browsing the internet.” I wanted real output here too, so I tried:&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="go"&gt;curl -v https://google.com
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;(Note on &lt;strong&gt;‘curl’&lt;/strong&gt; or &lt;strong&gt;Client URL&lt;/strong&gt; : It’s a command-line tool that lets you make HTTP requests and see the raw response — headers, status codes, the full HTML — without a browser getting in the way. It’s like being able to read the conversation between your browser and the server directly. (On Windows, ‘curl’ in PowerShell is actually an alias for a different command — you have to use ‘curl.exe’ to get the real one, as I found out the hard way.))&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That gave me an entire, genuinely interesting trace:&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="go"&gt;* Host google.com:443 was resolved.
* IPv6: 2a00:1450:4018:80d::200e
* IPv4: 142.250.186.238
* Trying [2a00:1450:4018:80d::200e]:443…
* Trying 142.250.186.238:443…
* Connected to google.com (142.250.186.238) port 443
* using HTTP/1.x
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GET / HTTP/1.1
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Host: google.com
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;User-Agent: curl/8.13.0
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;&amp;lt; HTTP/1.1 301 Moved Permanently
&amp;lt; Location: https://www.google.com/
&lt;/span&gt;&lt;span class="gp"&gt;&amp;lt; Content-Type: text/html;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;UTF-8
&lt;span class="go"&gt;&amp;lt; Server: gws
&amp;lt; Content-Length: 220
&lt;/span&gt;&lt;span class="gp"&gt;&amp;lt; Alt-Svc: h3=":443";&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2592000,h3–29&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;":443"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;ma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2592000
&lt;span class="go"&gt;&amp;lt;
&lt;/span&gt;&lt;span class="gp"&gt;&amp;lt;HTML&amp;gt;&lt;/span&gt;&amp;lt;HEAD&amp;gt;&amp;lt;meta http-equiv&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"content-type"&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;”text/html&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8&lt;span class="s2"&gt;"&amp;gt;
&lt;/span&gt;&lt;span class="gp"&gt;&amp;lt;TITLE&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;301 Moved&amp;lt;/TITLE&amp;gt;&amp;lt;/HEAD&amp;gt;&amp;lt;BODY&amp;gt;
&lt;/span&gt;&lt;span class="gp"&gt;&amp;lt;H1&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;301 Moved&amp;lt;/H1&amp;gt;
&lt;/span&gt;&lt;span class="go"&gt;The document has moved
&lt;/span&gt;&lt;span class="gp"&gt;&amp;lt;A HREF="https://www.google.com/"&amp;gt;&lt;/span&gt;here&amp;lt;/A&amp;gt;.
&lt;span class="gp"&gt;&amp;lt;/BODY&amp;gt;&lt;/span&gt;&amp;lt;/HTML&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things jumped out immediately.&lt;/p&gt;

&lt;p&gt;First — there’s that IPv4/IPv6 pattern again, showing up for a third time in this same journey. Both addresses get tried, and the connection lands on IPv4, same as the TCP section earlier. I didn’t go looking for this repetition; it just kept showing up every time I checked.&lt;/p&gt;

&lt;p&gt;Second — the actual request is exactly three lines: &lt;strong&gt;&lt;code&gt;GET / HTTP/1.1&lt;/code&gt;&lt;/strong&gt; , a &lt;strong&gt;&lt;code&gt;Host&lt;/code&gt;&lt;/strong&gt; header, and a couple of housekeeping headers identifying the client. That’s it. That’s the whole request &lt;strong&gt;curl&lt;/strong&gt; needed to send in this case.&lt;/p&gt;

&lt;p&gt;Third, and the part I didn’t expect: the response wasn’t &lt;code&gt;200 OK&lt;/code&gt; at all. It was &lt;code&gt;301 Moved Permanently&lt;/code&gt;, with a &lt;code&gt;Location&lt;/code&gt; header pointing to &lt;a href="https://www.google.com/" rel="noopener noreferrer"&gt;https://www.google.com/&lt;/a&gt;. Typing &lt;code&gt;google.com&lt;/code&gt; doesn’t actually load &lt;code&gt;google.com&lt;/code&gt; — the server immediately redirects you to &lt;a href="http://www.google.com" rel="noopener noreferrer"&gt;www.google.com&lt;/a&gt;, and your browser follows that redirect silently, so fast you’d never notice it happened. The “one simple request” I imagined at the start of this article is actually, in Google’s case, at least two.&lt;/p&gt;

&lt;p&gt;One more small thing worth a mention: that &lt;code&gt;Alt-Svc: h3=…&lt;/code&gt; header in the response is Google telling clients it also supports &lt;strong&gt;HTTP/3&lt;/strong&gt;  — a newer version of HTTP that runs over a different, faster transport than the TCP connection this whole request just used (QUIC, which runs on UDP — more protocols yes). I’m not going to open that door today, but it’s a good reminder that even “HTTP” isn’t one fixed, finished thing either.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Whole Trip
&lt;/h3&gt;

&lt;p&gt;This was it:&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="go"&gt;You type a URL → DNS finds the address → TCP connects → TLS secures it → HTTP asks for the page → your browser renders it
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Five arrows. A few paragraphs ago that would’ve just been a diagram to memorize. Now every single one is something I actually watched happen — DNS finding the address (with a real fallback happening along the way), TCP getting you connected, TLS securing the channel, and HTTP finally asking for the page. Every step here started with an actual command and actual output, not a diagram I was trusting blindly.&lt;/p&gt;

&lt;p&gt;What I didn’t expect, going in, was the repetition — the same IPv4/IPv6 pattern showing up in DNS, TCP, and the HTTP connection, every single time I checked, without me going looking for it. But that’s the thing about asking &lt;strong&gt;&lt;em&gt;why?&lt;/em&gt;&lt;/strong&gt; all the way down — you don’t just find the answers you were looking for. You find the places where the answers don’t quite agree with themselves, where the internet isn’t a perfect, finished machine humming underneath everything, but a stack of decisions made by people.&lt;/p&gt;

&lt;p&gt;That’s not a flaw you learn from a textbook. It’s sitting right there in a terminal — waiting for you to ask.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>softwareengineering</category>
      <category>networkprotocols</category>
      <category>internet</category>
    </item>
    <item>
      <title>LeetCode Journal # 1</title>
      <dc:creator>Fatima Qaisar</dc:creator>
      <pubDate>Sat, 25 Jul 2026 04:21:20 +0000</pubDate>
      <link>https://dev.to/fatimaaqaisar/leetcode-journal-1-ja</link>
      <guid>https://dev.to/fatimaaqaisar/leetcode-journal-1-ja</guid>
      <description>&lt;h3&gt;
  
  
  Documenting my daily LeetCode journey here!
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Today's Problem:&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1512. Number of Good Pairs
&lt;/h3&gt;

&lt;h2&gt;
  
  
  My First Approach
&lt;/h2&gt;

&lt;p&gt;My initial solution was straightforward: compare every element with every other element and count the pairs where the values are equal and &lt;code&gt;i &amp;lt; j&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;numIdenticalPairs&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&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="o"&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;nums&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;j&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time Complexity: &lt;code&gt;O(n²)&lt;/code&gt;&lt;br&gt;
Space Complexity: &lt;code&gt;O(1)&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why I wanted to optimize it
&lt;/h2&gt;

&lt;p&gt;This solution checks every possible pair, even though most comparisons don't contribute to the answer. As the input size grows, the number of comparisons increases quadratically.&lt;/p&gt;

&lt;p&gt;I realised that I didn't actually need to compare the current element with every previous element. I only needed to know how many times I'd already seen the current number.&lt;/p&gt;

&lt;p&gt;That led me to use a &lt;code&gt;HashMap&lt;/code&gt; to store frequencies. If a number has already appeared &lt;code&gt;k&lt;/code&gt; times, then the current occurrence immediately creates &lt;code&gt;k&lt;/code&gt; new good pairs.&lt;/p&gt;

&lt;p&gt;This reduces the time complexity from &lt;code&gt;O(n²)&lt;/code&gt; to &lt;code&gt;O(n)&lt;/code&gt; while trading a small amount of extra space &lt;code&gt;O(n)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;numIdenticalPairs&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&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="n"&gt;nums&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrDefault&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;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&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;count&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&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;,++&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time Complexity: &lt;code&gt;O(n)&lt;/code&gt;&lt;br&gt;
Space Complexity: &lt;code&gt;O(n)&lt;/code&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>leetcode</category>
      <category>java</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
