Challenge #5: Request Data
With the basics of the request/response exchange in place, you’re ready to start looking at the requests and responses in detail. In this challenge, you’ll read the request’s data.
Instructions
1. Set the request’s data:
- Modify the client’s request to send the following metadata:
method: "POST" path: "/my/path" headers: { myRequestHeader: "myRequestValue" }
- And the following body:
"my request body"
.
2. After the server receives the entire request, log the request’s data:
- Log
"SERVER RECEIVED METHOD:"
with the request’s method. It should be"POST"
. - Log
"SERVER RECEIVED PATH:"
with the request’s URL. It should be"/my/path"
. - Log
"SERVER RECEIVED HEADERS:"
with the request’s headers. All the header names will be lower-case, and some headers will be added automatically by Node.js. They should be:{ myrequestheader: 'myRequestValue' host: 'localhost:5001', connection: 'close', 'content-length': '15' }
- Log
"SERVER RECEIVED BODY:"
with the request’s body. It should be"my request body"
.
3. Check your test output. You should see:
SERVER LISTENING
SERVER STARTED
CLIENT SENDING REQUEST
SERVER RECEIVING REQUEST
SERVER RECEIVED ENTIRE REQUEST
SERVER RECEIVED METHOD: POST
SERVER RECEIVED PATH: /my/path
SERVER RECEIVED HEADERS: {
myrequestheader: 'myRequestValue',
host: 'localhost:5001',
connection: 'close',
'content-length': '15'
}
SERVER RECEIVED BODY: my request body
SERVER SENT RESPONSE
CLIENT RECEIVING RESPONSE
CLIENT RECEIVED ENTIRE RESPONSE
EXCHANGE COMPLETE
SERVER CLOSED
SERVER STOPPED
Remember to commit your changes when you’re done.
API Documentation
const clientRequest = http.request({ host, port, method, path, headers });
Start making an HTTP request. Note that the request isn’t complete until request.end()
is called.
- host
(string)
- the server host - port
(number)
- the server port - method
(string)
- the HTTP method - path
(string)
- the HTTP path - optional headers
(object)
- the HTTP headers; defaults to none - returns clientRequest
(http.ClientRequest)
- the request
clientRequest.end(body);
Complete the HTTP request by sending the request body (if any). This function returns immediately, before all the data has been sent.
Important! body
will be ignored if the HTTP method can’t have a body. For example, GET
requests can’t have a body, but POST
requests can.
- optional body
(string)
- the request body
const method = serverRequest.method;
The request’s HTTP method.
- returns method
(string)
- the HTTP method
const url = serverRequest.url;
The request’s URL. This is not a complete URL; just the path and querystring, if any.
- returns url
(string)
- the url
const headers = serverRequest.headers;
The request’s headers. Header names and values are mapped to object names and values.
- returns headers
(object)
- the headers
serverRequest.on("data", fn);
Important: This is a replacement for serverRequest.resume()
.
Run fn
when the server receives body data from the client. Note that the client can send multiple pieces of data, so fn
can be called multiple times. Accumulate it into a string like this:
let data = "";
serverRequest.on("data", (chunk) => {
data += chunk;
}
- fn
((chunk) => void)
- the function to run - chunk
(Buffer)
- the data
JavaScript Primers
No new concepts.
Hints
1
The client request needs to be updated to send the request metadata (method, headers, etc.).
You can use the expanded form of http.request()
to do that.
it("performs request", async () => {
const server = http.createServer();
await new Promise((resolve, reject) => { // add <void> for TypeScript
server.listen(PORT);
server.on("listening", () => {
console.log("SERVER LISTENING");
return resolve();
});
});
console.log("SERVER STARTED");
server.on("request", (serverRequest, serverResponse) => {
console.log("SERVER RECEIVING REQUEST");
serverRequest.resume();
serverRequest.on("end", () => {
console.log("SERVER RECEIVED ENTIRE REQUEST");
serverResponse.end();
console.log("SERVER SENT RESPONSE");
});
});
console.log("CLIENT SENDING REQUEST");
const clientRequest = http.request({
host: HOST,
port: PORT,
method: "POST",
path: "/my/path",
headers: {
myRequestHeader: "myRequestValue",
},
});
clientRequest.end();
await new Promise((resolve, reject) => { // add <void> for TypeScript
clientRequest.on("response", (clientResponse) => {
console.log("CLIENT RECEIVING RESPONSE");
clientResponse.resume();
clientResponse.on("end", () => {
console.log("CLIENT RECEIVED ENTIRE RESPONSE");
resolve();
});
});
});
console.log("EXCHANGE COMPLETE");
await new Promise((resolve, reject) => { // add <void> for TypeScript
server.close();
server.on("close", () => {
console.log("SERVER CLOSED");
return resolve();
});
});
console.log("SERVER STOPPED");
});
2
The client request also needs to send the request body.
You can use the expanded form of clientRequest.end()
to do that.
it("performs request", async () => {
const server = http.createServer();
await new Promise((resolve, reject) => { // add <void> for TypeScript
server.listen(PORT);
server.on("listening", () => {
console.log("SERVER LISTENING");
return resolve();
});
});
console.log("SERVER STARTED");
server.on("request", (serverRequest, serverResponse) => {
console.log("SERVER RECEIVING REQUEST");
serverRequest.resume();
serverRequest.on("end", () => {
console.log("SERVER RECEIVED ENTIRE REQUEST");
serverResponse.end();
console.log("SERVER SENT RESPONSE");
});
});
console.log("CLIENT SENDING REQUEST");
const clientRequest = http.request({
host: HOST,
port: PORT,
method: "POST",
path: "/my/path",
headers: {
myRequestHeader: "myRequestValue",
},
});
clientRequest.end("my request body");
await new Promise((resolve, reject) => { // add <void> for TypeScript
clientRequest.on("response", (clientResponse) => {
console.log("CLIENT RECEIVING RESPONSE");
clientResponse.resume();
clientResponse.on("end", () => {
console.log("CLIENT RECEIVED ENTIRE RESPONSE");
resolve();
});
});
});
console.log("EXCHANGE COMPLETE");
await new Promise((resolve, reject) => { // add <void> for TypeScript
server.close();
server.on("close", () => {
console.log("SERVER CLOSED");
return resolve();
});
});
console.log("SERVER STOPPED");
});
3
You’re ready to log the request metadata in the server.
You can use serverRequest.method
, serverRequest.url
, and serverRequest.headers
to do that.
They should go in the serverRequest.on("end", ...)
event handler.
it("performs request", async () => {
const server = http.createServer();
await new Promise((resolve, reject) => { // add <void> for TypeScript
server.listen(PORT);
server.on("listening", () => {
console.log("SERVER LISTENING");
return resolve();
});
});
console.log("SERVER STARTED");
server.on("request", (serverRequest, serverResponse) => {
console.log("SERVER RECEIVING REQUEST");
serverRequest.resume();
serverRequest.on("end", () => {
console.log("SERVER RECEIVED ENTIRE REQUEST");
console.log("SERVER RECEIVED METHOD:", serverRequest.method);
console.log("SERVER RECEIVED PATH:", serverRequest.url);
console.log("SERVER RECEIVED HEADERS:", serverRequest.headers);
serverResponse.end();
console.log("SERVER SENT RESPONSE");
});
});
console.log("CLIENT SENDING REQUEST");
const clientRequest = http.request({
host: HOST,
port: PORT,
method: "POST",
path: "/my/path",
headers: {
myRequestHeader: "myRequestValue",
},
});
clientRequest.end("my request body");
await new Promise((resolve, reject) => { // add <void> for TypeScript
clientRequest.on("response", (clientResponse) => {
console.log("CLIENT RECEIVING RESPONSE");
clientResponse.resume();
clientResponse.on("end", () => {
console.log("CLIENT RECEIVED ENTIRE RESPONSE");
resolve();
});
});
});
console.log("EXCHANGE COMPLETE");
await new Promise((resolve, reject) => { // add <void> for TypeScript
server.close();
server.on("close", () => {
console.log("SERVER CLOSED");
return resolve();
});
});
console.log("SERVER STOPPED");
});
4
Now log the request’s body.
You can use serverRequest.on("data", ...)
to do that.
It takes the place of serverRequest.resume()
.
it("performs request", async () => {
const server = http.createServer();
await new Promise((resolve, reject) => { // add <void> for TypeScript
server.listen(PORT);
server.on("listening", () => {
console.log("SERVER LISTENING");
return resolve();
});
});
console.log("SERVER STARTED");
server.on("request", (serverRequest, serverResponse) => {
console.log("SERVER RECEIVING REQUEST");
let body = "";
serverRequest.on("data", (chunk) => {
body += chunk;
});
serverRequest.on("end", () => {
console.log("SERVER RECEIVED ENTIRE REQUEST");
console.log("SERVER RECEIVED METHOD:", serverRequest.method);
console.log("SERVER RECEIVED PATH:", serverRequest.url);
console.log("SERVER RECEIVED HEADERS:", serverRequest.headers);
console.log("SERVER RECEIVED BODY:", body);
serverResponse.end();
console.log("SERVER SENT RESPONSE");
});
});
console.log("CLIENT SENDING REQUEST");
const clientRequest = http.request({
host: HOST,
port: PORT,
method: "POST",
path: "/my/path",
headers: {
myRequestHeader: "myRequestValue",
},
});
clientRequest.end("my request body");
await new Promise((resolve, reject) => { // add <void> for TypeScript
clientRequest.on("response", (clientResponse) => {
console.log("CLIENT RECEIVING RESPONSE");
clientResponse.resume();
clientResponse.on("end", () => {
console.log("CLIENT RECEIVED ENTIRE RESPONSE");
resolve();
});
});
});
console.log("EXCHANGE COMPLETE");
await new Promise((resolve, reject) => { // add <void> for TypeScript
server.close();
server.on("close", () => {
console.log("SERVER CLOSED");
return resolve();
});
});
console.log("SERVER STOPPED");
});
Complete Solution
Test code (JavaScript):
it("performs request", async () => {
const server = http.createServer();
await new Promise((resolve, reject) => {
server.listen(PORT);
server.on("listening", () => {
console.log("SERVER LISTENING");
return resolve();
});
});
console.log("SERVER STARTED");
server.on("request", (serverRequest, serverResponse) => {
console.log("SERVER RECEIVING REQUEST");
let body = "";
serverRequest.on("data", (chunk) => {
body += chunk;
});
serverRequest.on("end", () => {
console.log("SERVER RECEIVED ENTIRE REQUEST");
console.log("SERVER RECEIVED METHOD:", serverRequest.method);
console.log("SERVER RECEIVED PATH:", serverRequest.url);
console.log("SERVER RECEIVED HEADERS:", serverRequest.headers);
console.log("SERVER RECEIVED BODY:", body);
serverResponse.end();
console.log("SERVER SENT RESPONSE");
});
});
console.log("CLIENT SENDING REQUEST");
const clientRequest = http.request({
host: HOST,
port: PORT,
method: "POST",
path: "/my/path",
headers: {
myRequestHeader: "myRequestValue",
},
});
clientRequest.end("my request body");
await new Promise((resolve, reject) => {
clientRequest.on("response", (clientResponse) => {
console.log("CLIENT RECEIVING RESPONSE");
clientResponse.resume();
clientResponse.on("end", () => {
console.log("CLIENT RECEIVED ENTIRE RESPONSE");
resolve();
});
});
});
console.log("EXCHANGE COMPLETE");
await new Promise((resolve, reject) => {
server.close();
server.on("close", () => {
console.log("SERVER CLOSED");
return resolve();
});
});
console.log("SERVER STOPPED");
});
Test code (TypeScript):
it("performs request", async () => {
const server = http.createServer();
await new Promise<void>((resolve, reject) => {
server.listen(PORT);
server.on("listening", () => {
console.log("SERVER LISTENING");
return resolve();
});
});
console.log("SERVER STARTED");
server.on("request", (serverRequest, serverResponse) => {
console.log("SERVER RECEIVING REQUEST");
let body = "";
serverRequest.on("data", (chunk) => {
body += chunk;
});
serverRequest.on("end", () => {
console.log("SERVER RECEIVED ENTIRE REQUEST");
console.log("SERVER RECEIVED METHOD:", serverRequest.method);
console.log("SERVER RECEIVED PATH:", serverRequest.url);
console.log("SERVER RECEIVED HEADERS:", serverRequest.headers);
console.log("SERVER RECEIVED BODY:", body);
serverResponse.end();
console.log("SERVER SENT RESPONSE");
});
});
console.log("CLIENT SENDING REQUEST");
const clientRequest = http.request({
host: HOST,
port: PORT,
method: "POST",
path: "/my/path",
headers: {
myRequestHeader: "myRequestValue",
},
});
clientRequest.end("my request body");
await new Promise<void>((resolve, reject) => {
clientRequest.on("response", (clientResponse) => {
console.log("CLIENT RECEIVING RESPONSE");
clientResponse.resume();
clientResponse.on("end", () => {
console.log("CLIENT RECEIVED ENTIRE RESPONSE");
resolve();
});
});
});
console.log("EXCHANGE COMPLETE");
await new Promise<void>((resolve, reject) => {
server.close();
server.on("close", () => {
console.log("SERVER CLOSED");
return resolve();
});
});
console.log("SERVER STOPPED");
});
No production code yet.