Express API JSON 和 XML POST 请求

Posted

技术标签:

【中文标题】Express API JSON 和 XML POST 请求【英文标题】:Express API JSON and XML POST request 【发布时间】:2017-05-23 23:23:31 【问题描述】:

我有一个快速 API,它允许 json 发布请求。但是,在我的场景中,我的 API 之一需要接受 XML 帖子正文,而不是 JSON。

所以我的快递应用程序设置得很好:

// Init App
var app = express();

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

这是我的 POST api JSON 路由的示例:

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

当我传入我的 json 值时,效果很好,例如这是我的帖子请求:


    "milliseconds":"600"

但现在我有一个 API,我想在其中执行 POST 请求,但我的 POST 请求需要作为 XML 发送。所以这就是我的 API 的样子:

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

没有什么复杂的,因为我没有得到任何回报。这就是我执行 POST 请求的方式:

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

然而,我的身体却空空如也。知道如何解决这个问题吗?理想情况下,我想接受这个 XML 请求,然后也用我选择的 XML 进行响应。最好的方法是什么?

接受请求,转换为 JSON,写入 JSON 响应并转换回 XML 响应?

任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

bodyParser 仅支持以下格式(如果您使用的是 body-parser):

JSON 正文解析器 原始正文解析器 正文解析器 URL 编码的表单正文解析器

所以如果你想解析 XML 我建议你使用 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 
);

我希望这可以帮助你朝着正确的方向前进

【讨论】:

是否可以只为一个 API 路由做到这一点?请记住,我有很多 JSON 路由,只需要一个 XML 路由 从文档中,看起来你可以同时拥有,并且 express 会看到请求的内容类型并使用正确的。 npmjs.com/package/express-xml-bodyparser 这是一个猜测 我在我的 API 中使用了这两个解析器,并且两者都有效。 express-xml-bodyparser 按 mime 类型检测内容。 @R.Gulbrandsen npm 页面显示“解析原始 xml 正文”,所以,如果我们只使用 body.parser.raw( type: "application/xml" ) 并将我们在正文中获得的缓冲区转换为字符串,我们不应该得到xml 字符串? 对不起,我不知道这个问题的答案。【参考方案2】:

我相信你可以使用不同的路线

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)`);
);

还有其他部分需要其他文件才能执行,但显示了路由器部分以及如何基本使用 xml 解析来进行单个路由

【讨论】:

【参考方案3】:

我知道已经很晚了,但是,如果你想同时使用 xml 和 json,你可以像这样使用特定的 xml 请求,

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

【讨论】:

【参考方案4】:

body 是可读流,可以由块组成。

您可以在处理程序中执行类似的操作。

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);
        );
    

【讨论】:

【参考方案5】:

router.use(bodyparser.raw( type: 'application/xml' )); XML 正文将被解析,并将采用 Buffer 格式。在路由中,您可以执行类似new Buffer(req.body.data).toString() 的操作来获取原始请求正文。

【讨论】:

以上是关于Express API JSON 和 XML POST 请求的主要内容,如果未能解决你的问题,请参考以下文章

使用Express实现本机JSON API网络

json 使用Express JS的基本RESTful API

尝试发送 json 对象时,fetch api 如何与 express 一起使用

我正在尝试使用 json-server、Node 和 Express 在 localhost 上为我的 Angular 应用程序模拟 RESTFUL API。随之而来的 CORS 问题

Express 和 Nodejs:调用外部 API 的最佳方式

Expressjs 响应为 JSON 和 Xml