HTTP Status 400 when requesting other node js service

Viewed 230

I have two completely separate services Book and Review written in TypeScript, they have separate Database of their own.

The Book service is running on localhost:3001 The Review service is running on localhost:3000

Problem is when I am trying to request for reviews of each book from my Book service it shows this bad request error,

status: 400
headers: connection=close

The code below calls the api of Review service. For now I am just trying to retrieve the body.

public async getAllBooks(req: Request, res: Response) {
       
        await database.query("Select * from books", {
            type: sequelize.QueryTypes.SELECT,
            model: Book,
            mapToModel: true
        })
        .then(async (books) => {
            res.status(200).json(books);
            for(let i=0; i<books.length; i++) {
                var options = {
                    host: 'localhost',
                    port: 3000,
                    path: `/getReviewByBookId/${books[i].id}`,
                    method: 'GET'
                  };
                  
                  var req = request(options, function(res) {
                    console.log('status: ' + res.statusCode);
                    console.log('headers: ' + stringify(res.headers));
                    res.setEncoding('utf8');
                    res.on('data', function (chunk) {
                      console.log('BODY: ' + chunk);
                    });
                  });
                  
                  req.on('error', function(e) {
                    console.log('problem with request: ' + e.message);
                  });
                  
                  req.write('data\n');
                  req.write('data\n');
                  req.end();
            }
        })
        .catch((error) => {
            console.log(error);
        });
    }

The function that receives this request in the Review service is given below,

public async getReviewByBookId(req: Request, res: Response) {
        const bookId: number | string = req.params.id;

        await database.query(`Select * from reviews where bookId=${bookId}`, {
            type: sequelize.QueryTypes.SELECT,
            model: Review,
            mapToModel: true
        })
        .then((reviews) => {
            console.log(reviews);
            res.status(200).json({reviews: reviews});
        })
        .catch((error) => {
            console.log(error);
        });
    }

What I have found out is the request from Book service reaches the Review service and the above function, because the above function prints all the reviews in the console that it fetched according to the bookId it received from the request of Book service. But the Review service is not returning that result.

Most importantly both services work perfectly fine when I test using Postman

I have checked again and again if request uri is broken as it can cause such error as per HTTP status code definitions. But it seemed to be okay as the Review service is fetching data according to that request.

Also I have enabled cors in my Reviewservice. Allowed all the HTTP OPTIONS.

I am using a 64 bit Kali Linux machine.

Some clue would mean great help. Thanks for your time.

1 Answers

In the above code, you're sending a body with a GET request:

var options = {
    host: 'localhost',
    port: 3000,
    path: `/getReviewByBookId/${books[i].id}`,
    method: 'GET' // <-- It's a GET request
};

var req = request(options, function(res) { ... });


req.write('data\n'); // <-- This writes a request body
req.write('data\n'); // <--
req.end();

You're not generally allowed to do that. To quote the RFC:

A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

It's hard to be sure from the code given here, but it's likely that that's the problem. The server receives the request, it starts processing it (running your function) and then the server receives extra unexpected data so sends a 400 and closes the connection.

You clearly don't need that data, so you should just remove those lines. If you do need to send some data with this request, you need to either include it in the request headers/URL, or change the request to a POST/PUT/etc, so you can include a request body.

(I see it's been a little while since you posted this now, but hopefully this answer is helpful for others with the same problem!)

Related