【问题标题】:Express API JSON and XML POST requestExpress API JSON 和 XML POST 请求
【发布时间】: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 响应?

任何帮助将不胜感激!

【问题讨论】:

    标签: json node.js xml api express


    【解决方案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() 的操作来获取原始请求正文。

          【讨论】:

            猜你喜欢
            • 2014-11-19
            • 1970-01-01
            • 1970-01-01
            • 2019-11-04
            • 2019-06-16
            • 2017-01-10
            • 1970-01-01
            • 1970-01-01
            • 2020-11-24
            相关资源
            最近更新 更多