Node.js as Web-server: createServer(), writeHead() method; reading Query String, Split Query String

A real Node web server answers by reading the question: writeHead labels the response, req.url carries the visitor's query string, and url.parse(req.url, true).query splits it into a ready object.

11 min read · 9 cards · 2 checks

Read in: English · हिन्दी · ગુજરાતી


Theory

The server that never listens

Your 5-line server has one social flaw: it says the same thing to everyone. Ask for the schedule, the seat count, or day 2's events: same greeting.

A real web server READS the question before answering. And the question, you already know from Unit 4's GET lessons, travels in the URL:

localhost:8080/?event=garba&day=2

Everything after the ? is the query string, and today the server finally learns to split and answer it.

Theory

writeHead: label before body

res.writeHead(200, { 'Content-Type': 'text/html' });

The first thing a response declares: the status code (200 OK, 404 Not Found: the very codes your AJAX guard checked!) and headers, chiefly Content-Type:

  • text/html: the browser renders what follows as a page
  • application/json: the answer is API data: exactly what an AJAX caller's JSON.parse expects

Order law: writeHead comes before any write or end: you cannot label an envelope after it is sealed.

Theory

Splitting the query string

A visit to /?event=garba&day=2 lands in your callback with req.url holding exactly that text. You COULD split it by hand (chop at ?, split on &, split on =), but Node's built-in url module does it properly:

const q = url.parse(req.url, true).query;

  • url.parse(req.url, true) dissects the URL; the true asks for the query as a parsed OBJECT
  • its .query property is then { event: 'garba', day: '2' }

Note the quotes on '2': query values arrive as strings, the same convert-before-maths rule as every input so far.

Practical

The server that answers the question

const http = require('http');
const url = require('url');

http.createServer(function (req, res) {
    res.writeHead(200, { 'Content-Type': 'text/html' });

    const q = url.parse(req.url, true).query;   // split the query string

    if (q.event == "garba") {
        res.write('<h1>Garba Night</h1>');
        res.write('<p>Day ' + q.day + ', Main Ground, 40 seats left</p>');
    } else {
        res.write('<p>Ask me with ?event=garba&day=2</p>');
    }
    res.end();
}).listen(8080);

// Visit:  localhost:8080/?event=garba&day=2
// Answer: Garba Night, Day 2, Main Ground, 40 seats left

This example runs in Gri-Learn on the web, where you can edit it and see the output.

Quiz

The visitor opens localhost:8080/?event=garba&day=2. What does url.parse(req.url, true).query return?

  1. The string "?event=garba&day=2", unchanged
  2. The object { event: 'garba', day: '2' }, with values as strings
  3. The object { event: 'garba', day: 2 }, with day as a number
  4. An array: ['garba', '2']
Show the answer

The object { event: 'garba', day: '2' }, with values as strings

With true as the second argument, parse splits the query into a ready object keyed by parameter names: q.event and q.day just work. The subtlety option C misses: values are ALWAYS strings: '2', not 2: URLs carry text, so arithmetic on q.day needs parseInt first, the same lesson TextBoxes and InputBoxes taught. Option A is what req.url gives you BEFORE parsing (well, with the / prefix). Option D loses the names, which are the whole point: parameters answer by name, not position.

Think first

Close the full-stack loop

Unit 4's live search sent xhr.open('GET', 'search.php?q=g'). Rewrite the server side in your head: what should THIS Node server do differently from the listing to serve that AJAX caller: think Content-Type and response format, then tap.

Show the answer

Two changes: writeHead sends application/json (the caller will JSON.parse, not render), and the body becomes a JSON string: filter the events whose names contain q.q, then res.end(JSON.stringify(matches)). The browser side you wrote in Unit 4 needs ZERO changes: its responseText now arrives from YOUR server. That is the full stack in one language: the AJAX engine asks, the event loop answers, JSON in between: and you have personally written every piece of that sentence.

Watch out

Web-server slips

writeHead after write: headers cannot follow body: ERR_HTTP_HEADERS_SENT: label first, always.

Maths on query values: q.day + 1 is '21' territory: parseInt(q.day) first.

Trusting the query blindly: q.event might be missing (undefined) or nonsense: branch defensively, as the listing's else does. Every visitor-supplied value is a guest, not family.

Theory

One lesson left in the subject

The server now listens, splits and answers: but it still remembers nothing: every restart forgets all registrations. The finale gives Node a memory: the fs module: reading, creating, updating, deleting and renaming FILES: registrations written to disk at last, and FestConnect Live complete from XML to a persistent server.

Summary

Key takeaways

  • writeHead(status, headers) labels the response BEFORE any body: 200/404, and Content-Type text/html vs application/json.
  • The visitor's query string rides req.url: /?event=garba&day=2.
  • url.parse(req.url, true).query splits it into a ready object: q.event, q.day.
  • Query values are strings: parseInt before arithmetic.
  • Branch on the query to answer personally; guard against missing parameters.
  • Swap Content-Type to application/json + JSON.stringify, and this server answers Unit 4's AJAX unchanged.
  • Memory hook: label the envelope, split the question, answer by name.

Study this properly

This page is the lesson to read. In Gri-Learn the same topic is a graded deck: the self-checks are scored and your weak topics are tracked. Free to start.

Start this topic

Already have an account? Sign in

More from Node.js

Gri-Learn · syllabus-mapped B.C.A. lessons in English, Hindi and Gujarati

Node.js as Web-server: createServer(), writeHead() method; reading Query String, Split Query String · Web Designing-2 (option A) · Gri-Learn