HTTP post request is not sending body or param data to the server
Forgive me if this turns out to be a duplicate question. I've looked at several similar questions on stack overflow, but none of them have solved my problem. Also tried using a GET request instead of a POST request, but body data is still not sending.
Client side code:
// ionic code
homeUrl: string = 'http://localhost:80';
let obj = {"name": "Guest"};
let response = this.httpClient.post(this.homeUrl + '/admin-signup', JSON.stringify(obj));
response.subscribe(data => {
console.log('response: ', data);
//TODO: handle HTTP errors
});
Server side code:
server.post('/admin-signup', (req, res) => {
console.log('sign')
console.log(req.body);
// TODO: Process request
res
.status(200)
.send(JSON.parse('{"message": "Hello, signup!"}'))
.end();
});
First of all, import http client
import { HttpClient, HttpHeaders } from '#angular/common/http';
Then do the following
const header = new HttpHeaders({
'Content-Type': 'application/json',
Accept: 'application/json'
//api token (if need)
});
const options = {
headers: header
}
let response = this.httpClient.post(this.homeUrl + '/admin-signup', obj, options);
response.toPromise().then(data => {
console.log('response: ', data);
//TODO: handle HTTP errors
}).catch((err) =>{
console.log('error', err);
});
Hope it solve your problem.
I'm not familiar with ionic
but I'm guessing its a cors issue
can you try use cors?
const cors = require('cors');
app.use(cors());
Related
NodeJs Code:
const express = require('express');
const port = 3000;
const router = express();
router.get('/', (req, res) => {
res.send('Hi');
})
var request = require('request');
var options = {
'method': 'GET',
'url': 'URL',
'headers': {
'Authorization': 'API_KEY'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
router.listen(port, function(err) {
if(err) return;
console.log('Server Up');
})
JavaScript Code:
const options = {
method: 'GET',
headers: {
'Authorization': 'API_KEY'
}
};
fetch('URL', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
Error:
has been blocked by CORS policy: Response to preflight request doesn't
pass access control check: No 'Access-Control-Allow-Origin' header is
present on the requested resource. If an opaque response serves your
needs, set the request's mode to 'no-cors' to fetch the resource with
CORS disabled.
Am I missing a Header in JS or is the syntax wrong?
Note: The API I call to Get request is not my own.
This may solve your problem:
Install cors and add the following line to the node server file:
router.use(cors())
If it doesn't work, remove any headers config and try again.
I am trying to access an api but when I access it in the browser, I get a CORS error. To get around this problem I set up an api proxy server. When this proxy gets a html request it connects to the browser blocked api and pulls the data needed. I think there is a problem on the proxy server where it is also blocking CORS and that needs to be changed, I’m not so sure. When I call the proxy api it gets the data from the browser blocked api and logs it to the console but does not push it to the browser because of the error below.
1.How do I correct this error “Reason: CORS header 'Access-Control-Allow-Origin' missing”
2.Should I be doing this a different way?
Error
Data being logged on the server
Server routing code - app.js
const apiCallFromRequest = require('./Request')
const apiCallFromNode = require('./NodeJsCall')
const apiCallFromTEST = require('./test.js')
const http = require('http')
http.createServer((req, res) => {
if(req.url === "/test"){
let start_time = new Date().getTime();
apiCallFromTEST.callApi(function(response){
//console.log(JSON.stringify(response));
res.write(JSON.stringify(response));
console.log(response);
console.log("Request API Requested");
console.log('API Test Time:', new Date().getTime() - start_time, 'ms');
res.end();
});
API proxy rought code -test.js
var rp = require('request-promise');
const callExternalApiUsingRequest = (callback) => {
var options = {
uri: 'https://app.invoiceninja.com/api/v1/products',
headers: {
'X-Ninja-Token': 'APIKEY'
},
json: true // Automatically parses the JSON string in the response
};
rp(options)
.then(function (data) {
console.log(data);
return callback(data);
})
.catch(function (err) {
// API call failed...
});
}
module.exports.callApi = callExternalApiUsingRequest;
website side - Just a basic fetch request
function gotProductData(){
fetch('http://localhost:3000/test')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
Try to install "cors" package (npm install cors) and import to app.js :
const cors = require('cors');
Run that above routes:
app.use(cors())
More details:
https://www.npmjs.com/package/cors#installation
I'm trying to make a request to my localhost server but am getting the error Failed to load resource: net::ERR_CONNECTION_REFUSED.
Here is my front end code:
(async () => {
const data = await fetch('http://localhost:8080/articles/', {
headers: { "Access-Control-Allow-Origin": "http://localhost:8080/articles/" }
});
const articles = await data.json()
console.log(articles)
})();
and backend code:
app.get("/articles/", function (req, res) {
let inputValue = req.body.page;
let pages = Math.ceil(totalResults / 10)
page = scripts.iteratePages(inputValue, page, pages);
request("https://newsapi.org/v2/top-headlines?q=" + initialQ +
"&category=sports&pageSize=10&page=" + page + "&sortBy=relevance&apiKey=" +
apiKey, function (error, response, body) {
if (!error && response.statusCode == 200) {
let data = JSON.parse(body);
let articles = scripts.articlesArr(data);
res.json({ articles: articles });
} else {
res.redirect("/");
console.log(response.body);
}
});
});
I've done some research myself, which points to using my private IP address instead of localhost and am getting an ... is not a function error in the console:
let ipAddress = "blah.blah.blah.blah"
(async () => {
const data = await fetch('http://' + ipAddress + ':8080/articles/', {
headers: { "Access-Control-Allow-Origin": "http://" + ipAddress + ":8080/articles/" }
});
const articles = await data.json()
console.log(articles)
})();
Any help would be great.
I think the error was caused by cross domain issues. You make a misunderstanding about CORS headers. The headers are not used by request but response.
If javascript program is making a cross domain request, the browser will first send an OPTION request with same parameters to the server. If backend on the server consider the request is legal, a response with only CORS headers will be send back to the browser, and then the browser check the CORS header against current environment. If CORS headers are suitable, the browser will finaly send the real request to server, or throw an error otherwise.
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
I am trying to upload an image from the front-end, post it with axios to back-end (node.js) and then from there post it again to the GroupMe image service.
The main thing is to avoid using the API token in the front-end and so I was trying to first send a request to the back-end and then send the actual API request to the GroupMe image service which expects to get FormData of an image and sends back converted image URL.
I have tried to send FormData directly to the GroupMe image service from the front-end and everything works fine. However, in order to do so, I had to store the token in the front-end, which is not a good idea I believe.
The working code below:
let config = {
headers : {
'X-Access-Token': myToken,
'Content-Type' : 'multipart/form-data'
}
}
let fd = new FormData()
fd.append('name', 'image')
fd.append('file', fileToUpload)
axios.post'(https://image.groupme.com/pictures', fd, config)
.then((response)=>{
console.log(response)
})
.catch(err =>{
console.log(err.response)
})
What I need to happen instead is to send the request to the back-end like so:
axios.post(process.env.baseUrl+'/messengerRequests/upload-file/', fd, config)
.then((response)=>{
console.log(response)
})
.catch(err =>{
console.log(err.response)
})
And now in the back-end somehow be able to get that FormData and then create another post request to the GroupMe image service as I initially did in the front-end.
sendMessage: async(req, res) => {
axios.post('https://image.groupme.com/pictures', ???, config)
.then((response)=>{
res.send(response)
})
.catch(err =>{
console.log(err.response)
})
}
I do not know where it appears in the axios request. There is nothing in the req.body or req.params so I am not able to simply pass it further for the next post.
Is there a way somehow pass this FormData again?
Or maybe there is a way to safely use the token in the frond-end?
So, it should be relatively straightforward to post the image to GroupMe using Node.js and Express / Multer / Request. I've gone for Request rather than Axios on the backend since I'm more familiar with the API, but it's the same difference really.
Node.js Code (index.js)
const request = require("request");
const express = require("express");
const multer = require("multer");
const upload = multer();
const app = express();
const port = 3000;
const myToken = "" // Your API token goes here.
app.use(express.static("./"));
/* Here we take the image from the client and pass it on to GroupMe */
app.post("/uploadFile", upload.any(), (req, res) => {
sendImageToGroupMe(req, res);
});
function sendImageToGroupMe(req, res) {
const options = {
uri: "https://image.groupme.com/pictures",
body: req.files[0].buffer,
method: "POST",
headers: {
"X-Access-Token" : myToken
}
}
request(options, (err, response, body) => {
console.log("Request complete: Response: ", body);
if (err) {
console.error("Request err: ", err);
res.status(500).send("Upload failed: ", err.message);
} else {
res.status(201).send("Upload successful: GroupMe response: " + body);
}
});
}
app.listen(port);
Client side
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function uploadFile() {
var fileToUpload = document.querySelector('input[type=file]').files[0];
let config = {
headers : {
'Content-Type' : 'multipart/form-data'
}
}
let fd = new FormData()
fd.append('name', 'image')
fd.append('file', fileToUpload)
axios.post('http://localhost:3000/uploadFile', fd, config)
.then((response)=>{
console.log("Image posted successfully: ", response);
showOutput("Image posted successfully: " + response.data);
})
.catch(err =>{
console.error("Image post failed: ", err)
showOutput("Image post failed!");
})
}
function showOutput(html) {
document.getElementById("output").innerHTML = html;
}
</script>
</head>
<body style="margin:50px">
<input type="file" onchange="uploadFile()"><br>
<p id="output"></p>
</body>
</html>
All files go in the same directory. You can go to http://localhost:3000/ to test the index.html code, this will be served by the Node.js server as a static file.
I get a response like below from the GroupMe API:
{
"payload": {
"url": "https://i.groupme.com/157x168.png.940f20356cd048c98478da2b181ee971",
"picture_url": "https://i.groupme.com/157x168.png.940f20356cd048c98478da2b181ee971"
}
}
We'll serve locally on port 3000, so to start the server:
node index.js
If you are using Express, you will need something to process the FormData. I have used multer for something similar before. I had to save the files into local storage, then resend the file with axios.
I have method
router.post('/user',passport.authenticate('jwt', { session: false }), function (request, res) {
res.send(request.user);
});
and authorization token
"JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyIkX18iOnsic3RyaWN0TW9kZSI6dHJ1ZSwic2VsZWN0ZWQi"
when i send request to this route from postman everything is working.
but when i send request from angular application with same token its throw with error unauthorized
getUser() {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', localStorage.getItem('token'));
return this.http.post('localhost:8000/api/user/', {
headers
})
.map((data: Response) => data.json())
.catch((error: Response) => Observable.throw(error.json()));
}
Instead of sending headers like an header object, use RequestOptions to wrap it and then send it via your post request.
your code will be like:
import { Http, Headers, RequestOptions } from '#angular/http';
getUser() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', localStorage.getItem('token'));
let options = new RequestOptions({ headers: headers });
return this.http.post('https://dropali.com/api/user/',options)
.map((data: Response) => data.json())
.catch((error: Response) => Observable.throw(error.json()));
}
Also a suggestion instead of getting your token while your post request retrieve it first in a variable and check if it's there or not, If not then do whatever is necessary if it is successfully retrieved then make post request.
1.) Check at the server side you are getting the token or not.
2.) if you are not getting the token then check Developer option > Network > your request's header tag and see whether the token is going or not
3.) if not going the problem is in a front and else it can because of cross origin..
FRONT END CODE EXAMPLE
var token = localStorage.Authorization
var options = {
url: '/user',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': token
}
}
$http(options)
.then((data) => console.log(data.data))
.catch((error) => console.log(error));
if front end is ok then you should check CROSS
app.use((req, res, next) => {
res.header('Access-Control-Expose-Headers', 'Authorization');
next();
})
OR
npm install cors --save
app.use(cors());