Help with http request

Hello. I’m trying to send an object to my server, but I can’t see how.
I’ve already tried:

Client:

module.exports = async function(params, keys) {
	return new Promise((resolve, reject) => {
    // select http or https module, depending on reqested url
	let url
	if (params.ops.target) {url = `${keys.domain}push?params=${params.id}&value=${JSON.stringify(params.data)}&target=${params.ops.target}&password=${keys.password}`} else url = `${keys.domain}push?params=${params.id}&value=${JSON.stringify(params.data)}&password=${keys.password}`
	const lib = url.startsWith('https') ? require('https') : require('http');
    const request = lib.get(url, (response) => {
      // handle http errors
      if (response.statusCode < 200 || response.statusCode > 299) {
         reject(new Error('Failed to make request, status code: ' + response.statusCode));
       }
      // temporary data holder
      const body = [];
      // on every content chunk, push it to the data array
      response.on('data', (chunk) => body.push(chunk));
      // we are done, resolve promise with those joined chunks
      response.on('end', () => resolve(body.join('')));
    });
    // handle connection errors of the request
    request.on('error', (err) => reject(err))
    })

Usage: https://example.com/push?params=test&value={my:%27obj%27}&password=1234

Server:

app.get("/push", checkpass, async (req, res) => {
  let params = req.query.params,
      value = req.query.value,
      target = req.query.target
  if (params) {
    if (value) {
      if (target) {
        try {
			
            await db.push(params, JSON.parse(value), {target: `.${target}`})
            res.status(200).json({message: `${JSON.parse(value)} pushed to ${params}.${target}`})
            } catch(e) {
            res.status(200).send(e)
          }
        } else {
          try {
          await db.push(params, JSON.parse(value))
            res.status(200).json({message: `${JSON.parse(value)} pushed to ${params}`})
          } catch(e) {
          return res.status(200).send(e)
        }
      }
    } else return res.status(200).json({message: "No value to insert.", code: 401})
  } else return res.status(200).json({message: "No database entry specified.", code: 401})
});

Anyone knows any way to send objects in that url path with node.js native packages?

EDIT: I tried this code:

module.exports = async function(params, keys) {
	return new Promise((resolve, reject) => {
		let url
		let domain = ''
		const myObj = params.data
		if (params.ops.target) {url = `/push?params=${params.id}&target=${params.ops.target}&password=${keys.password}`} else url = `/push?params=${params.id}&password=${keys.password}`
		/*if (keys.domain.includes('https://')) {
			domain = keys.domain.replace('https://', '')
		} else {
			if (keys.domain.includes('http://')) {
				domain = keys.domain.replace('http://', '')
			}
		}*/
		var options = {
			hostname: domain,
			path: url,
			method: 'POST',
			//body: myobj,
			headers: {
				'Content-Type': 'application/json',
				'Content-Length': myObj.length
				}
		};
		const lib = keys.domain.startsWith('https') ? require('https') : require('http');
		const request = lib.request(options, (response) => {
      // handle http errors
      if (response.statusCode < 200 || response.statusCode > 299) {
         reject(new Error('Failed to make request, status code: ' + response.statusCode));
       }
      // temporary data holder
      const body = [];
      // on every content chunk, push it to the data array
      response.on('data', (chunk) => body.push(chunk));
      // we are done, resolve promise with those joined chunks
      response.on('end', () => resolve(body.join('')));
    });
    // handle connection errors of the request
    request.on('error', (err) => reject(err))
	})
 }

But it gave me this:

If I’m not mistaken, the domain you’re using is an empty string. I would really highly suggest using the node-fetch library for http requests in node.js, since the built-in packages are quite a pain

1 Like

Ok. I tried node-fetch, but it gave me this error:


This is the code:

module.exports = async function(params, keys) {
		let url
		if (params.ops.target) {url = `${keys.domain}set?params=${params.id}&target=${params.ops.target}&password=${keys.password}`} else url = `${keys.domain}set?params=${params.id}&password=${keys.password}`
   return fetch(url, {
        method: 'post',
        body:    JSON.stringify(params.data),
        headers: { 'Content-Type': 'application/json' },
    })
}

Hmm looks like for some reason body-parser cannot parse the incoming JSON body because it starts with ". That’s strange though, because (assuming the error is coming from the fetch request you pasted), tthe body is coming from JSON.stringify, which should produce valid JSON.

Is that error coming from a different request, maybe?

I don’t think so, because I only call that request, but maybe it’s something with the server code?
Is anything wrong with this?

const express = require("express");
const bodyParser = require('body-parser');
const app = express();
const db = require('quick.db')
global.QDRapp = app

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

module.exports = function(params) {
// Check if password is correct
function checkpass(req, res, next) {
	//console.log(params.password)
if (req.query.password === params.password) return next();
	throw new TypeError('Password incorrect.')
}
	
if (!params.path) {
app.post("/set", checkpass, async (req, res) => {
  let params = req.query.params,
      value = req.body,
      target = req.query.target
  if (params) {
    if (value) {
      if (target) {
        try {
          await db.set(params, value, {target: `.${target}`})
          res.status(200).json({message: `${params}.${target} has been set to ${value}`})
        } catch(e) {
          return res.status(200).send(e)
        }
      } else {
        try {
          await db.set(params, JSON.parse(value))
          res.status(200).json({message: `${params} has been set to ${value}`})
        } catch(e) {
          return res.status(200).send(e)
        }
      }
    } else return res.status(200).json({message: "No value to insert.", code: 401})
  } else return res.status(200).json({message: "No database entry specified.", code: 401})
});
}

Hmm I don’t think you should be wrapping the whole thing in a module.exports - that’s for defining what other files should import from this file. Is there a good reason why you’re using it?

Also, you shouldn’t be defining a route based on some sort of parameters (whether params.path exists, i think in this case?). The route should just be defined, so that it exists no matter what (a route shouldn’t disappear depending on parameters).

I’m using module.exports because this is for a npm package. And params.path is to whenever use like:
With path: https://example.com/page/[method here]
Without path: https://example.com/[method here]

So if someone wants to setup my packages’s server, but already has another website running in that url, they can change it to an page, like an API page.

@benborgers so, the problem is in the server part? If so, what should I do?

Does making the request body a JSON object work?

It worked. Thank you.

I’ve been getting those errors for the past few days whenever I use the Fetch API, and that was the only thing that worked!

Thanks. Btw, do you know how to console.log the value after the promise if fulfilled? Because when I do console.log with this code:

var fetch = require("node-fetch")
module.exports = async function(params, keys) {
		let url
    if (keys.domain.slice(-1) !== '/') keys.domain += '/'
		if (params.ops.target) {url = `${keys.domain}set?params=${params.id}&target=${params.ops.target}&password=${keys.password}`} else url = `${keys.domain}set?params=${params.id}&password=${keys.password}`
    
    let reqS = await fetch(url, {
      method: 'post',
      body:    params.data,
      headers: { 'Content-Type': 'application/json' },
  })
    return console.log(reqS.json())
 }

It returns Promise { <pending> }

Try using .then() to resolve the promise.

Tryed this:

var fetch = require("node-fetch")
module.exports = async function (params, keys) {
  let url
  if (keys.domain.slice(-1) !== '/') keys.domain += '/'
  if (params.ops.target) {url = `${keys.domain}set?params=${params.id}&target=${params.ops.target}&password=${keys.password}`} else url = `${keys.domain}set?params=${params.id}&password=${keys.password}`

  let reqS = await fetch(url, {
    method: 'post',
    body: params.data,
    headers: {
      'Content-Type': 'application/json'
    },
  }).then(data => {
    if (data.message) {return console.log(data.json().message)} else return console.log(data.json())
  })
}

But still gives me promise pending.

Does this help: https://stackoverflow.com/questions/38884522/why-is-my-asynchronous-function-returning-promise-pending-instead-of-a-val?

It didn’t work, however, I went to the npm page of node-fetch, and the solution was there:

Thanks anyway.

1 Like