简体   繁体   中英

how to post data in node.js with content type ='application/x-www-form-urlencoded'

I'm having a problem in posting data in node.js with Content-type: 'application/x-www-form-urlencoded'

var loginArgs = {
    data: 'username="xyzzzzz"&"password="abc12345#"',

    //data: {
    //    'username': "xyzzzzz",
    //    'password': "abc12345#",
    //},

    headers: {
            'User-Agent': 'MYAPI',
            'Accept': 'application/json',
            'Content-Type':'application/x-www-form-urlencoded'      
    }   
};

And post request is:

client.post("http:/url/rest/login", loginArgs, function(data, response){
console.log(loginArgs);

if (response.statusCode == 200) {
    console.log('succesfully logged in, session:', data.msg);
}

It always returns username/password incorrect.

In the rest api it is said that the request body should be:

username='provide user name in url encoded
format'&password= "provide password in url encoded format'

request supports application/x-www-form-urlencoded and multipart/form-data form uploads. For multipart/related refer to the multipart API.

application/x-www-form-urlencoded (URL-Encoded Forms)

URL-encoded forms are simple:

const request = require('request');

request.post('http:/url/rest/login', {
  form: {
    username: 'xyzzzzz',
    password: 'abc12345#'
  }
})
// or
request.post('http:/url/rest/login').form({
  username: 'xyzzzzz',
  password: 'abc12345#'
})
// or
request.post({
  url: 'http:/url/rest/login',
  form: {
    username: 'xyzzzzz',
    password: 'abc12345#'
  }
}, function (err, httpResponse, body) { /* ... */ })

See: https://github.com/request/request#forms

Or, using request-promise

const rp = require('request-promise');
rp.post('http:/url/rest/login', {
  form: {
    username: 'xyzzzzz',
    password: 'abc12345#'
  }
}).then(...);

See: https://github.com/request/request-promise#api-in-detail

application/x-www-form-urlencoded requires that you URL encode your Key and Values ( MSDN Documentation ). For illustration:

data:`${encodeURI('username')}=${encodeURI('xyzzzzz')}&${encodeURI('password')}=${encodeURI('abc12345')}`

Request Library has been deprecated , as commented by @Bram.

The example I will write will use the standard HTTPS library which comes with NodeJS.
You could write it as the following (in typescript):

import * as https from 'https';
// import * as http from 'http'; // For HTTP instead of HTTPS

export class ApiExample {

    // tslint:disable-next-line: no-empty
    constructor() { }

    public async postLogin(username: string, password: string): Promise<any> {
        // application/x-www-form-urlencoded requires the syntax "UrlEncodedKey=UrlEncodedValue&UrlEncodedKey2=UrlEncodedValue2"
        const xFormBody = `${encodeURI('username')}=${encodeURI(username)}&${encodeURI('password')}=${encodeURI(password)}`;

        return this.performRequest(xFormBody)
    }

    private performRequest(requestBody: string) {
        return new Promise((resolve, reject) => {

            const options: https.RequestOptions = {
                hostname: 'example.url.com',
                port: 443,
                path: '/login',
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Content-Length': Buffer.byteLength(requestBody)
                }
            };

            // const req = http.request(options, function (res) { // For HTTP
            const req = https.request(options, function (res) {
                // This may need to be modified based on your server's response.
                res.setEncoding('utf8');

                let responseBody = '';

                // Build JSON string from response chunks.
                res.on('data', (chunk) => responseBody = responseBody + chunk);
                res.on('end', function () {
                    const parsedBody = JSON.parse(responseBody + '');

                    // Resolve or reject based on status code.
                    res.statusCode !== 200 ? reject(parsedBody) : resolve(parsedBody);
                });
            });

            // Make sure to write the request body.
            req.write(requestBody);
            req.end();
            req.on('error', function (e) { reject(e); });
        });
    }
}

export default ApiExample;

Use node's URLSearchParams class to encode the js object to "url encoded" form and pass the string as the request body. Documentation

If you are using axios package, Here is the solution.

If you have the headers as Content-type: 'application/x-www-form-urlencoded'

then you will call post API as

const response: any = await axios.post(URL, bodyData,  {
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                }
            });

URL is you API url like http//YOUR_HOST/XYZ..., and

bodyData is the data which you want to send in post API,

Now how will you pass it ?

Suppose you have data as object, so you have to encode it as url, let me show you

let data = {
username: name,
password: password
}

then your bodyData will be like

let bodyData = `username=${name}&password=${password}`

This is the way you can pass your data in body if header is Content-type: 'application/x-www-form-urlencoded'

If you have a huge data which you cannot encode it manually then you can use qs module

run command npm i qs and in your file

const qs = require('qs');

...

let data = {
username: name,
password: password,
manyMoreKeys: manyMoreValues
} 
 
let bodyData = qs.stringify(data);

If you are using got package

const got = require('got');
const qs = require('qs');

const body = qs.stringify({
    a: 'd',
    b: 'b',
    c: 'c',
});

In async function

const response = await got.post(url, { body });

If the Content-Type header is not present, it will be set to application/x-www-form-urlencoded

I think that the got package has built-in functionality that works:

const got = require('got');

const response = await got.post(url, {form: {a: 'd', b: 'b', c: 'c'});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM