1

I am trying to send a post request from python to my nodeJS server. I can successfully do it from client-side js to nodeJS server using the fetch API but how can I achieve this with python? What I tried below is sending the post request successfully but the data/body attached to it is not reaching the server. What am I doing wrong and how can I fix it? Thanks in advance.

NOTE: All my nodeJS routes are set up correctly and work fines!

//index.js

'use strict';
const express = require('express')
const app = express()
const PORT = 5000

app.use('/js', express.static(__dirname + '/public/js'))
app.use('/css', express.static(__dirname + '/public/css'))
app.set('view engine', 'ejs')
app.set('views', './views')
app.use(cookie())
app.use(express.json({
  limit: '50mb'
}));

app.use('/', require('./routes/pages'))
app.use('/api', require('./controllers/auth'))

app.listen(PORT, '127.0.0.1', function(err) {
  if (err) console.log("Error in server setup")
  console.log("Server listening on Port", '127.0.0.1', PORT);
})

//server file
//served on http://127.0.0.1:5000/api/server

const distribution = async(req, res) => {
  //prints an empty object
  console.log(req.body)
}

module.exports = distribution;

//auth
const express = require('express')
const server = require('./server')

const router = express.Router()

router.post('/server', server)

module.exports = router;

//routes
const express = require('express')
const router = express.Router()

router.get('/', loggedIn, (req, res) => {
  res.render('test', {
    status: 'no',
    user: 'nothing'
  })
})
#python3
import requests

API_ENDPOINT = "http://127.0.0.1:5000/api/server"
  
data = '{"test": "testing"}'

response = requests.post(url = API_ENDPOINT, data = data)

print(response)
seriously
  • 1,202
  • 5
  • 23
  • "All my nodeJS routes are set up correctly and work fines" I don't believe you, so show the [mcve] code on the node side so we can confirm your route really does look like it was set up correctly and should work fine. Because the code you're showing for the Node part has basically nothing to do with setting up a route correctly, nor does it show which server framework you're using, and what additionals you've loaded for that =) One thing to note on the python side: `data` is a string. It should just be a dict. – Mike 'Pomax' Kamermans Mar 04 '23 at 05:34
  • @Mike'Pomax'Kamermans I am using the same node js backed to receive a post request from client side js and it works without any problems. But if you insist I can add the code. – seriously Mar 04 '23 at 05:36
  • As per the [posting guidelines](/help/how-to-ask), I must indeed insist. We can only take your word for claims like "part X works fine", and no words are as good as actual ([mcve]) code. – Mike 'Pomax' Kamermans Mar 04 '23 at 05:37
  • @Mike'Pomax'Kamermans I am using express. I focued on the python part cause I am sure that's where the issue is but I will add more code on nodeJS in a sec – seriously Mar 04 '23 at 05:37
  • Be sure to also fix that Python mistake though, and verify that that wasn't your problem. – Mike 'Pomax' Kamermans Mar 04 '23 at 05:37
  • @Mike'Pomax'Kamermans I have edited my question. Hope this helps better understand the issue. – seriously Mar 04 '23 at 05:49
  • No, really, _fix hat python mistake_. You've made `data` a string, and it _really_ needs to be a normal dict so that `requests` can properly pack it up. Don't put it in quotes. Also, I don't see your Node code using [body-parser](http://expressjs.com/en/resources/middleware/body-parser.html), which you're almost certainly going to need if you want to handle POST bodies. – Mike 'Pomax' Kamermans Mar 04 '23 at 06:11
  • @Mike'Pomax'Kamermans `express` includes the `body-parser` library now, the middleware that parses JSON is `express.json()` and configured correctly. The python side though is not passing the expected header so the middleware does nothing. Passing a dictionary in `data` will pass the data as form-data instead of json so won't work in this case – pqnet Mar 04 '23 at 06:40
  • @Mike'Pomax'Kamermans pqnet explains it better also I included ```app.use(express.json({ limit: '50mb' }));``` because after express 4.16.0 bodyparser has been added back to express – seriously Mar 04 '23 at 06:43

2 Answers2

1

Since you are manually passing the request as a string you may need to specify also the content-type so that Express middleware can recognise and parse it as JSON.

See express.json documentation

Returns middleware that only parses JSON and only looks at requests where the Content-Type header matches the type option. This parser accepts any Unicode encoding of the body and supports automatic inflation of gzip and deflate encodings.

you could do it like this:

headers = {'Content-type': 'application/json'}
data = '{"test": "testing"}'

response = requests.post(url = API_ENDPOINT, data = data, headers = headers)

A better idea is to use instead (if your requests version supports it) the json parameter instead of data as shown in How to POST JSON data with Python Requests? and let the requests framework set the correct header for you:

data = {'test': 'testing'}

response = requests.post(url = API_ENDPOINT, json = data)
pqnet
  • 6,070
  • 1
  • 30
  • 51
1

Have you tried passing the request payload directly as a json instead of converting it to string? Like @pqnet Has mentioned, Python's request library will automatically add content-type header to your post request.

import requests

API_ENDPOINT = "http://127.0.0.1:5000/api/server"
  
data = {"test": "testing"}

response = requests.post(url = API_ENDPOINT, json = data)

print(response)
Darkness
  • 21
  • 4