How to use an object passed as a function parameter? - javascript

I'm setting a CRUD vue app that communicates with an api via axios. I'm having problems trying to set the PATCH function
I use a mixin providing this method
axiosPatch (url, body, msg = 'Failed to update data to server') {
return this.$axios.patch(url, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.token
},
body
})
.catch(() => console.log(msg))
}
and I call it somewhere else:
this.axiosPatch('/people/' + this.person.id, { body: { person: { first_name: 'test' } } })
At the api side I this output:
Started PATCH "/people/712" for 127.0.0.1 at 2019-07-19 00:26:54 +0300
Processing by PeopleController#update as HTML
Parameters: {"headers"=>{"Content-Type"=>"application/json", "Authorization"=>"Bearer ey...w"}, "body"=>{"body"=>{"person"=>{"first_name"=>"test"}}}, "id"=>"712", "person"=>{}}
I expected the output to be
...
Parameters: {"headers"=>{"Content-Type"=>"application/json", "Authorization"=>"Bearer ey...w"}, "person"=>{"first_name"=>"test"}, "id"=>"712"}
any help please?
EDIT
approach #1:
this.axiosPatch('/people/' + this.person.id, { person: { first_name: 'test' } })
axiosPatch (url, { body }, msg = 'Failed to update data to server') {
// console.log(body) <-- this outputs 'undefined'
return this.$axios.patch(url, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.token
},
body
}).catch(() => console.log(msg))
}
API output:
Started PATCH "/people/712" for 127.0.0.1 at 2019-07-19 00:26:54 +0300
Processing by PeopleController#update as HTML
Parameters: {"headers"=>{"Content-Type"=>"application/json", "Authorization"=>"Bearer ey...w"}, "id"=>"712", "person"=>{}}
approach #2:
this.axiosPatch('/people/' + this.person.id, { body: { person: { first_name: 'test' } } })
axiosPatch (url, body, msg = 'Failed to update data to server') {
// console.log(body) <-- this outputs the Object correctly
return this.$axios.patch(url, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.token
},
body: body.body
}).catch(() => console.log(msg))
}
API output:
Started PATCH "/people/712" for 127.0.0.1 at 2019-07-19 00:26:54 +0300
Processing by PeopleController#update as HTML
Parameters: {"headers"=>{"Content-Type"=>"application/json", "Authorization"=>"Bearer ey...w"}, "body"=>{"person"=>{"first_name"=>"test"}}, "id"=>"712", "person"=>{}}

The problem is that you are adding an Object with the key body, you can fix it by adding {body} to your param list. This will give you body var with { person: ... }
axiosPatch (url, {body}, msg = 'Failed to update data to server') {
return this.$axios.patch(url, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.token
},
body
})
.catch(() => console.log(msg))
}
Also, you can remove the body key in the argument you pass to axiosPatch.
Or you can do you can:
axiosPatch (url, body, msg = 'Failed to update data to server') {
return this.$axios.patch(url, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.token
},
body: body.body
})
.catch(() => console.log(msg))
}

I found a solution:
this.axiosPatch('/people/' + this.person.id, { person: { first_name: 'test' } })
axiosPatch (url, body, msg = 'Failed to update data to server') {
var o = Object.assign({
{ headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.token
}
},
body
)
return this.$axios.patch(url, o).catch(() => console.log(msg))
}
and I get what I expected.
Is there a better solution?

Related

HTTP function times out when subscribing an FCM token to a topic in Cloud Function

Minimum reproducible code:
index.ts:
import * as admin from "firebase-admin"
import fetch, { Headers } from "node-fetch";
interface BarPayload {
topic: string,
token: string,
}
exports.bar = functions.https.onCall(async (data, context) => {
if (data != null) {
const payload: BarPayload = {
topic: data.topic,
token: data.token,
}
const url = `https://${location}-${project}.cloudfunctions.net/subscribeToTopic`
await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
topic: payload.topic,
token: payload.token,
}),
})
}
return null;
});
export const subscribeToTopic = functions.https.onRequest(async (req, res) => {
const payload = req.body as BarPayload;
fetch('https://iid.googleapis.com/iid/v1/' + payload.token + '/rel/topics/' + payload.topic, {
method: 'POST',
headers: new Headers({
'Authorization': 'key=AA...Wp9',
'Content-Type': 'application/json'
})
}).then(response => {
if (response.status < 200 || response.status >= 400) {
res.sendStatus(299)
}
}).catch(error => {
console.error(error);
res.sendStatus(299)
})
return Promise.resolve();
})
I'm running bar in Flutter and I see the timeout error in Logs Explorer:
textPayload: "Function execution took 60051 ms. Finished with status: timeout"
But if I change my subscribeToTopic from HTTP function to a callable function, then it works fine. For example:
exports.subscribeToTopic = functions.https.onCall(async (data, context) => {
fetch('https://iid.googleapis.com/iid/v1/' + data.token + '/rel/topics/' + data.topic, {
method: 'POST',
headers: new Headers({
'Authorization': 'key=AA...Wp9',
'Content-Type': 'application/json'
})
}).then(response => {
if (response.status < 200 || response.status >= 400) {
console.log('Error = ' + response.error);
}
}).catch(error => {
console.error(error);
})
return null;
});
(I know I'm making some trivial mistake, and I'm new to Typescript. Any help would be appreciated :)
You should not do return Promise.resolve(); in the HTTPS Cloud Function:
HTTPS Cloud Functions shall be terminated with with send(), redirect() or end();
return Promise.resolve(); is executed before the asynchronous call to fetch is complete.
The following should do the trick (untested):
export const subscribeToTopic = functions.https.onRequest(async (req, res) => {
try {
const payload = req.body as BarPayload;
const response = await fetch('https://iid.googleapis.com/iid/v1/' + payload.token + '/rel/topics/' + payload.topic, {
method: 'POST',
headers: new Headers({
'Authorization': 'key=AA...Wp9',
'Content-Type': 'application/json'
})
});
if(response.status < 200 || response.status >= 400) {
res.status(299).send();
}
} catch (error) {
res.status(400).send();
}
})
However I don't understand why you separate your business logic in two Cloud Functions. Why don't you directly fetch https://iid.googleapis.com within the bar Callable Cloud Function?

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'subscribe' of null (Ionic Angular)

In my angular ionic project, when I log in the first page gives me the error "ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'subscribe' of null" but when I reload the page I don't have the error and I have the data. thank you
(await this.pageService.getAllTables()).subscribe((res: any) => {
this.tables = res.body
});
}```
```getAllTables() {
this.storage.get('USER').then(user =>{this.user = user;});
return this.storage.get('ACCESS_TOKEN').then(token =>{
if (this.user) {
return this.http.get(this.url + 'table/' + this.user.id, {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}),
observe: 'response'
});
}
return null;
});
}```
try this
getAllTables() {
return this.storage.get('USER')
.then(user =>{this.user = user;})
.then(() => this.storage.get('ACCESS_TOKEN'))
.then(token =>{
if (this.user) {
return this.http.get(this.url + 'table/' + this.user.id, {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}),
observe: 'response'
});
}
return null;
});
this code is still strange, as you return observable, wrapped in promise but at least is should work.
you could try to convert everything to promises. it would look like this:
getAllTables() {
return this.storage.get('USER')
.then(user =>{this.user = user;})
.then(() => this.storage.get('ACCESS_TOKEN'))
.then(token =>{
if (this.user) {
return this.http.get(this.url + 'table/' + this.user.id, {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}),
observe: 'response'
}).toPromise();
}
return null;
});
usage:
this.tables = (await this.pageService.getAllTables())?.body;
i think your this.pageService.getAllTables is not loaded yet when you subscribe.
please first inject the "pageService" in constructor and then convert everything to promises
like This
constructor(){
private pageService: PageService
}
after that convert everything to promises
getAllTables() {
return this.storage.get('USER')
.then(user =>{this.user = user;})
.then(() => this.storage.get('ACCESS_TOKEN'))
.then(token =>{
if (this.user) {
return this.http.get(this.url + 'table/' + this.user.id, {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}),
observe: 'response'
}).toPromise();
}
return null;
});

Generating Access token with axios in react-native

POSTMAN sample
the same process i want to do it in react-native and i have tried like that
var baseHeaders = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ' + btoa(client_id + ':' + client_secret)
};
var params = {
client_id: client_id,
client_secret: client_secret,
grant_type: "client_credentials",
}
axios({
method: 'POST',
url: "http://transrv02-ap01.transsyssolutions.com:8080/apex/apxprd/oauth/token",
headers: baseHeaders,
body:params
})
.then((responseJson) => { console.log("clientid---"+responseJson)})
.catch((error) => {
console.error(error);
});
but it have showing 401 error.
Anyone can help me!
thanks in advance....
You can try this...
axios.post('http://transrv02-ap01.transsyssolutions.com:8080/apex/apxprd/oauth/token',
params,
{
headers: baseHeaders
})
.then((responseJson) => { console.log("clientid---"+responseJson)})
.catch((error) => {
console.error(error);
});
Finally I Found My own way not in axios
var baseHeaders = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': "Basic " + btoa(client_id + ":" + client_secret)
};
console.log(JSON.stringify(baseHeaders) + "baseHeaders")
var params = "grant_type=client_credentials";
console.log(JSON.stringify(params) + "params")
return fetch('http://apex/apxprd/oauth/token',{
method: "POST",
body: params,
headers: baseHeaders
}).then((response) => response.json()).then((responsetokenJson) => {
console.log(JSON.stringify(responsetokenJson) + "responseJsonclientid")
var token = responsetokenJson.access_token
console.log("this.props.tokens--" + token)
this.setState({
accessToken: token
})
})

React Native "fetch" returning server response without the information

I am using react native to create an application to act as a website that currently exists (with a user interface that works on a phone). i am using the "fetch" method to send a Http POST request to get information from a web server. The web server sends a response but it doesn't include the response message:
I apologies that is an image but the debugger is not working for me.
The code used to send the request:
HttpRequest = (RequestURL, callback) => {
var AdminLoginBindingModel = {
usr: this.state.username,
pwd: this.state.password,
}
fetch(RequestURL,
{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(AdminLoginBindingModel)
})
.then((res) => {
callback(res);
})
.catch((error) => {
this.setState({Response: "Error: " + error});
})
}
The callback function in the parameters is just a function to change the state variable to display the information on the screen
ValidateResponse(response){
this.setState({Response: "Result: " + JSON.stringify(response),
displayMessage: "Success"});
console.log(JSON.stringify(response));
}
The Request being sent is "https://mibase-test.mibase.com.au/members/api/startSession.php?usr=&pwd="
The server responds with a json object regardless of a correct login or not
Edit:
Changing the response to
.then((res) => {
callback(res.json());
})
Result:
To get object from fetch response, you have to call res.json like following:
fetch(RequestURL, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(AdminLoginBindingModel)
})
.then(res => res.json()) // HERE
.then(obj => callback(obj))
But it occurs an error because response body itself is invalid json format. It contains some HTML tags:
{"member": {"username":"","password":"","key":"***","status":"No"}}<br><br>Username: <br>Key: ***
Please check the inplementation of server.
EDIT: full code here
const fetch = require("node-fetch")
HttpRequest = (RequestURL, callback) => {
const AdminLoginBindingModel = { usr: "foo", pwd: "bar" }
fetch(RequestURL, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(AdminLoginBindingModel)
})
.then(res => res.json())
.then(obj => callback(obj))
.catch(error => console.log(error))
}
const ValidateResponse = response => console.log(JSON.stringify(response))
URL = 'https://mibase-test.mibase.com.au/members/api/startSession.php?usr=&pwd='
HttpRequest(URL, ValidateResponse)
response doesn't contain received data directly. It provides interface methods to retrieve it. For example use response.json() to parse response text as JSON. It will return promise that resolves to the parsed object. You won't need to call JSON.parse on it:
fetch(RequestURL,
{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(AdminLoginBindingModel)
})
.then((res) => {
return res.json();
}).then((obj) => {
console.log(obj);
});
Check https://developer.mozilla.org/en-US/docs/Web/API/Response and https://facebook.github.io/react-native/docs/network.html for more information.

Issue with POST Request being passed as GET

I'm going to insert the whole module in case you need to see other aspects of the code. The call in question is the addTracks method. The project is to allow the person to search the spotify library, create a playlist of songs, then add the playlist to their account. Everything works fine, besides the tracks actually saving to the account, I get a 401 error on the API, but both Chrome and FireFox also label it as a GET call, instead of as a POST. The error is an authentication error, but I should be authorized correctly, the only odd thing for authorization is the scope, which is taken care of in the redirect in getAccessToken(). What am I missing here? In case you need it: Spotify add track documentation
let accessToken;
let expiresIn;
const clientId = '86f8f621d81a4ce18bd21da9fd2da2b1';
const redirectURI = 'http://localhost:3000/';
const Spotify = {
getAccessToken() {
if (accessToken) {
return accessToken;
} else if (window.location.href.match(/access_token=([^&]*)/) != null) {
accessToken = window.location.href.match(/access_token=([^&]*)/)[1];
expiresIn = window.location.href.match(/expires_in=([^&]*)/)[1];
window.setTimeout(() => accessToken = '', expiresIn * 1000);
window.history.pushState('Access Token', null, '/');
} else {
window.location = `https://accounts.spotify.com/authorize?client_id=${clientId}&response_type=token&scope=playlist-modify-public&redirect_uri=${redirectURI}`;
}
},
async search(term) {
if (accessToken === undefined) {
this.getAccessToken();
}
try {
let response = await fetch(`https://api.spotify.com/v1/search?type=track&q=${term}`, {
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`
}
});
if (response.ok) {
let jsonResponse = await response.json();
let tracks = jsonResponse.tracks.items.map(track => ({
id: track.id,
name: track.name,
artist: track.artists[0].name,
album: track.album.name,
uri: track.uri
}));
return tracks;
}
} catch (error) {
console.log(error);
}
},
async savePlaylist(name, trackURIs) {
if (accessToken === undefined) {
this.getAccessToken();
}
if (name === undefined || trackURIs === undefined) {
return;
} else {
let userId = await this.findUserId();
let playlistID;
fetch(`https://api.spotify.com/v1/users/${userId}/playlists`, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": 'application/json'
},
body: JSON.stringify({
name: name
})
}).then(response => {
return response.json()
}).then(playlist => {
playlistID = playlist.id;
this.addTracks(playlistID, trackURIs, userId);
});
}
},
addTracks(playlistID, trackURIs, userId) {
console.log(trackURIs);
fetch(`https://api.spotify.com/v1/users/${userId}/playlists/${playlistID}/tracks`), {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": 'application/json'
},
body: JSON.stringify({
uris: trackURIs
})
}
},
findUserId() {
if (accessToken === undefined) {
this.getAccessToken();
}
let userId;
return fetch(`https://api.spotify.com/v1/me`, {
headers: {
Authorization: `Bearer ${accessToken}`
}
}).then(response => {
return response.json()
}).then(jsonResponse => {
userId = jsonResponse.id;
return userId;
});
}
};
export default Spotify;
I'm beginner but probably you should check bracket in fetch() method in addTracks()
addTracks(playlistID, trackURIs, userId) {
console.log(trackURIs);
fetch(`https://api.spotify.com/v1/users/${userId}/playlists/${playlistID}/tracks`->)<-, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": 'application/json'
},
body: JSON.stringify({
uris: trackURIs
})
}
},
correct
addTracks(playlistID, trackURIs, userId) {
console.log(trackURIs);
fetch(`https://api.spotify.com/v1/users/${userId}/playlists/${playlistID}/tracks`, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": 'application/json'
},
body: JSON.stringify({
uris: trackURIs
})
})
},

Categories

Resources