0

I have this server.js code:

const bodyParser = require('body-parser');
const cors = require('cors');
const morgan = require('morgan');


var express = require('express')
    , http = require('http')
    , https = require('https')
    , app = express();
app.use(morgan('combined'));
app.use(bodyParser.json());
app.use(cors());

http.createServer(app);
https.createServer({  }, app);

app.get('/', (req, res) => {
    res.json({message: "Home"})
});

app.get('/test', (req, res) => {
    res.json({message: "Testing..."})
});

app.post('/token', (req, res) => {
    var clientId = req.body.client_id;
    var clientSecret = req.body.client_secret;

    if (clientId === 'admin' && clientSecret === 'admin') {
        res.json({message: "Your token is 123456"});
    }
    else  {
        res.json({message: "Not allowed!"});
    }
})

app.listen(process.env.PORT || 8081);

And this client.js code:

const http = require("http");
const querystring = require("querystring");

function getTestHome()  {
    const options = {
        method: "GET",
    }
    const token_endpoint = "http://localhost:8081/";
    const token_request = http.request(token_endpoint, options);
    token_request.once("error", err => {throw err});
    token_request.once("response",
        (token_stream) =>
            getFromStream(token_stream));
    token_request.end();
}

function getTestToken()  {
    const  parameters = {
        "grant_type": "client_credentials",
        "client_id": "admin",
        "client_secret": "admin"
    };

    const post_data = querystring.stringify(parameters);
    const options = {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        method: "POST",
        body: post_data
    }
    const token_endpoint = "http://localhost:8081/token";
    const token_request = http.request(token_endpoint, options);
    token_request.once("error", err => {throw err});
    token_request.once("response",
        (token_stream) =>
            getFromStream(token_stream));
    token_request.write(post_data);
    token_request.end();
}

function getFromStream(stream)  {
    let body = "";
    stream.on("data", piece => body += piece);
    stream.on("end", () => console.log(body));
}

getTestHome();  //{"message":"Home"}
getTestToken();  //{"message":"Not allowed!"}

I'm trying to send requests to / (GET request with no parameters) and /token (POST request with body JSON data).

The GET request goes through fine and I get the

{"message":"Home"}

message.

However despite me sending the correct client_id and client_secret in the POST request, I get the

{"message":"Not allowed!"}

message back.

I tried using debugger on the server.js and I can see that the req.body.client_id and req.body_client_secret are undefined:

enter image description here

What am I doing wrong and how do I fix it?

The correct output would have been

{"message":"Home"}
{"message": "Your token is 123456"}

PS The POST request works fine in Postman:

enter image description here

EDIT:

I think I got it.

Adding

app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies

to server.js solved it.

But I'd like to know if there is a way to solve it in client.js only? In case I wouldn't have had access to the server code?

parsecer
  • 4,758
  • 13
  • 71
  • 140

1 Answers1

1

Exactly as you point at your edit, you needed to add:

app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies

This is because on your client-side, you are sending the data as:

Content-type: application/x-www-form-urlencoded

Which makes express to need that extra line of code to get data at req.body (because of how the data is being sent).

On the other hand, when you are doing by Postman, you are explicitly setting the content-type as a JSON raw, which puts the header of the request automaticaly as:

Content-type: application/json

Postman Content-type header

So, what you could do at client side is exactly that: put content type as application/json, and send the data as a JSON:

function getTestToken() {
    const parameters = {
        "grant_type": "client_credentials",
        "client_id": "admin",
        "client_secret": "admin"
    };

    const options = {
        headers: { 'Content-Type': 'application/json' },
        method: "POST",
    }
    const token_endpoint = "http://localhost:8081/token";
    const token_request = http.request(token_endpoint, options);
    token_request.once("error", err => { throw err });
    token_request.once("response",
        (token_stream) =>
        getFromStream(token_stream));
    token_request.write(JSON.stringify(parameters));
    token_request.end();
}

You can take that approach at the client side without modifying the server's code. With that approach, you also can skip the importing of the querystring module.