14

I have a express API which allows json post requests. However, in my scenario, one of my API's needs to accept a XML post body, rather than a JSON one.

So my express app is set fine using:

// Init App
var app = express();

// BodyParser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));

And here is an example of my POST api JSON route:

router.post('/', function(req, res, next) {
  defaultPoll.create(req.body, function(err, post) {
    if (err) { console.log(err)
    } else {res.json(post);
  }
  });
});

Which works great when I pass in my json values e.g. this is my Post request:

{
    "milliseconds":"600"
}

But now I have an API where I want to do a POST request, but my POST request needs to be send of as XML. So this is what my API looks like:

router.post('/test', function(req, res) {
    var body = req
    console.log(body)
});

Nothing complicated as im not getting anything back. This is how I do the POST request:

<?xml version="1.0"?>
<methodCall>
   <methodName>myMethod</methodName>
    <params>
      <param>
         <value><string>hello</string></value>
      </param>
   </params>
</methodCall>

However, my body comes back empty. Any idea how I can fix this? Ideally, I would like to take this XML request, and then respond with an XML of my choice too. What is the best way to do this?

Take the request, convert into JSON, write JSON response and convert back to a XML response?

Any help will be appreciated!

5 Answers 5

22

bodyParser only supports the following formats (if it is body-parser you're using):

  • JSON body parser
  • Raw body parser
  • Text body parser
  • URL-encoded form body parser

So if you want to parse XML I suggest you use express-xml-bodyparser

var xmlparser = require('express-xml-bodyparser');
app.use(xmlparser());

app.post('/test', function(req, res, next) {
  // req.body contains the parsed xml 
});

I hope this might help you in the right direction

Sign up to request clarification or add additional context in comments.

5 Comments

is it possible just to do that for one API route though? Bearing in mind I have a lot of JSON routes, and just require this one XML one
from the documentation, it looks like you can have both, and express will see the content type of the request and use the correct one. npmjs.com/package/express-xml-bodyparser This is a guess though
I use both parsers in my API and both works. express-xml-bodyparser detects content by mime type.
@R.Gulbrandsen The npm page says "parse raw xml body", so, if we just use body.parser.raw({ type: "application/xml" }) and convert the buffer we get in the body to string, shouldn't we get the xml string?
Sorry, I dont know the answer for this by heart.
3

I know it's lot late but, If you want to use both xml and json, you can use it with specific xml request like this,

app.post('/receive-xml', xmlparser({trim: false, explicitArray: false}), function(req, res, next) {
  // check req.body  
});

Comments

3

The body is a readable stream and can be composed of chunks.

You can do something like this in the handler.

let body = "";
let response = {}; 
if (req.method === "POST") {
        req.on("data", chunk => {
            body += chunk.toString();
        });
        req.on("end", () => {
            response.message = "Success";
            response.data.length = body.length;
            return res.status(200).json(response);
        });
    }

Comments

3

router.use(bodyparser.raw({ type: 'application/xml' })); XML body will be parsed and it'll be in Buffer format. In the route you can do something like this new Buffer(req.body.data).toString() to get the original request body.

2 Comments

new Buffer(req.body.data).toString(); is deprecated. use Buffer.from(req.body.data, 'utf-8').toString('base64'); instead
that was an old answer Hem!
0

I believe you would be able to use it different routes

appRoute1.js

const express = require('express');
const router = express.Router();
const bodyParse = require('body-parser');
const cookieParser = require('cookie-parser');

const xmlparser = require('express-xml-bodyparser');
 router.use(xmlparser());

router.use(bodyParse.json());
router.use(bodyParse.urlencoded({extended:true}));
router.use(cookieParser());

router.use((req, res, next)=>{
    if(req.header('Content-Type').endsWith("xml")){
        parser.parseString(req.body, (err, data)=>{
            console.log('xml data',data);
            next();
        })
    }
    next();
});
//router.use(courseRequestInterceptor);
router.get('/test', (req,res, next)=>{
    console.log('Inside router test', req);

    //write a sample cookie to be sent to client
    res.cookie('testCookieKey', 'testCookieValue');
    res.write(JSON.stringify({id:1, test:'test'}, null, 2));
    res.end();
}),
router.post('/v1/postSampleCourse',(req,res, next)=>{
    console.log('cookies', req.cookies);


    res.cookie('appName', 'server_demo');
    debugger;
    //maybe add a validation like Joi validation for the input data
    res.write(JSON.stringify(['record created successfully', req.headers, 
    req.body.id], null, 2));
    res.end();

});



module.exports = router;

appRoute2.js

const express = require('express');
const router = express.Router();
//const constants = require('./../utils/constants');
const bodyParser = require('body-parser');

router.use(bodyParser.json());
router.use(bodyParser.urlencoded({extended:true}));
module.exports = router;

router.get('/addHeaders', (req, res, next)=>{
    req.headers['testHeader']='testHeaderValue';
    //req.accepts() gets the Accept content negotiation of the incoming request, exaple if its xml or json, or ecmascript
    // or stream
    //req.header() requires a name of the header to see
    console.log(req);
    console.log('request headers', req.header('origin'));
    res.header('testHeaderResponseKey', 'testHeaderResponseValue');
    //
    res.write(JSON.stringify({id:1}));
    //u can either do res.end() which will end the response and generate the result
    // or pipe the response and call next() which will also end the result
    req.pipe(res);
    next();
} )

Exec.js

const process = require('process');
const _ = require('lodash');
const util =require('util');
const express = require('express');
const app  = express();

const bodyParser = require('body-parser');
//Extract arugments from command line
const argumentExtractor = require('./utils/argumentExtrator');

//make use of constants
const constants = require('./utils/constants');

//sample to make use of cors router
// const corsRouter = require('./controllers/corsRoute');
// app.use(corsRouter);
console.log('env vars', process.env);

app.use(bodyParser.json());
app.use(bodyParser.raw({type: () => true}));

const corsHeaders = require('./middlewares/corsHeaders');
app.use(corsHeaders);

//additional response headers
const addition_headers = require('./middlewares/additionalReponseHeaeders');
app.use(addition_headers);
debugger;


//Routing sample1
const appRouter1 = require('./controllers/appRoute1');
app.use(constants.COURSE_ROUTE,appRouter1);

//Routing sample 2
const appRouter2 = require('./controllers/appRoute2');
app.use(constants.HEADER_ROUTE, appRouter2);



//getting the commandline properties
console.log('command line arguments');
_.each(process.argv, (data)=>{

    console.log('each data', data);

});
console.log('env from argument',argumentExtractor.env);
console.log('port from argument',argumentExtractor.port);

//spread opertaor example
const oldArray = ['1', 2];
const newArray = [...oldArray];
console.log(newArray);

//Rest operator- basically to handle mutiple inputs
const sampleFunc = (...params)=>{
    return params;
}
console.log(sampleFunc(3,4));
console.log(sampleFunc(3,4,5,6 ));

const port = argumentExtractor.port || 3000;
app.listen(port, () => {
    console.log(`Server started on port..${port})`);
});

There are other parts that requires other files to be present for the execution but the router part and how to basically use the xml parsing for a single route is shown

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.