I've got a react/d3 project where I'm using axios.get to retrieve my data passed into a local url with express. Here is my code :
return axios.get("http://localhost:3000/gadata")
.then(response => {
dispatch({
type: 'FETCH_DATA_SUCCESS',
isFetching: false,
data: response.data.rows
});
})
Instead of axios, I would like to be able to use d3-request. How should I refactor my code ?
Related
I am playing around with Cypress for e2e testing and want to execute login flow on each of the spec file.
I know that we can do it by storing it locally by writing custom commands like this :
Cypress.Commands.add('login', ()=> {
cy.request({
method : 'POST',
url : 'url',
...
}
}).then((resp) => {
window.localStorage.setItem('jwt',resp.body.user.token)
})
})
and then calling this function in our actual spec file.
But with my application, there are multiple api calls to be made one after the other in order to actually land up inside the application. How can I achieve this in custom commands? My application actually takes username and password in step-1, and then from the jwt received it executes another api call, and then a final one. I want to store the last jwt value so that I can continue with the rest of the application.
You can parameterize your cypress custom commands, so from the test spec file you can just pass the URL.
Custom Command:
Cypress.Commands.add('login', (url) => {
cy.request({
method: 'POST',
url: URL,
...
}).then((resp) => {
window.localStorage.setItem('jwt', resp.body.user.token)
})
})
In your test write:
cy.login('https://example1.com')
cy.login('https://example2.com')
....
The requests can be nested,
Cypress.Commands.add('login', () => {
cy.request({
method : 'POST',
url : 'url1',
...
})
.then((resp1) => {
cy.request({
method : 'POST',
url : 'url2',
body : { token: resp1.body.user.token }
})
.then((resp2) => {
cy.request({
method : 'POST',
url : 'url3',
body : { token: resp2.body.user.token }
})
.then((resp3) => {
window.localStorage.setItem('jwt', resp3.body.user.token)
})
})
})
})
I'm writing a plugin for Wordpress that uses VueJS. Everything works fine until I come to send the data via a Ajax POST request.
Here is an extract of what I have:
data () {
return {
form: {
items: []
}
}
}
methods: {
processOrder () {
axios({
method: 'post',
url: '/ajax.php',
data: JSON.stringify({
action: "process_order"
})
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
}
and when I examine the request in Chrome I get:
"body":"{\"action\":\"process_order\"}"
which means the action key is never found on the server. If I take out the Stringify then the server sees nothing. Any ideas on how to remove the escaping?
u can try this
npm install qs --save-dev
and use:
import Qs from qs
data:Qs.stringify({action: "process_order"})
I have a problem with file uploading on my Laravel&Vue.js website using API
I get - 500 Server Error "SyntaxError: Unexpected token < in JSON at position 0"
I'm trying to create new value in my database, for this I use pop up form with image uploading and other fields like username, email, phone etc.
I've tested my API via Postman - it works fine, but when I try to create this directly on my website - it desn't work
you can check a function which must create new value(startup) in DB:
createStartup() {
fetch('/api/startup', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: JSON.stringify(this.new_startup),
})
.then(res => res.json())
.then(res => {
$('#createStartUp').modal('hide');
alert('New Startup Created!');
// this.fetchStartups();
})
.catch(err => console.log(err));
}
I think the issue in Headers (I didn't use any Headers in Postman), when I tried to not use any Headers - it didn't wok too, also O tried to use Content-Type with bypass and unfortunately it didn't work
Also I think it must be helpful - how I get image in vue.js:
HTML:
<input id="upload_create" class="file-upload_input" type="file" #change="onFileSelected" >
JS (Vue.js):
onFileSelected(event) {
this.new_startup.startup_logo = event.target.files[0];
}
Thanks a lot guys for any ideas and helps!
You need to pass your data as form-data. Here is how I managed to send a file upload via Vue.js:
createStartup() {
let formData = new FormData();
formData.append('file', this.new_startup.startup_logo);
formData.append('anythingElse', JSON.stringify(this.someVariable);
// ... etc
fetch('/api/startup', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data'
},
body: formData,
})
.then(res => res.json())
.then(res => {
$('#createStartUp').modal('hide');
alert('New Startup Created!');
// this.fetchStartups();
})
.catch(err => console.log(err));
}
Background:
The following AJAX code works successfully (ReactJS + JQuery frontend, PHP backend).
const data = {request_type:"load_data", start:1, end:50};
$.ajax({
type: "POST",
url: "http://localhost/site/server.php",
data: data,
dataType: "json",
success: (JSobject) => {
this.setState({arr: JSobject.arr});
}
});
In Chrome Dev Tools server.php's Headers show up as "Form Data" like so:
At the PHP server backend, there's this line of code:
$request_type = $_POST["request_type"];
In an attempt to learn how to do Fetch (I've avoided it so far mostly because I had AJAX boilerplate that worked well), I've been playing around with trying to build a drop-in replacement for the above code.
I tried this:
const data = {request_type:"load_data", start:1, end:50};
fetch("http://localhost/site/server.php", {
method: "POST",
body: data
})
.then((JSobject) => {
this.setState({arr: JSobject.arr});
});
But I get this PHP error:
Notice: Undefined index: request_type in .....server.php
And in Chrome Dev Tools server.php's Headers show up like so:
So, I tried changing the data to JSON.stringify(data) like so:
const data = {request_type:"load_data", start:1, end:50};
fetch("http://localhost/site/server.php", {
method: "POST",
body: JSON.stringify(data)
})
.then((JSobject) => {
this.setState({arr: JSobject.arr});
});
But I still get the exact same PHP error:
Notice: Undefined index: request_type in .....server.php
And in Chrome Dev Tools server.php's Headers show up like so:
Out of general frustration (although it's pointless because I'd be still using JQuery), I thought I'd use JQuery's $.param(), and that would surely work.
So I tried this:
const data = $.param({request_type:"load_data", start:1, end:50});
fetch("http://localhost/site/server.php", {
method: "POST",
body: data
})
.then((JSobject) => {
this.setState({arr: JSobject.arr});
});
Still get the same PHP error
Notice: Undefined index: request_type in .....server.php
And in Chrome Dev Tools server.php's Headers show up like so:
My question: how do I modify the Fetch code above so that it becomes a drop-in replacement for the AJAX code up top.
I realize that the use of horizontal lines can be bothersome for some. You can give yourself permission to believe that it really helps a lot of us regular folks follow what's going on in the question.
Answering my own question for others who might encounter this issue in future (and also for my own reference). Figured out the answer via this link and this link. The following code worked:
fetch("http://localhost/site/server.php", {
method: "POST",
body: JSON.stringify(data)
}).then(response => {
return response.json();
}).then((JSobject) => {
this.setState({arr: JSobject.arr});
});
I had to change some PHP code on the server. The initial "gatekeeper" code was:
$_POST = array_map("trim", $_POST);
$request_type = $_POST["request_type"];
This had to be commented out:
$_POST = array_map("trim", $_POST); //this had to be commented out
And this had to be added instead:
$content = trim(file_get_contents("php://input"));
$_POST = json_decode($content, true);
And in Chrome Dev Tools server.php's Headers show up as "Request Payload":
I also saw some suggestions to add a "headers" key like so:
fetch("http://localhost/site/server.php", {
method: "POST",
headers: {"Content-Type": "application/x-www-form-urlencoded",},
body: JSON.stringify(data)
}).then(response => {
return response.json();
}).then((JSobject) => {
this.setState({arr: JSobject.arr});
});
This did also work, but in Chrome Dev Tools server.php's Headers show up as "Form Data":
Another way to do this is by wrapping the object (to be sent) in JQuery's $.param() (I was interested in this because I often use $.param() to append key-values to form.serialize(), on the client side before sending to the PHP on the server)
const data = $.param({request_type:"load_data", start:1, end:50});
fetch("http://localhost/site/server.php", {
method: "POST",
headers: {"Content-Type": "application/x-www-form-urlencoded",},
body: data
}).then(response => {
return response.json();
}).then((JSobject) => {
this.setState({arr: JSobject.arr});
});
The advantage of doing it this way was that no changes were needed to the code on the server side.
In Chrome Dev Tools server.php's Headers show up as"Form Data":
Without using JQuery:
Re: the previous method (using $.param()), it's possible to do it completely without JQuery, but then one would need some function to chain the javascript object's key-value pairs while properly encoding special characters as x-www-form-urlencoded (this link explains how to do it).
E.g., instead of this:
const data = $.param({request_type:"load_data", start:1, end:50});
...
body: data
One would do this:
const data = {request_type:"load_data", start:1, end:50};
...
...
body: "request_type=load_data&start=1&end=50"
My ajax axios like this :
let formData = new FormData()
formData.append('file', user.avatar)
formData.append('selected_data', JSON.stringify(user))
axios.post('/member/profile/update',
formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}
)
.then(response => cb(response))
.catch(error => ecb(error))
My routes like this :
Route::post('update', 'member\UserController#update')->name('member.profile.update');
If the script executed, it works. I success get the data sended
But here, I want to change post method to put method. Because this used to update profile
I change like this :
axios.put(...
And the routes :
Route::put('update', ...
I don't success get the data sended. The data sended is empty
How can I solve this problem?
Update :
If I console.log(user), the result like this :
Laravel uses method spoofing for PUT, use axios.post and add the following to your requests data:
data: {
...
_method: 'PUT',
...
}
You can do:
formData.append('_method', 'PUT')
Complete example using axios:
axios.post('/user', { _method: 'PUT', foo: 'bar' })
.then(function (response) { console.log(response); })
.catch(function (error) { console.log(error); });
Form method spoofing