How to make http put request with zip file in nodejs - node.js

I want to make a http PUT request with zip file in binary to a web api and get response with http status code.
How to read the file and PUT it with binary ?
Thank you for your help!!

You can start with this:
var http = require('http');
var fs = require('fs');
var req = http.request({
hostname : HOSTNAME,
port : PORT,
path : UPLOAD_PATH,
method : 'PUT',
});
fs.createReadStream('somefile.zip').pipe(req);
You may need to perform some other actions, like proper error handling, setting Content-Type headers, etc.

Using request-promise (based on bluebird)
const fs = require('fs');
const request = require('request-promise');
const options = {
method: 'PUT',
url: 'dest url',
qs: {key: 'value'}, // optional
headers: {
'content-type': 'application/octet-stream'
}
};
fs.createReadStream(zipFilePath).pipe(request(options)).then(body =>{
console.log(body);
})
.catch(err => {
console.log(err);
});

Check that answer.
The only difference would be, you are using .put() instead on .post().

Related

Multer fails when using https on express. Works when using only http

I can't receive files when using https on express but works well when using only http. I just updated my express app to use a self-signed certificate for testing.
Here's what I am trying:
upload function
exports.upload = async (req, res) => {
console.log(req.file); //returns undefined
console.log(req.body.file); //returns [Object: null prototype] {}
...REST OF CODE...
}
client function
const formData = new FormData();
formData.append('file', pdfFile);
formData.append('user', 'test');
const params = {
body: formData,
method: 'POST',
credentials: 'include'
}
const result = await fetch('https://localhost:3000/service/upload', params);
I also noticed that the content-length is set to "0" when inspecting the network tab. Payload tab is also missing.
Request headers

Handle API Response in .gzip with XML file inside

I'm trying to handle this API interaction with node.js (using express and request) but i'm having a lot of trouble dealing with the data.
Here's my current code:
// Requirements
const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
const fs = require("fs");
const zlib = require("zlib");
const gunzip = require("gunzip-file");
const decompressResponse = require("decompress-response");
// Setting Up App
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
// Routes
app.get("/", (req, res) => {
res.send("App Running");
});
// API Integration
let responseXML = "";
let bodyXML =
'<?xml version="1.0" encoding="UTF-8"?><RequestMensagemCB><login>14087809000107</login><senha>xxxx</senha><mId>1</mId></RequestMensagemCB>';
const options = {
url: "http://webservice.newrastreamentoonline.com.br/",
method: "POST",
body: bodyXML
};
app.get("/onix", function(req, res) {
request(options, function(error, response, body) {
// body is the decompressed response body
console.log(
"server encoded the data as: " +
(response.headers["content-encoding"] || "identity")
);
console.log("the decoded data is: " + body);
})
.on("data", function(data) {
// decompressed data as it is received
console.log("decoded chunk: " + data);
})
.on("response", function(response) {
// unmodified http.IncomingMessage object
response.on("data", function(data) {
// compressed data as it is received
console.log("received " + data.length + " bytes of compressed data");
});
});
});
// Server Listening
app.listen(process.env.PORT || 3000, () => {
console.log("Server Online Listening to port 3000");
});
This is the console.log response i get:
Using postman i can reach the XML through the following route:
I first make the post request with the XML needed to validate the API Access, then i send and download the response giving it the extension of .gz and inside the .gz there's a compressed version of the file that when opened shows the XML response:
This is my first time working with an API that returns the data in .gz that way. I've tried piping the data using zLib and now was thinking on the following route: download the response in .gz, decompress the resulting file, then opening it to reach the XML. I imagine there's a better way of doing this!
I Could fix the code through another approach.
I've added 2 more params for the const options:
const options = {
url: "http://webservice.newrastreamentoonline.com.br/",
method: "POST",
body: bodyXML,
headers: {
"Accept-Encoding": "gzip"
},
encoding: null,
gzip: true
};
The key value is the following: encoding: null, , that way the stream comes without corruption.
Then i've been able to print out the XML response. Using xml2json NPM i've been able to convert it on a JSON object, and now i'll work normally with the data.

Error 400 when making POST request to Spotify API with Axios on Express.js

I'm trying to retrieve an access token from the Spotify API when making a post request with axios on an Express back end server. So far I have been unsuccessful. I'm getting the following error:
data:
{ error: 'unsupported_grant_type',
error_description:
'grant_type must be client_credentials, authorization_code or refresh_token' } } }
I've already tried to change 'data' property for 'grant_type' to 'params' but it's still not working. Any advice would help.
const express = require('express');
const axios = require('axios');
const dotenv = require('dotenv');
dotenv.config();
const app = express();
const port = 3000;
const client_id = process.env.CLIENT_ID;
const client_secret = process.env.CLIENT_SECRET;
app.get('/spotify-authorization', (req, res) => {
axios({
method: 'post',
url: 'https://accounts.spotify.com/api/token',
data: {
grant_type: 'client_credentials'
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization:
'Basic ' +
Buffer.from(client_id + ':' + client_secret).toString('base64')
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
res.send('successful response received!');
});
app.listen(port, () => console.log(`Express app listening on port ${port}!`));
I want to be able to retrieve the access token in the response from the Spotify API. Please help!
From axios docs : By default, axios serializes JavaScript objects to JSON. To send data in the application/x-www-form-urlencoded format instead, you can use one of the following options.
For Nodejs you can use the querystring module as follows:
var querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
So, in your case you could try data: querystring.stringify({ grant_type: 'client_credentials' })
I can't leave a comment due to low reputation, but 1556089774's answer should be the accepted answer. I've spent over 4 hours researching as to why it wasn't working since Spotify's iOS sdk points to https://glitch.com/~spotify-token-swap as an example which does NOT WORK. Adding the stringify to the data part of the request makes it work:
data: querystring.stringify ({
grant_type: "authorization_code",
redirect_uri: SPOTIFY_CLIENT_CALLBACK_URL,
code: authorization_code
})

How to use API path param in npm request & request-promise libraries

In my NodeJS/Express app, I have API implementation which calls another external API.
For this, I am using npm request & request-promise libraries
How can I call API's that has path parameter?
const express = require('express');
const router = express.Router();
const rp = require('request-promise');
router.post('employee/:id', (req, res) => {
const id = req.params.id; // I dont know how to use this in request library
handleRequest(req, res);
})
function handleRequest(req, res) {
const id = req.params.id; // I dont know how to use this in request library options?
var options = {
method: req.method,
uri: 'http://api.anotherhost.com/external/'+ req.path,
body: req.body,
qs: req.query,
json: true
};
rp(options)
.then((success) => res.send(success))
.catch((err) => res.status(err.statusCode).send(err.message));
}
https://github.com/request/request
https://www.npmjs.com/package/request-promise
Update:-
This code so far works fine for other calls without path parameter.
Since request doesn't provide an option to add path parameters you have to format your request uri to include them, you can simply use string literals to do this:
const id = req.params.id;
var options = {
method: req.method,
uri: `http://api.anotherhost.com/external/${id}`,
body: req.body,
qs: req.query,
json: true
};
Keep in mind you must verify that the id format is valid.

Sending/handling GET requests in typescript using Express, Request and Node.js

I'm using a combination of Express and Request (installed using npm) to try to send a get request to get some json from the server. However no matter what I do the body that is returned is "undefined".
This is the code in my server.js file. The json isn't actually what I'm sending, it's just an example as I can't post what I'm actually sending.
import express = require("express");
import bodyParser = require("body-parser");
let app = express();
app.use(bodyParser.json());
app.get('/config', function(req, res){
res.json('{name: test}');
})
app.listen(3000);
I've tried both of the following but both of them say that body is undefined.
import request = require("request");
let req = {
url: `http://localhost:3000/config`,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
request(req, function(error, response, body){
this.config = JSON.parse(body);
})
request(`/config`, function(err, res, body) {
this.config = JSON.parse(body);
});
Does anyone know what I'm doing wrong? I've never used express or request before so any tips would be greatly appreciated.
UPDATE
If I change the request code to the following, the inside of the function is never run. Does anyone know why this would be?
let req = {
url: `http://localhost:3000/config`,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
request(req, function(error, response, body){
console.log("response => "+JSON.parse(body));
return JSON.parse(body);
})
Since OP hasn't got it working and I believe the code he got up there is correct. I may as well post my working solution here to help him get started.
Hopefully this will save you hours of debugging...
Client:
"use strict";
let request = require("request");
let req = {
url: `localhost:4444/config`,
proxy: 'http://localhost:4444',
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
request(req, function (err, res, body) {
this.config = JSON.parse(body);
console.log("response => " + this.config);
});
Server:
"use strict";
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
var config = require('config');
app.use(bodyParser.json());
app.get('/config', function(req, res){
res.json('{name: test}');
});
// Start the server
app.set('port', 4444);
app.listen(app.get('port'), "0.0.0.0", function() {
console.log('started');
});
Output:
response => {name: test}
I dont't know if you have posted whole of your server's code, it seems like you missed app.listen(port) so that your server cannot be started up correctly.
Also, if you added if (error) { console.log(error); } at the first line of the callback function of request, you'll find it print an error: [Error: Invalid URI "/config"]
And that's why the body is always undefined: You have to give the full url such like http://localhost:xxxx to request.
In short:
Your server didn't listen to a specific port. app.listen(5678)
Your client didn't know the complete url. request('http://localhost:5678/config', (...)=>{...})

Resources