Skip to content

Update network programming season#394

Merged
ja7ad merged 11 commits into
GoFarsi:mainfrom
amirhasanpour:network-programming
Sep 6, 2025
Merged

Update network programming season#394
ja7ad merged 11 commits into
GoFarsi:mainfrom
amirhasanpour:network-programming

Conversation

@amirhasanpour
Copy link
Copy Markdown
Contributor

@amirhasanpour amirhasanpour commented Sep 6, 2025

5.2 => Fix typo error, log.Fetal used instead of log.Fatal

5.3 => Remove additional enters for better code format

5.4.1 => Fix incorrect UDP vs TCP speed description

5.4.2 => Remove additional enters for better code format

5.4.3 => Modify code format

5.7 => Add explanation about encode and decode in code

5.8 => Use io instead of io/ioutil which is deprecated and write an error check

5.9.3 => Use io instead of io/ioutil which is deprecated

5.9.5 => Add some enters for better code format

5.9.6 => Fix code format error and modify it

5.10 => Modify code format

Summary by CodeRabbit

  • New Features

    • Added Persian-language explanations, JSON Encode/Decode guidance, and testing walkthroughs for the HTTP server, including sample requests/responses for CRUD endpoints.
  • Documentation

    • Updated HTTP client examples to use modern io.ReadAll and improved error handling.
    • Corrected UDP overview to state it’s faster than TCP while noting delivery caveats.
    • General formatting and clarity improvements across TCP, UDP, HTTP, and QUIC chapters.
  • Bug Fixes

    • Fixed a fatal logging call typo that could affect startup error handling.
    • Corrected minor comment typos.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 6, 2025

Walkthrough

Documentation updates and formatting cleanups across Chapter 5. Minor functional edits include fixing a fatal logging call in the TCP beginner server and switching HTTP client examples from ioutil.ReadAll to io.ReadAll. Additional Persian-language documentation and examples were added to the HTTP server chapter.

Changes

Cohort / File(s) Summary
QUIC server doc grooming
content/chapter 5/5.10-quic-server.md
Whitespace/indentation tweaks; minor comment typo fix; no code or flow changes.
TCP server (beginner) minor fix + formatting
content/chapter 5/5.2-tcp-server-begginer.md
Formatting alignments; fix log.Fetal → log.Fatal in main; no API changes.
TCP server (advanced) formatting
content/chapter 5/5.3-tcp-server-advanced.md
Formatting only (struct/goroutine spacing, indentation); no behavioral changes.
UDP server (beginner) doc wording + formatting
content/chapter 5/5.4-udp-server-begginer.md
Documentation updates (UDP described as faster than TCP); indentation/comment alignment; no code changes.
HTTP server (advanced) documentation additions
content/chapter 5/5.7-http-server-advanced.md
Added Persian explanations, Encode/Decode sections, and testing guide; server code unchanged.
HTTP client examples: migrate ioutil → io
content/chapter 5/5.8-http-client-begginer.md, content/chapter 5/5.9-http-client-advanced.md
Switch to io.ReadAll and import io; added explicit read error handling in beginner; advanced example re-ordered/indented; no API changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

Thump-thump, I nibble through lines of code,
Swapping ioutil for io on the road.
A Fatal hop, not Fetal—fixed with care,
QUIC and TCP brushed tidy and fair.
Docs bloom in Persian, neat and bright—
Carrots of clarity, bytes just right! 🥕✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
content/chapter 5/5.10-quic-server.md (1)

135-147: Weak RSA key size (1024-bit).
Use at least 2048-bit RSA or prefer ECDSA (P-256) for TLS 1.3.

- key, err := rsa.GenerateKey(rand.Reader, 1024)
+ key, err := rsa.GenerateKey(rand.Reader, 2048)

Optionally replace with ECDSA (elliptic.P256) to reduce CPU cost.

content/chapter 5/5.3-tcp-server-advanced.md (2)

61-76: Do not use log.Fatal in read loop; fix unbounded buffer growth; check read errors.

  • log.Fatal exits the whole process; prefer returning/closing the conn.
  • buf is never reset, causing unbounded growth across chunks.
  • binary.Read error is ignored.
 func (fs *FileServer) readLoop(conn net.Conn) {
-  // make a new buffer
-  buf := new(bytes.Buffer)
+  // a fresh buffer per file
+  buf := new(bytes.Buffer)
   for {
     var size int64
-    // get the size from connection
-    binary.Read(conn, binary.LittleEndian, &size)
+    // get the size from connection
+    if err := binary.Read(conn, binary.LittleEndian, &size); err != nil {
+      log.Printf("size read error: %v", err)
+      return
+    }
     // copy from connection until the end of file
     n, err := io.CopyN(buf, conn, size)
-    if err != nil {
-      log.Fatal(err)
-      continue
-    }
+    if err != nil {
+      log.Printf("copy error: %v", err)
+      return
+    }
+    // process buf.Bytes() here...
+    buf.Reset()
     fmt.Println(buf.Bytes())
     fmt.Printf("received %d bytes over the network\n", n)
   }
 }

101-112: Close client connection and check write errors.
sendFile leaks the connection and ignores errors from binary.Write.

 conn, err := net.Dial("tcp", ":3000")
 if err != nil {
   return err
 }
+defer conn.Close()
 // send the size of file
- binary.Write(conn, binary.LittleEndian, int64(size))
+ if err := binary.Write(conn, binary.LittleEndian, int64(size)); err != nil {
+   return err
+ }
 // copy file over the network until the end of file
 n, err := io.CopyN(conn, bytes.NewReader(file), int64(size))
content/chapter 5/5.9-http-client-advanced.md (1)

216-224: Invalid JSON payload and missing Content-Type in PUT request.

Keys/strings must be double-quoted; also set Content-Type to application/json so servers parse it correctly.

-// مقدار های جدید را برای اپدیت شدن وارد میکنیم
+// مقدارهای جدید را برای آپدیت وارد می‌کنیم
 requestBody := []byte(`
-	{
-		title: 'test product',
-		price: 13.5,
-		description: 'lorem ipsum set',
-		image: 'https://i.pravatar.cc',
-		category: 'electronic'
-	}
+{
+  "title": "test product",
+  "price": 13.5,
+  "description": "lorem ipsum set",
+  "image": "https://i.pravatar.cc",
+  "category": "electronic"
+}
 `)
@@
-req, err := http.NewRequest("PUT", url, bytes.NewBuffer(requestBody))
+req, err := http.NewRequest("PUT", url, bytes.NewBuffer(requestBody))
 if err != nil {
   fmt.Println(err)
   return
 }
+req.Header.Set("Content-Type", "application/json")
@@
-// درصورت 200 بودن کد وضعیت اپدیت با موفقیت انجام شده.
+// در صورت 200 بودن کد وضعیت، آپدیت با موفقیت انجام شده است.
 fmt.Println(resp.StatusCode)

Also applies to: 226-244

🧹 Nitpick comments (20)
content/chapter 5/5.8-http-client-begginer.md (4)

30-30: Simplify timeout expression.
Use time.Second instead of time.Duration(1) * time.Second.

- c := http.Client{Timeout: time.Duration(1) * time.Second}
+ c := http.Client{Timeout: time.Second}

34-41: Handle non-2xx HTTP responses.
Check resp.StatusCode before reading the body to avoid treating HTTP errors as success.

 resp, err := c.Get("https://www.example.com")
 if err != nil {
   fmt.Printf("Error %s", err)
   return
 }
 defer resp.Body.Close()
+if resp.StatusCode < 200 || resp.StatusCode >= 300 {
+  fmt.Printf("HTTP error: %s\n", resp.Status)
+  return
+}

32-35: Fix Persian typos in comments.

  • "درخوایت" → "درخواست"
  • Consider adding punctuation and spacing consistency.
-// دقیقا سروری مشابه ... درخوایت ارسال میکنیم ...
+// دقیقاً سروری مشابه ... درخواست ارسال می‌کنیم ...

22-48: Replace hard tabs with spaces in code blocks.
markdownlint (MD010) flags hard tabs across this block. Replace tabs with spaces or configure the linter to ignore fenced code blocks.

content/chapter 5/5.10-quic-server.md (5)

64-66: Nit: spelling in comment.
"listner" → "listener".

- // make a new listner with quic
+ // make a new listener with quic

87-94: Nit: comment grammar.
"client function that send the message" → "client function that sends the message".

-// client function that send the message to our server
+// client function that sends the message to our server

70-85: Accept loops for multiple connections/streams.
Server currently handles a single connection and single stream, then exits. Wrap Accept and AcceptStream in loops for a usable echo server.

- // accept incoming connections
- conn, err := listener.Accept(context.Background())
- ...
- // accept incoming streams
- stream, err := conn.AcceptStream(context.Background())
+ for {
+   // accept incoming connections
+   conn, err := listener.Accept(context.Background())
+   if err != nil { return err }
+   go func(c quic.Connection) {
+     for {
+       stream, err := c.AcceptStream(context.Background())
+       if err != nil { return }
+       go func(s quic.Stream) { _, _ = io.Copy(loggingWriter{s}, s) }(stream)
+     }
+   }(conn)
+ }

49-51: Nit: message text consistency.
"hello gifarsi!" vs "gofarsi" elsewhere; pick one for consistency.


1-5: Slug typo.
slug: go-quic-prtoocol → go-quic-protocol. If you change the slug, add an aliases entry to avoid breaking links.

 slug: go-quic-prtoocol
+aliases: ["go-quic-prtoocol"]
+slug: go-quic-protocol
content/chapter 5/5.3-tcp-server-advanced.md (1)

80-85: Handle sendFile error and fix typo.
The goroutine ignores sendFile errors; also "szie" typo.

 go func() {
   time.Sleep(4 * time.Second)
-  // set your file szie
-  sendFile(2000000)
+  // set your file size
+  if err := sendFile(2_000_000); err != nil {
+    log.Printf("sendFile error: %v", err)
+  }
 }()
content/chapter 5/5.4-udp-server-begginer.md (2)

14-15: Persian spelling and nuance.

  • "تظمین" → "تضمین".
  • Consider clarifying that lower overhead often results in lower latency, but “faster than TCP” depends on the application and reliability requirements.
-به همین دلیل سرعت در این پروتکل از پروتکل tcp بیشتر است اما تظمین ارسال کامل و سالم داده وجود ندارد.
+به همین دلیل سربار کمتر و معمولاً تأخیر پایین‌تری نسبت به TCP دارد، اما تضمینی برای ارسال کامل و سالم داده وجود ندارد.

30-55: Replace hard tabs with spaces in code blocks.
markdownlint (MD010) flags hard tabs across this section.

content/chapter 5/5.2-tcp-server-begginer.md (2)

92-99: Avoid busy loop on connection read errors.
On read error, continuing the loop can spin on a dead connection. Break or return instead.

 n, err := conn.Read(buf)
 if err != nil {
-  fmt.Println("read error:", err)
-  continue
+  fmt.Println("read error:", err)
+  return
 }

Also consider handling io.EOF distinctly.


98-104: Check write error to the client.
Capture and handle the error from conn.Write to avoid silent failures.

- conn.Write([]byte("your message recived!\n"))
+ if _, err := conn.Write([]byte("your message received!\n")); err != nil {
+   fmt.Println("write error:", err)
+   return
+ }
content/chapter 5/5.7-http-server-advanced.md (3)

108-111: Fix Persian typography (ZWNJ) and wording.

Apply ZWNJ and minor fixes for clarity.

-پیش از توضیح نحوه تست سرور http ایجاد شده، اجازه بدهید کمی درباره دو مفهوم
-کلیدی Encode و Decode که در کد بالا آمده است و ممکن است برای کسانی که تازه وارد بحث
-برنامه نویسی شبکه شده اند کمی گنگ باشد، توضیح بدهیم.
+پیش از توضیح نحوهٔ تست سرور http ایجادشده، اجازه بدهید کمی دربارهٔ دو مفهوم
+کلیدی Encode و Decode که در کد بالا آمده است و ممکن است برای کسانی که تازه‌واردِ بحث
+برنامه‌نویسی شبکه شده‌اند کمی گنگ باشد، توضیح بدهیم.

112-116: Add blank lines after headings (MD022).

Headings should be followed by a blank line to satisfy markdownlint.

-## توضیح Encode و Decode در کد
-در کدی که نوشتیم، دو عمل خیلی مهم وجود دارد: Encode و Decode. این‌ها مسئول تبدیل داده‌ها بین دنیای Go و دنیای JSON هستند.
+## توضیح Encode و Decode در کد
+
+در کدی که نوشتیم، دو عمل خیلی مهم وجود دارد: Encode و Decode. این‌ها مسئول تبدیل داده‌ها بین دنیای Go و دنیای JSON هستند.

-### Encode
-هر وقت بخواهیم داده‌های سمت سرور (مثل یک struct یا slice) را به صورت JSON برای کلاینت بفرستیم، از Encode استفاده می‌کنیم.
+### Encode
+
+هر وقت بخواهیم داده‌های سمت سرور (مثل یک struct یا slice) را به صورت JSON برای کلاینت بفرستیم، از Encode استفاده می‌کنیم.

-### Decode
-وقتی کلاینت داده‌ای را به سرور می‌فرستد (مثلاً با متد POST یا PATCH)، داده‌ها معمولاً در قالب JSON ارسال می‌شوند. ما باید این JSON را به یک struct در Go تبدیل کنیم تا بتوانیم راحت با آن کار کنیم. اینجاست که Decode به کار می‌آید.
+### Decode
+
+وقتی کلاینت داده‌ای را به سرور می‌فرستد (مثلاً با متد POST یا PATCH)، داده‌ها معمولاً در قالب JSON ارسال می‌شوند. ما باید این JSON را به یک struct در Go تبدیل کنیم تا بتوانیم راحت با آن کار کنیم. اینجاست که Decode به کار می‌آید.

Also applies to: 133-136


120-123: Handle Encode error in the example.

Demonstrate best practice by checking the encoder error.

-json.NewEncoder(w).Encode(todos)
+if err := json.NewEncoder(w).Encode(todos); err != nil {
+  http.Error(w, err.Error(), http.StatusInternalServerError)
+  return
+}
content/chapter 5/5.9-http-client-advanced.md (3)

74-81: Check non-2xx responses before reading body.

Small robustness tweak: fail fast on unexpected status codes.

 resp, err := http.Get("https://fakestoreapi.com/products")
 if err != nil {
   fmt.Println("Error:", err)
   return
 }
 defer resp.Body.Close()

-// کد وضعیت پاسخ سرور را چاپ میکنیم
-fmt.Println(resp.StatusCode)
+// کد وضعیت پاسخ سرور را بررسی/چاپ میکنیم
+if resp.StatusCode != http.StatusOK {
+  fmt.Println("Status:", resp.Status)
+  return
+}
+fmt.Println("Status:", resp.Status)

 // خروجی را در یک اسلایس ذخیره میکنیم
 body, err := io.ReadAll(resp.Body)

Also applies to: 82-93


172-196: Add HTTP client timeout for DELETE request.

Prevents hangs on slow/unreachable servers.

-import (
-	"fmt"
-	"net/http"
-)
+import (
+	"fmt"
+	"net/http"
+	"time"
+)
@@
-	client := &http.Client{}
+	client := &http.Client{Timeout: 10 * time.Second}

212-214: Fix typos in Persian comment.

Correct wording.

-// ایدی محول مورد نظر را به انتهای url اضافه میکنیم
+// شناسهٔ محصول مورد نظر را به انتهای URL اضافه می‌کنیم
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f535e38 and 4013389.

📒 Files selected for processing (7)
  • content/chapter 5/5.10-quic-server.md (3 hunks)
  • content/chapter 5/5.2-tcp-server-begginer.md (4 hunks)
  • content/chapter 5/5.3-tcp-server-advanced.md (2 hunks)
  • content/chapter 5/5.4-udp-server-begginer.md (4 hunks)
  • content/chapter 5/5.7-http-server-advanced.md (1 hunks)
  • content/chapter 5/5.8-http-client-begginer.md (1 hunks)
  • content/chapter 5/5.9-http-client-advanced.md (4 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
content/chapter 5/5.8-http-client-begginer.md

22-22: Hard tabs
Column: 1

(MD010, no-hard-tabs)


23-23: Hard tabs
Column: 1

(MD010, no-hard-tabs)


24-24: Hard tabs
Column: 1

(MD010, no-hard-tabs)


25-25: Hard tabs
Column: 1

(MD010, no-hard-tabs)


29-29: Hard tabs
Column: 1

(MD010, no-hard-tabs)


30-30: Hard tabs
Column: 1

(MD010, no-hard-tabs)


32-32: Hard tabs
Column: 1

(MD010, no-hard-tabs)


33-33: Hard tabs
Column: 1

(MD010, no-hard-tabs)


34-34: Hard tabs
Column: 1

(MD010, no-hard-tabs)


35-35: Hard tabs
Column: 1

(MD010, no-hard-tabs)


36-36: Hard tabs
Column: 1

(MD010, no-hard-tabs)


37-37: Hard tabs
Column: 1

(MD010, no-hard-tabs)


38-38: Hard tabs
Column: 1

(MD010, no-hard-tabs)


39-39: Hard tabs
Column: 1

(MD010, no-hard-tabs)


40-40: Hard tabs
Column: 1

(MD010, no-hard-tabs)


41-41: Hard tabs
Column: 1

(MD010, no-hard-tabs)


42-42: Hard tabs
Column: 1

(MD010, no-hard-tabs)


43-43: Hard tabs
Column: 1

(MD010, no-hard-tabs)


44-44: Hard tabs
Column: 1

(MD010, no-hard-tabs)


45-45: Hard tabs
Column: 1

(MD010, no-hard-tabs)


46-46: Hard tabs
Column: 1

(MD010, no-hard-tabs)


48-48: Hard tabs
Column: 1

(MD010, no-hard-tabs)

content/chapter 5/5.4-udp-server-begginer.md

30-30: Hard tabs
Column: 1

(MD010, no-hard-tabs)


44-44: Hard tabs
Column: 1

(MD010, no-hard-tabs)


45-45: Hard tabs
Column: 1

(MD010, no-hard-tabs)


46-46: Hard tabs
Column: 1

(MD010, no-hard-tabs)


47-47: Hard tabs
Column: 1

(MD010, no-hard-tabs)


48-48: Hard tabs
Column: 1

(MD010, no-hard-tabs)


49-49: Hard tabs
Column: 1

(MD010, no-hard-tabs)


51-51: Hard tabs
Column: 1

(MD010, no-hard-tabs)


52-52: Hard tabs
Column: 1

(MD010, no-hard-tabs)


53-53: Hard tabs
Column: 1

(MD010, no-hard-tabs)


70-70: Hard tabs
Column: 1

(MD010, no-hard-tabs)


71-71: Hard tabs
Column: 1

(MD010, no-hard-tabs)


73-73: Hard tabs
Column: 1

(MD010, no-hard-tabs)


74-74: Hard tabs
Column: 1

(MD010, no-hard-tabs)


75-75: Hard tabs
Column: 1

(MD010, no-hard-tabs)

content/chapter 5/5.7-http-server-advanced.md

112-112: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


115-115: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


120-120: Code block style
Expected: indented; Actual: fenced

(MD046, code-block-style)


126-126: Code block style
Expected: indented; Actual: fenced

(MD046, code-block-style)


133-133: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


138-138: Code block style
Expected: indented; Actual: fenced

(MD046, code-block-style)


144-144: Code block style
Expected: indented; Actual: fenced

(MD046, code-block-style)

content/chapter 5/5.9-http-client-advanced.md

69-69: Hard tabs
Column: 1

(MD010, no-hard-tabs)


70-70: Hard tabs
Column: 1

(MD010, no-hard-tabs)


74-74: Hard tabs
Column: 1

(MD010, no-hard-tabs)


75-75: Hard tabs
Column: 1

(MD010, no-hard-tabs)


75-75: Bare URL used

(MD034, no-bare-urls)


76-76: Hard tabs
Column: 1

(MD010, no-hard-tabs)


77-77: Hard tabs
Column: 1

(MD010, no-hard-tabs)


78-78: Hard tabs
Column: 1

(MD010, no-hard-tabs)


79-79: Hard tabs
Column: 1

(MD010, no-hard-tabs)


80-80: Hard tabs
Column: 1

(MD010, no-hard-tabs)


82-82: Hard tabs
Column: 1

(MD010, no-hard-tabs)


83-83: Hard tabs
Column: 1

(MD010, no-hard-tabs)


85-85: Hard tabs
Column: 1

(MD010, no-hard-tabs)


86-86: Hard tabs
Column: 1

(MD010, no-hard-tabs)


87-87: Hard tabs
Column: 1

(MD010, no-hard-tabs)


88-88: Hard tabs
Column: 1

(MD010, no-hard-tabs)


89-89: Hard tabs
Column: 1

(MD010, no-hard-tabs)


90-90: Hard tabs
Column: 1

(MD010, no-hard-tabs)


92-92: Hard tabs
Column: 1

(MD010, no-hard-tabs)


93-93: Hard tabs
Column: 1

(MD010, no-hard-tabs)


172-172: Hard tabs
Column: 1

(MD010, no-hard-tabs)


173-173: Hard tabs
Column: 1

(MD010, no-hard-tabs)


177-177: Hard tabs
Column: 1

(MD010, no-hard-tabs)


178-178: Hard tabs
Column: 1

(MD010, no-hard-tabs)


178-178: Bare URL used

(MD034, no-bare-urls)


180-180: Hard tabs
Column: 1

(MD010, no-hard-tabs)


181-181: Hard tabs
Column: 1

(MD010, no-hard-tabs)


182-182: Hard tabs
Column: 1

(MD010, no-hard-tabs)


183-183: Hard tabs
Column: 1

(MD010, no-hard-tabs)


184-184: Hard tabs
Column: 1

(MD010, no-hard-tabs)


186-186: Hard tabs
Column: 1

(MD010, no-hard-tabs)


187-187: Hard tabs
Column: 1

(MD010, no-hard-tabs)


188-188: Hard tabs
Column: 1

(MD010, no-hard-tabs)


189-189: Hard tabs
Column: 1

(MD010, no-hard-tabs)


190-190: Hard tabs
Column: 1

(MD010, no-hard-tabs)


191-191: Hard tabs
Column: 1

(MD010, no-hard-tabs)


192-192: Hard tabs
Column: 1

(MD010, no-hard-tabs)


194-194: Hard tabs
Column: 1

(MD010, no-hard-tabs)


195-195: Hard tabs
Column: 1

(MD010, no-hard-tabs)


212-212: Hard tabs
Column: 1

(MD010, no-hard-tabs)


213-213: Hard tabs
Column: 1

(MD010, no-hard-tabs)


213-213: Bare URL used

(MD034, no-bare-urls)


215-215: Hard tabs
Column: 1

(MD010, no-hard-tabs)


216-216: Hard tabs
Column: 1

(MD010, no-hard-tabs)


226-226: Hard tabs
Column: 1

(MD010, no-hard-tabs)


227-227: Hard tabs
Column: 1

(MD010, no-hard-tabs)


228-228: Hard tabs
Column: 1

(MD010, no-hard-tabs)


229-229: Hard tabs
Column: 1

(MD010, no-hard-tabs)


230-230: Hard tabs
Column: 1

(MD010, no-hard-tabs)


231-231: Hard tabs
Column: 1

(MD010, no-hard-tabs)


233-233: Hard tabs
Column: 1

(MD010, no-hard-tabs)


234-234: Hard tabs
Column: 1

(MD010, no-hard-tabs)


235-235: Hard tabs
Column: 1

(MD010, no-hard-tabs)


236-236: Hard tabs
Column: 1

(MD010, no-hard-tabs)


237-237: Hard tabs
Column: 1

(MD010, no-hard-tabs)


238-238: Hard tabs
Column: 1

(MD010, no-hard-tabs)


239-239: Hard tabs
Column: 1

(MD010, no-hard-tabs)


240-240: Hard tabs
Column: 1

(MD010, no-hard-tabs)


242-242: Hard tabs
Column: 1

(MD010, no-hard-tabs)


243-243: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🪛 LanguageTool
content/chapter 5/5.7-http-server-advanced.md

[whitespace] ~109-~109: آیا منظور شما «"تازه‌وارد"» است؟
Context: ... بالا آمده است و ممکن است برای کسانی که تازه وارد بحث برنامه نویسی شبکه شده اند کمی گنگ ب...

(ZWNJ_Connection)

🔇 Additional comments (5)
content/chapter 5/5.8-http-client-begginer.md (2)

22-25: Good migration to io.ReadAll and tidy imports.
The switch from io/ioutil to io is correct and future-proof.


42-47: Nice: added read error handling.
The explicit check around io.ReadAll is a solid improvement.

content/chapter 5/5.3-tcp-server-advanced.md (1)

34-34: LGTM: idiomatic empty struct.
type FileServer struct{} is the idiomatic form.

content/chapter 5/5.2-tcp-server-begginer.md (1)

116-117: Correct fix: log.Fatal instead of log.Fetal.
Good catch; this prevents a runtime panic due to an undefined identifier and ensures proper fatal logging.

content/chapter 5/5.9-http-client-advanced.md (1)

69-71: Good update: migrate to io.ReadAll.

Moving from ioutil.ReadAll to io.ReadAll is correct and modern.

Comment on lines 90 to 97
tlsConf := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"quic-echo-example"},
}
// dial with our udp server

// dial with our udp server
conn, err := quic.DialAddr(context.Background(), addr, tlsConf, nil)
if err != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Insecure TLS on client (InsecureSkipVerify).
InsecureSkipVerify: true disables certificate verification. For an example with a self-signed cert, trust the server cert via a cert pool instead.

- tlsConf := &tls.Config{
-   InsecureSkipVerify: true,
-   NextProtos:         []string{"quic-echo-example"},
- }
+ certPool := x509.NewCertPool()
+ // TODO: add server cert to pool (e.g., from generateTLSConfig output)
+ tlsConf := &tls.Config{
+   RootCAs:    certPool,
+   NextProtos: []string{"quic-echo-example"},
+ }

If keeping it as a quick demo, add a prominent warning in the text.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tlsConf := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"quic-echo-example"},
}
// dial with our udp server
// dial with our udp server
conn, err := quic.DialAddr(context.Background(), addr, tlsConf, nil)
if err != nil {
// …earlier code…
// Trust only our self-signed server certificate instead of skipping verification.
certPool := x509.NewCertPool()
// TODO: load and add the server’s certificate to certPool, e.g.:
// certData, _ := os.ReadFile("server-cert.pem")
// certPool.AppendCertsFromPEM(certData)
tlsConf := &tls.Config{
RootCAs: certPool,
NextProtos: []string{"quic-echo-example"},
}
// dial with our udp server
conn, err := quic.DialAddr(context.Background(), addr, tlsConf, nil)
if err != nil {
// …
}
// …remaining code…
🤖 Prompt for AI Agents
In content/chapter 5/5.10-quic-server.md around lines 90 to 97, the client TLS
config uses InsecureSkipVerify: true which disables certificate verification;
replace this by loading the server's certificate into a x509.CertPool and set
tls.Config.RootCAs (and optionally ServerName) so the client trusts the
self-signed cert, or if you must keep the insecure setting for a short demo add
a prominent warning in the text above the code block stating that
InsecureSkipVerify disables certificate verification and must never be used in
production.

Comment on lines +70 to 76
// یک اتصال به سرور ایجاد میکنیم
Conn, _ := net.DialUDP("udp", nil, &net.UDPAddr{IP: []byte{127, 0, 0, 1}, Port: 3000, Zone: ""})

defer Conn.Close()
// متن زیر را به سرور ارسال میکنیم
Conn.Write([]byte("hello, gofarsi!"))
defer Conn.Close()
// متن زیر را به سرور ارسال میکنیم
Conn.Write([]byte("hello, gofarsi!"))
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Invalid UDPAddr IP literal; missing error handling.
IP field expects net.IP; []byte literal won’t assign to net.IP without conversion. Also don’t discard the error from net.DialUDP.

- // یک اتصال به سرور ایجاد میکنیم
- Conn, _ := net.DialUDP("udp", nil, &net.UDPAddr{IP: []byte{127, 0, 0, 1}, Port: 3000, Zone: ""})
+ // یک اتصال به سرور ایجاد می‌کنیم
+ conn, err := net.DialUDP("udp", nil, &net.UDPAddr{
+   IP:   net.ParseIP("127.0.0.1"),
+   Port: 3000,
+ })
+ if err != nil {
+   panic(err)
+ }
- defer Conn.Close()
+ defer conn.Close()
- // متن زیر را به سرور ارسال میکنیم
- Conn.Write([]byte("hello, gofarsi!"))
+ // متن زیر را به سرور ارسال می‌کنیم
+ if _, err := conn.Write([]byte("hello, gofarsi!")); err != nil {
+   panic(err)
+ }

Also rename Conn → conn to follow Go naming conventions.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// یک اتصال به سرور ایجاد میکنیم
Conn, _ := net.DialUDP("udp", nil, &net.UDPAddr{IP: []byte{127, 0, 0, 1}, Port: 3000, Zone: ""})
defer Conn.Close()
// متن زیر را به سرور ارسال میکنیم
Conn.Write([]byte("hello, gofarsi!"))
defer Conn.Close()
// متن زیر را به سرور ارسال میکنیم
Conn.Write([]byte("hello, gofarsi!"))
}
// یک اتصال به سرور ایجاد می‌کنیم
conn, err := net.DialUDP("udp", nil, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"),
Port: 3000,
})
if err != nil {
panic(err)
}
defer conn.Close()
// متن زیر را به سرور ارسال می‌کنیم
if _, err := conn.Write([]byte("hello, gofarsi!")); err != nil {
panic(err)
}
}
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

70-70: Hard tabs
Column: 1

(MD010, no-hard-tabs)


71-71: Hard tabs
Column: 1

(MD010, no-hard-tabs)


73-73: Hard tabs
Column: 1

(MD010, no-hard-tabs)


74-74: Hard tabs
Column: 1

(MD010, no-hard-tabs)


75-75: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🤖 Prompt for AI Agents
In content/chapter 5/5.4-udp-server-begginer.md around lines 70 to 76, the UDP
client code uses a []byte literal for UDPAddr.IP, ignores the error returned by
net.DialUDP, and uses a capitalized Conn identifier; change the IP to a net.IP
(e.g. net.IPv4(127,0,0,1) or net.ParseIP("127.0.0.1")), capture and handle the
(conn, err) returned by net.DialUDP (return or log and exit on error), rename
Conn to conn (lowercase) and defer conn.Close(), and also check the error
returned by conn.Write and handle it.

Comment on lines +139 to +141
json.NewDecoder(r.Body).Decode(&todo)
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Validate request body on Decode.

Show decoding error handling to avoid 200 on malformed JSON.

-json.NewDecoder(r.Body).Decode(&todo)
+if err := json.NewDecoder(r.Body).Decode(&todo); err != nil {
+  http.Error(w, "invalid JSON", http.StatusBadRequest)
+  return
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
json.NewDecoder(r.Body).Decode(&todo)
```
if err := json.NewDecoder(r.Body).Decode(&todo); err != nil {
http.Error(w, "invalid JSON", http.StatusBadRequest)
return
}
🤖 Prompt for AI Agents
In content/chapter 5/5.7-http-server-advanced.md around lines 139–141, the call
json.NewDecoder(r.Body).Decode(&todo) ignores the returned error so malformed
JSON will still return 200; capture and check the error from Decode and return a
400 Bad Request (e.g., via http.Error or w.WriteHeader with a JSON error body)
when decoding fails, optionally validating the decoded struct and
closing/limiting the request body (e.g., via r.Body = http.MaxBytesReader)
before decoding to prevent oversized payloads.

@ja7ad ja7ad merged commit f1645f6 into GoFarsi:main Sep 6, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants