I'm having a lot of trouble using axios to send requests to this API, which accepts parameters in an object fashion:
GET https://api.osrsbox.com/items?where={ "name": "Abyssal whip", "duplicate": false }
The main problem is that axios automatically encodes the string. Searching for solutions in StackOverflow, i've came to this:
const item = "Abyssal Whip"
const config = {
paramsSerializer: (params) => {
return querystring.stringify(params, { arrayFormat: 'brackets' });
},
params: {
where : {
name: item,
duplicate: false
}
}
}
axios.get("https://api.osrsbox.com/items", config).then( (resp) => {
[...]
})
This results in the following request:
https://api.osrsbox.com/items?where=%7B%22name%22:%22Abyssal%20Whip%22,%22duplicate%22:false%7D
I would like to know what am i doing wrong. Thanks in advance.
PS: I'm making requests from a Node.js environment/server.
That's a really weird format that your API accepts. But I suppose it's what you've got to work with...
It looks to me like you might be successful by changing the relevant part of your code to:
where: JSON.stringify({
name: item,
duplicate: false
})
(I hope the spaces in your example request aren't required, if they are then this won't work)
you have to use npm package "qs"
npm i qs
make a object which has all your request body params eg -
const requestBody = {
....... ;
}
now while making Axios request -
Axios.get("https://api.osrsbox.com/items", qs.stringyfy(requestBody), config)
.then(res => console.log(res)
.catch(err => console.log(err))
Related
I have been trying to extract a token from say http://test.com/confirm?token=MMsndiwhjidh... and then send a post request to another server.
I have tried this:
export default {
data() {
return {
confirmation : false,
somethingWrong: false
}
},
created: function() {
axios.post('/confirm', null, {
method: 'post',
params: {
token:this.$route.query.token
}
})
.then(function(res) {
console.log(res)
this.confirmation = true
})
.catch(function(error) {
console.log(error)
this.somethingWrong = true
})
}
}
I got the following errors:
I think I am not able to extract the token properly.
The reason is you're using declarative functions instead of arrow functions in your then / catch blocks. The this don't refer to the same thing (here, this is not your Vue component).
Try like this:
.then((res) => {
console.log(res)
this.confirmation = true
})
I won't try to explain the difference myself as there are plenty of articles on the web about it. Here's one
I'm using Cypress to do some API testing, but I am struggling to access values in the JSON response body; however I can perform assertions against the body which suggests it's receiving it correctly.
Below I am trying to assign the JSON body (response.body) and then get the value of 'id' out of it:
describe('Creating a board', () => {
it('should create a board', () => {
cy.request({
method : 'POST',
url:`${requestUrl}/boards/`,
qs: {
name : "test-board",
token : token,
key : key
}
}).then((response) => {
expect(response).property('status').to.equal(200)
expect(response.body).property('id').to.not.be.oneOf([null, ""])
const body = (response.body)
boardId = body['id']
})
})
I've done numerous searches and can't find a concrete way to do it. Any help would be appreciated...
I managed to solve this by using a Promise;
Doing some further reading, I found out the then function I am executing is synchronous (I'm new to JS, pls don't hurt me).
I refactored the then function to the following:
.then((response) => {
return new Promise(resolve => {
expect(response).property('status').to.equal(200)
expect(response.body).property('id').to.not.be.oneOf([null, ""])
const respBody = response.body;
boardId = respBody['id']
resolve(boardId)
})
It's probably not entirely correct or best practice, but it will do for my demo
Although not needed anymore as you found a workaround, I've looked into my cypress code. I was able to access properties of response body followingly:
cy.request({
...
}.its('body').then((body) => {
const whatever = body.whatever;
})
I believe it basically works the same as your workaround - waiting to resolve body in a promise.
I was able to do it in the following way:
cy.request(
'POST',
url,
payload()).then((response) => {
expect(response.body).to.have.property('ReturnCode', 'Success')
expect(response.body).to.have.property('ReturnText', 'Success')
expect(response.body).to.have.property('PaymentInstructionId')
paymentID = response.body.PaymentInstructionId
})
paymentID is the variable that is filled with the value that i want from the repply.
I am trying to map over the returned json and save the id into profile/profiles. However it does not seem to be mapping over the the data correctly, id: ${ profile.id } this bit needs to be changed? Any help is much appreciated.
Is their a online tool that can help with me this?
API request:
// Grabs company data from the json url
private getProfiles() {
let config = {
headers: {'Authorization':'Bearer AQVVEqNXTWVYPpPYivKNWVO8jsTx2eveV3kBg'}
}
axios
.get("https://cors-anywhere.herokuapp.com/" + "https://api.linkedin.com/v2/me", config)
.then(response =>
response.data.map(profile => ({
id: `${ profile.id }`
}))
)
.then(profiles => {
this.setState({
profiles
});
})
// We can still use the `.catch()` method since axios is promise-based
.catch(error => this.setState({ error, isLoading: false }));
}
Json data returned:
{
"localizedLastName": "King",
"id": "fm0B3D6y3I",
"localizedFirstName": "Benn"
}
When I console log the response.data
If the only data returned from your endpoint is the JSON you posted, then you don't have an array to map over.
You have a single object.
I've never used the axios library before, but looking at the source code response.data should be the JSON-parsed responseText from the XHR request:
https://github.com/axios/axios/blob/4f189ec80ce01a0275d87d24463ef12b16715d9b/lib/adapters/xhr.js#L51-L53
https://github.com/axios/axios/blob/4f189ec80ce01a0275d87d24463ef12b16715d9b/lib/defaults.js#L61
And now I see that you have posted response.data and it matches what I'd expect.
With that in mind I'd suggest handling it like this:
// Grabs company data from the json url
private getProfiles() {
let config = {
headers: {'Authorization':'Bearer AQVVEqNXTWVYPpPYivKNWVO8jsTx2eveV3kBg'}
}
axios
.get("https://cors-anywhere.herokuapp.com/" + "https://api.linkedin.com/v2/me", config)
.then(response => ({
id: profile.id
}))
.then(profiles => {
this.setState({
profiles
});
})
// We can still use the `.catch()` method since axios is promise-based
.catch(error => this.setState({ error, isLoading: false }));
}
What you're getting back is a single profile though. If you need profiles to be an array you'll need to put the response in an array.
I don't get it, what you are trying to do. In the map you have a callback function, but as I see you wrote there an object. If you are wanting to rewrite the current profile's id then write this:
response.data.map(profile => ({
profile.id = `${ profile.id }`;
}))
But if you want it to make a variable then this:
response.data.map(profile => ({
let id = `${ profile.id }`;
}))
When I call the URL, an undefined number of requests are sent.
Now I try to find out if one of the requests contains a certain payload.
cy.server();
cy.visit(url);
cy.route({
method: 'POST',
url: '**/t/e/**',
}).as('xhrRequest');
I have found a similar approach on How to capture all API calls in cypress? so far.
the problem here is that a fixed number of API calls is assumed.
cy.wait(Array(60).fill('#xhrRequest'), { timeout: 30000 }).then((xhrs) => {
xhrs.forEach((res) => {
expect(res.status).not.to.be.null
})
})
How do I get it that all requests are intercepted and fail my test if there is not a single request containing the payload.
I already wrote something like this in puppeteer
let hasSpecialRequest = false;
page.on('request', request => {
if (isSpecialRequest(request)) {
hasSpecialRequest = true;
}
request.continue();
});
await page.setRequestInterception(true);
expect(hasSpecialRequest).to.equal(true);
The system checks whether each request is one of the special requests and sets the variable accordingly. Something like this I try to recreate with Cypress.
You might consider doing cy.exec and run a script in another language and return status from subprocess.
I may have misunderstood the problem but since I got here through my Google expedition maybe this might help someone that had my problem and possibly you.
At first I used the cy.wait(#alias) but could never retrieve all the responses (only one response was being shown and I couldn't figure out how to access ALL the responses). So I ended up immediately storing the responses into another array to access within the test.
let xhrRequests;
function getXhrRequests() {
xhrRequests = [];
cy.intercept('GET', '**', (res) => {
xhrRequests.push(res);
});
return xhrRequests;
}
describe('Some', function () {
it('Thing 1', () => {
let thing1 = getXhrRequests();
cy.visit('http://some.site');
thing1.forEach((res) => {
expect(res.status).not.to.be.null;
})
}
it('Thing 2', () => {
let thing2 = getXhrRequests();
cy.visit('http://some.site/2');
thing2.forEach((res) => {
expect(res.status).not.to.be.null;
})
}
});
I tested with two apis for axios put.
for one api its working fine where as with another api it throws an error.
for one api its showing request as options eventhough I gave as put and I am seeing 403 forbidden error
for this api i am facing the issue 'http:///sports/sportsId',
I debugged but still I am not able to find the issue.
is it a back-end issue
can you tell me how to fix it, providing my code snippet below
savesports = () => {
console.log("savesports---->");
console.log(this.state.sports);
let savesports = this.state.sports;
savesports.updatedBy = 'xxx';
savesports.priceRuleDescription = "test description";
let data = {
name: "yyyy",
email: "sda#gmail.com",
phone: "2321313"
};
axios
.put("https://jsonplaceholder.typicode.com/users/1", data)
.then(r => console.log("dada", r));
console.log(JSON.stringify(savesports));
axios
.put(
'http:///sports/sportsId',
savesports
// { headers: { 'Content-Type': 'application/json' } }
)
.then(r => console.log(r))
.catch(e => console.log(e));
//this.toggleDrawer("right", false);
this.setState({ right: false });
this.setState({ snackBarOpen: true });
setTimeout(() => {
this.setState({ snackBarOpen: false });
}, 6000)
};
1. Check if URL is right
I would first check if the URL is right.
Try changing http:///sports/sportsId to http://sports/sportsId if that's actually the URL you are requesting to.
2. Avoid name confusion
Both the method name and the put data variable name are the same (savesports). I would change the put data variable name to something meaningful like
let sportsData = this.state.sports;
sportsData.updatedBy = 'xxx';
sportsData.priceRuleDescription = 'test description';
3. Check authentication
403 might also be to auth error. I would check if the endpoint requires any authentication token or headers.