Skip to content

[Phase 2] Task 2.2: HTTP Response Construction - #17

Merged
MukhammadIbrokhimov merged 7 commits into
mainfrom
feature/phase-2-2-response-construction
Jun 19, 2026
Merged

[Phase 2] Task 2.2: HTTP Response Construction#17
MukhammadIbrokhimov merged 7 commits into
mainfrom
feature/phase-2-2-response-construction

Conversation

@MukhammadIbrokhimov

Copy link
Copy Markdown
Owner

Task

  • Kanban Task: Task 2.2 — HTTP Response Construction
  • Assignee: Dev B
  • Phase: Phase 2

Description

Adds the Response class — the mirror of the Request parser from 2.1. Where Request decodes a byte stream into fields, Response builds fields into the HTTP/1.1 wire format. serialize() is the only thing the 2.5 server loop needs to hand to the write buffer. Kept I/O-free (no sockets, no Logger) like Request, so it unit-tests as a dependency-free two-file build.

Changes

  • includes/http.hpp: Response declaration (status/headers/body + serialize, httpDate, reasonPhrase)
  • src/http/response.cpp: implementation
    • setStatusCode(code) looks up the reason phrase; setStatusCode(code, reason) is the explicit-reason escape hatch
    • case-insensitive headers (lowercased key, canonical casing on the wire) so duplicate spellings dedupe
    • Content-Length is body-authoritativeserialize() overrides any caller-set value so a wrong length can't desync framing (smuggling guard)
    • Date auto-filled only if the caller didn't pin one; httpDate() hand-rolls RFC 1123 to avoid locale-dependent strftime %a/%b
    • a fresh Response is already a valid empty 200 OK
  • tests/unit/test_response.cpp: 22 framework-free assertions in the test_request.cpp style
  • Makefile: make unit now builds and runs the request and response suites separately; fclean removes both binaries

Testing

  • Compiles without warnings (make re, -Wall -Wextra -Werror -std=c++98)
  • make unit: response 22 passed, 0 failed; request 88 passed, 0 failed
  • Manually serialized a response and verified valid status line, CRLF headers, auto Content-Length/Date, blank line, body
  • Valgrind clean — not run (no valgrind on the dev host; class is RAII-only, no manual allocations)

- Response mirrors Request: builds fields into the HTTP/1.1 wire format
- setStatusCode() with reason-phrase lookup + explicit-reason overload
- case-insensitive headers, canonical casing on output
- Content-Length is body-authoritative (anti-smuggling); Date auto-filled
- httpDate() hand-rolled RFC 1123 to dodge locale-dependent strftime
- I/O-free like Request, so it unit-tests as a dependency-free build

Related to task: 2.2
- framework-free check() suite mirroring test_request.cpp
- covers default 200, reason lookup, case-insensitive headers,
  authoritative Content-Length, auto/preserved Date, httpDate(0) anchor
- make unit now builds+runs request and response suites separately

Related to task: 2.2
Copilot AI review requested due to automatic review settings June 18, 2026 13:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces an HTTP/1.1 Response builder to complement the existing Request parser, enabling the server loop (Phase 2.5) to serialize status/headers/body into wire-format bytes without performing any I/O.

Changes:

  • Add Response class declaration to includes/http.hpp and implement serialization/date/reason-phrase helpers in src/http/response.cpp.
  • Add a new framework-free unit test suite for Response construction and serialization.
  • Extend make unit to build and run request/response unit binaries separately; update kanban status for Task 2.2.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
includes/http.hpp Declares the new Response API (status/headers/body + serialize, httpDate, reasonPhrase).
src/http/response.cpp Implements header canonicalization, serialization, Content-Length override, and Date formatting.
tests/unit/test_response.cpp Adds unit tests validating default response, header behavior, Content-Length/Date behavior, and helper tables.
Makefile Splits unit tests into separate request/response binaries and cleans both on fclean.
kanban.md Marks Task 2.2 as completed and checks off DoD items.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/http/response.cpp
Comment thread src/http/response.cpp
Comment thread src/http/response.cpp
request.cpp and response.cpp had byte-identical copies of the hand-rolled
ASCII lowercaser. Moved both into string_utils.hpp as inline (header lands
in several TUs) and dropped the local statics. make unit now also depends
on string_utils.hpp so editing it retriggers the suites.
config.cpp, parser.cpp and main.cpp each had the same ifstream+rdbuf body.
Pulled it into a non-throwing bool readFileToString -- the three callers
keep their own failure policy (two ConfigException flavours, one cerr+exit),
and 2.3's static handler can reuse it for 404/403. Dropped the now-unused
<fstream> (and <sstream> from main.cpp); rewrote parser.cpp's stale
'copy is cheaper than header churn' comment.
Addresses Copilot review on PR #17:
- setHeader drops any header whose name (CTL/SP/HTAB/':') or value (CTL
  except HTAB) would break framing -- response splitting via a CGI
  passthrough (3.3) or error page. Mirrors what the request parser already
  refuses to accept, at the same boundary.
- two-arg setStatusCode falls back to the table phrase when the reason
  carries a CTL, so attacker bytes can't split the status line.
- httpDate guards a NULL gmtime() (out-of-range time_t); serialize() then
  omits Date rather than emit an empty one. No-crash rule holds.
- 4 new injection tests; tab-in-value kept legal to avoid over-rejecting.

Related to task: 2.2
@MukhammadIbrokhimov
MukhammadIbrokhimov merged commit 7cb7795 into main Jun 19, 2026
2 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