notansandwich
notansandwich

Reputation: 69

Can I use res.send(foo) twice?

I want to send my token and my user's role to my login.component.ts.

When I was trying to find the problem, in my research I came across someone's suggestion to use

res.write(foo1)
res.write(foo2)
res.end

Instead of

res.send(foo1)
res.send(foo2)

But that didn't work. I then tried using this to test it:

res.write(foo1)
res.end()

But this is giving me an error:

events.js:174

  throw er; // Unhandled 'error' event
  ^

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string or Buffer. Received type object
    at write_ (_http_outgoing.js:595:11)
    at ServerResponse.write (_http_outgoing.js:567:10)
    at User.findOne (C:\Users\notan\GitHub\se3316-notansandwich-lab5\server\controllers\user.controller.js:46:33)
    at C:\Users\notan\node_modules\mongoose\lib\model.js:4604:16
    at C:\Users\notan\node_modules\mongoose\lib\query.js:4348:12
    at process.nextTick (C:\Users\notan\node_modules\mongoose\lib\query.js:2850:28)
    at process._tickCallback (internal/process/next_tick.js:61:11)
Emitted 'error' event at:
    at C:\Users\notan\node_modules\mongoose\lib\model.js:4606:13
    at C:\Users\notan\node_modules\mongoose\lib\query.js:4348:12
    at process.nextTick (C:\Users\notan\node_modules\mongoose\lib\query.js:2850:28)
    at process._tickCallback (internal/process/next_tick.js:61:11)

This is my user.controller.js, which I use in my route.js which is used in my sever.js

const User = require('../models/user.model')
const jwt = require('jsonwebtoken')

exports.user_create = function (req, res, next) {
    let user = new User(
        {
            _id: Math.random().toString(36).substr(2, 5), // generate a random ID
            email: req.body.email,
            password: req.body.password,
            firstName: req.body.firstName,
            lastName: req.body.lastName,
            role: "user"
        }
    );

    user.save(function (err, registeredUser) {
        if (err) {
            return next(err);
        } 
        else {
            let payload = { subject: registeredUser._id}
            let token = jwt.sign(payload, 'secretKey')
            res.status(200).send({token})
        }

    })
}

exports.user_login = function (req, res, next) {
    let userData = req.body
    User.findOne({email: userData.email}, (err, user) => {
        if (err) {
            console.log(err)
        } 
        else {
            if (!user) {
                res.status(401).send('Invalid email')
            } 
            else if (user.password !== userData.password) {
                res.status(401).send('Invalid password')
            }
            else {
                let payload = {subject: user._id}
                let token = jwt.sign(payload, 'secretKey')
                //res.status(200).send({token})
                res.status(200).write({token})
                //let role = this.user.role
                // res.status(200).write({role})
                res.end()
            }
        }
    })
}

Using this works

res.status(200).send({token})

But this does not

res.status(200).write({token})
res.end()

Upvotes: 3

Views: 4520

Answers (4)

jfriend00
jfriend00

Reputation: 707786

In response to the title of your question:

Can I use res.send(foo) twice?

No, you cannot call that twice for the same request.

See the second part of the answer since the OP changed their question after I wrote this first part

In Express, you can only use res.send() or res.json() or res.end() once per request. When you execute those, it sends the request. If you try to send more on the same request, it will do nothing and will show a warning in Express.

res.write() can be called more than once, then followed by res.end() when you are finally done with the request.

In your example:

res.status(200).send({token})
res.end()

The res.send() already calls .end() for you so trying to call it again is considered an error because the request has already been sent.


FYI, .status(200) is not necessary. The default status is already 200 so res.send({token}) will already have a 200 status.


More Recent Answer for the Modified Question

Now that you've completely changed the question to be about res.write({token}), that does not work because res.write() requires a String or a Buffer as an argument and you were giving it an object. You would have to manually convert the object to JSON yourself:

res.type('application/json');
res.write(JSON.stringify({token}));
res.end();

And note that this also sets the appropriate content type. If your object is large with res.write() you may also have to pay attention to the write buffer being full and listen for the drain event. res.write() is a much lower level facility (it's at the http level, not at the Express level) than the Express functions for sending data.

Built into Express, you can use res.send() or res.json() which are Express methods that will both that you passed an object, automatically convert it to JSON for you and set the content type to JSON also. It will also handle any buffer full issues in the write stream too.

res.send({token});

or, I prefer to be more explicit in my Express code with:

res.json({token});

And, if you're trying to send multiple pieces of data, you can put them into the same object:

res.json({token, role});

Upvotes: 8

Dimitri Lavrenük
Dimitri Lavrenük

Reputation: 4879

If you want to use res.write(argument) you have to pass the argument as a string or Buffer, just like the error message says. To get the same effect just convert your response object to a string:

res.status(200).write(JSON.stringify({token}))

Upvotes: 0

Kwame Opare Asiedu
Kwame Opare Asiedu

Reputation: 2345

Calling res.status(200).send({ token }) ends the request and sends the object back to the client...

Since the request is now ended... Calling res.end() generates the error...

You'd usually use res.end if u were piping some data (usually binary) after several res.write to close the pipe...

For more info... checkout Express' docs in the response object...

https://expressjs.com/en/api.html#res

Also... U can't send an object using res.write...

From your error... it says that it inly accepts a string or buffer. If u want to send plain objects... res.send or res.json would be more appropriate...

Upvotes: 1

notansandwich
notansandwich

Reputation: 69

I found the solution: I can send multiple things in an res.send(...)

res.status(200).send({token, role})

Upvotes: 0

Related Questions