Difference between response.setHeader and response.writeHead? - javascript

In my application, I have my Nodejs server send a JSON response. I found two ways to do this but I'm not sure what the differences are.
One way is
var json = JSON.stringify(result.rows);
response.writeHead(200, {'content-type':'application/json', 'content-length':Buffer.byteLength(json)});
response.end(json);
And my other way is
var json = JSON.stringify(result.rows);
response.setHeader('Content-Type', 'application/json');
response.end(json);
Both ways work and I'm just wondering what the difference is between the two and when I should use one over the other.

response.setHeader() allows you only to set a singular header.
response.writeHead() will allow you to set pretty much everything about the response head including status code, content, and multiple headers.
Consider the NodeJS docs:
response.setHeader(name, value)
Sets a single header value for implicit headers. If this header already exists in the to-be-sent headers, its value will be replaced. Use an array of strings here to send multiple headers with the same name.
var body = "hello world";
response.setHeader("Content-Length", body.length);
response.setHeader("Content-Type", "text/plain");
response.setHeader("Set-Cookie", "type=ninja");
response.status(200);
response.writeHead(statusCode[, statusMessage][, headers]))
Sends a response header to the request. The status code is a 3-digit HTTP status code, like 404. The last argument, headers, are the response headers. Optionally one can give a human-readable statusMessage as the second argument.
var body = "hello world";
response.writeHead(200, {
"Content-Length": body.length,
"Content-Type": "text/plain",
"Set-Cookie": "type=ninja"
});

Related

Javascript object coming through empty on server side

I have a client-side script running to send the string "Y" to the server. I set up a console.log on the client-side (which you can see below) and another on the server-side. The one on the client-side works, but the one logs an "empty" object.. it just shows "{}".
How do I get my data to stay in the object?
const status = "Y";
const options = {
method: 'POST',
headers: {
'Content-type': 'application/json'
},
body: status
fetch('/events/<%- event.id %>/prompt', options)
console.log(options.body)
Here's my route for context:
router.route('events/:id/prompt')
.get(catchAsync(events.showPrompt))
.post(catchAsync(events.checkIn))
And my controller:
module.exports.checkIn = async(req, res) => {
console.log(req.body);
}
How do I get the object to come through to the server?
For sending "y" as the content and receiving that in Express, you need two things:
You need to make sure the content-type is set to text/plain on the request.
You need the appropriate middleware that will read that text/plain body.
app.use(express.text())
Then, you will find the body in req.body within any express request handler registered after the above middleware.
You could pick different content-types also such as application/json, the corresponding middleware for that content-type app.use(express.json())` and then format the body data in that format.
It's important to realize that Express does not by itself read the body of an incoming request. It reads the headers, but not the body by default. If you want the body to be read, then you need middleware that is looking for whatever content-type the incoming request has, reads the body, parses it from whatever it's format is and puts the resulting parsed data into req.body. Express comes with a number of built-in middleware for popular content-types.
Status is a string. However body have to take a object with key-value pair. If send like with like below, then you get object which contains status on the backend side.
body: {status: status}
Problem from :
Client : you choose Content-type': 'application/json' , so your body must be json format , something like body : { status } . Make sure you sent exact object with browser debug , because some call api package can change value of request.
Server : Some nodejs framework need parse the value is sent from client before read it (Exp : app.use(express.json()) with Express)

Access response body after multiple res.write()s

How do I access the response body after doing multiple res.write()s? Simplified example:
endpoint(req, res) {
res.set('Content-Type', 'application/json')
res.write('{"resdata":')
//Stream data, format it, and then add to the response
res.write(stream1)
res.write(', "resdata2":')
//Stream some other data, format it, and then add to the response:
res.write(stream2)
res.write('}')
var savedBody = res.getBody() //Is there a way to extract the response body here from all the res.writes()?
res.end()
doSomethingElseWithResponseBody(savedBody)
}
Technically, I could create my own JSON and then do a single res.send at the end -- I know -- but in the specific implementation of this, it's very difficult to use that method; the res.writes() need to be kept.
Appreciate any tips!

Sending and recieving plain text instead of an object with node http

I'm incredibly new at trying to do anything relating to webservers and the like and I've gotten stuck trying to send data from a javascript that runs on a website to a server that runs locally. I've been able to get them to communicate, but all the data I get on the server is always just "[object object]" instead of the string that I send from the browser.
This is how the server is looking currently, very bareboned:
http.createServer(function(request, response){
response.writeHead(200, {"Content-Type": "text/plain"});
console.log("request recieved: " + response + request);
}).listen(8001);
And this is what i send from the browser:
var url = "http://localhost:8001";
$.ajax({
url: url,
type: "POST",
data: "Hello friend",
contentType: "text/plain",
});
I've also tried something like this which results in the same problem:
var http = new XMLHttpRequest();
var sendData = "HELLO";
http.open("POST", "http://localhost:8001", true);
http.setRequestHeader("Content-type", "text/plain");
http.send(sendData);
I've also tried to use JSON.stringify on the server-side to try to get the string, but this returns an error stating that it cannot be used on a 'circular object'.
I'm sorry if this question is really stupid, as I said, I'm a complete beginner and this is the first time I've tried to do something remotely similar. I've tried researching what to do differently, but after trying countless options I felt that I needed to ask here instead.
Thanks in advance! And if any more information is needed I'd be happy to try to expand on the issue!
When you use concatenation (+) operator then javascript will convert object to string. Default String representation of object is [object object]. That's why it's printing [object object].
http.createServer(function(request, response){
response.writeHead(200, {"Content-Type": "text/plain"});
console.log("request recieved: " , response , request);
}).listen(8001);
And if you want to get the body then you have the listen to data event and consume the data.
http
.createServer(function(request, response) {
let body = "";
request.on("data", chunk => {
body += chunk.toString(); // convert Buffer to string
});
request.on("end", () => {
console.log(body);
response.end('ok');
});
})
.listen(8001);
I will recommend to use express package to avoid all boilerplate code.
You can access the body with request.body. You can't JSON.stringify the whole request because, as you saw, it holds ciruclar deps, but you can do so with the request.body.

Programmatically setting http request headers in javascript for Content-Type

I'm writing some code to handle sending post data for my application and I wanted to make it so that I can send custom headers from another function if I need them. My question is, can I default something like "Content-Type" the way my code example does below and then overwrite it, or do I need to check the custom headers being sent, and if Content-type is not set, set it to the default. Basically, during the creation of the post request, can you overwrite headers programmatically?
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.setRequestHeader("Content-length", formData.length);
// check for custom headers
if ((headers !== null) && (headers !== undefined)) {
for(var k in headers) {
if(headers.hasOwnProperty(k) {
xmlhttp.setRequestHeader(k.toString(), headers[k]);
}
}
}
I'm sending a different "Content-Type" like JSON perhaps in the "headers" object. If I do setRequestHeader on Content-Type again does it overwrite or does it send 2 content-type headers in the post request?
edit: I don't know why I asked this on StackOverflow, I just realized I could probably test this by logging my headers with a form handler, which I'm off to do, I'll leave the question up anyway.
According to MDN:
Sets the value of an HTTP request header. You must call
setRequestHeader()after open(), but before send(). If this method is
called several times with the same header, the values are merged into
one single request header.
So calling setRequestHeader() multiple times will yield the following:
Content-Type: application/x-www-form-urlencoded, application/json

Sending two objects as response to a single GET request using Express and Node.js

I have the following piece of code -
sendServer.get('/download',function(request,response){
var status="SELECT * from poetserver.download where status='0'";
console.log(status)
connection.query(status,function(error,rows){
var toSend=rows[0].id
response.sendfile('./testimages/'+toSend+'.PNG')
// var details={"pictureId":toSend}
// response.writeHead(200, { 'Content-Type': 'application/json' });
// response.send(JSON.stringify(details));
Essentially I, first, want to send a file as identified by toSend. The file is successfully sent using response.sendFile. But I also want to provide some identification of the file for the client for future responses. How do I send that too?
To send an id for the image (ressource) that you are responding with, you should use a HTTP header such as ETag. Do not try to send JSON and binary data in one response body.

Categories

Resources