Why Laravel API request sent from Vue gets canceled - laravel

I'm trying to send formData from Vue using Axios to Laravel (v6) API on Laravel Homestead containing some data and an excel file to read and validate data in the backend. If the sheet contains records than 800 for example everything works file but when I increased it to 850 or 1000 the request gets cancelled I don't know why.
Successful request
Cancelled request
As you see it doesn't reach the actual request like the successful request it just gets cancelled at the beginning.
But the weird thing is that the data got validated and inserted into the DB already but the response gets converted to cancelled and the actual success response doesn't get returned from the API
Is this error related to server configurations or needs code fix?
Vue code
submitImportedUsers(){
let formData = this.gatherFormData();
this.importUsers(formData);
},
gatherFormData() {
//create formData to send normal dta with files
let formdata = new FormData();
formdata.append("users", this.form.usersFile);
formdata.append("images", this.form.imagesFile);
const json = JSON.stringify({
unique_fields: this.form.uniqueFields,
update_duplicates: this.form.duplicateUsers,
entity_id: this.entityId,
user_id: this.userId,
});
formdata.append("data", json);
return formdata;
Laravel
$usersImportService->moveFile($request->file('users'));
public function moveFile($file) {
if(is_null($this->folderName) || !isset($this->folderName)){
$this->generateUuid();
}
$ext = $this->getRequestFileExt($file);
$usersFileName = $this->folderName.'.'.$ext;
$this->fileName = $usersFileName;
$path = storage_path().'/uploads';
\File::isDirectory($path) or \File::makeDirectory($path, 0777, true, true);
move_uploaded_file($file->getRealPath(), $this->storePath.$usersFileName);
}
Then start reading it using Laravel Excel and insert the data into the database

I found the issue which the front end developer did in axios instance that might help anyone facing this issue
axiosInstance.defaults.timeout = 10000;
It could be anything like that used to set the timeout of axios it's set to 10 seconds here and the request needs more time so setting this to a higher value solved the issue

Related

Cannot send HTML string through axios

I'm working on a blog like website and have being adding this rich text editor feature to it. This app is built with Vue for the front and Laravel, and this text editor is a dependency called vue-quill.
I use axios to post all the data and nothing more. Im using it to create posts with Raw html tags from this editor, it actually works fine creating and updating posts locally, but only fails on my server whenever you try to update any post, it returns empty response and status 200.
It does not happen when you create a post. Im not using any kind of image upload service but I'm using my own solution, which consists on transforming images from base 64 to file objects and then send them to a controller via axios. On update action it is similar but the images that were already uploaded on the post are fetched, then converted to base64 again and then converted to file objects again (in order to preserve previous images) for new images I convert them from base64 to file object as I do on my create action.
Here is the code I use to create from base 64 to file object :
dataURLtoFile(dataurl, filename) {
let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
And this would be my axios action:
axios
.post("/api/posts", formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then((response)=>{
this.submit = false;
this.title= '';
this.showAlert("success", 'Post created successfully.' , '')
})
.catch((error) =>{
// etc
});
The formData object only store the raw html, images and a string, nothing more than that, but I'm not sure if the headers of the axios are ok, the laravel action is like this:
public function updatePost(Request $request)
{
$request->validate([
'files.*' => 'required|mimes:jpg,jpeg,png|max:2048'
]);
$post = Post::find($request->postId);
$images = $request->file('files');
// creamos el post primero
$post->title = $request->title;
$post->body = $request->body;
$post->save();
// the rest of the code for storing images
return response()->json(['post' => $post]);
I think something is preventing it to reach to this action, because the response is empty.
Edit: I had a problem later where the request was giving status 301, after searching here and there I found out that everything was okay but in the server. The host has to be configured as stated here in this quick guide for 301 troubles : https://medium.com/#mshanak/laravel-return-empty-response-690f8a308d9a.

Vue API Calls and Laravel Middleware

Is it possible to globally set a listener on API calls made with Axios in Vue? The Laravel back-end has middleware set up on each endpoint that will either give the requested data or return a message saying that they need to check their messages. My goal is to capture that message and redirect the user to the page to view their message. I can't think of a way to do this other than setting something on each function that checks for the message and responds accordingly. There are hundreds of functions and that it wouldn't be a clean solution.
Any and all recommendations are welcome!
Using Axios Interceptors you can do something along these lines:
this.$http.interceptors.response.use(response => () {
// Redirect to a new page when you send
// custom header from the server
if (response.headers.hasOwnProperty('my-custom-header')) {
window.location.href = '/another-page';
}
// Or when you get a specific response status code
if (response.status === 402) {
window.location.href = '/another-page';
}
// Or when the response contains some specific data
if (response.data.someKey === 'redirect') {
window.location.href = '/another-page';
}
// ...or whatever you want
});

Sharing root data with router-view component vue js

Best to give more context to this first.
I am creating an Single Page Application with vuejs, vue-router. When the user logs in the user object is returned from the backend. I am using Laravel 5.4 for the backend. The user object is then sorted on the vue $root instance so it can be accessed anywhere by using this.$root.user.
My only problem is that when I want to edit the user data, I have an edit form in which the user data should be automatically populated with the existing data. This would be fine if I just wanted to do something like this: v-model="this.$root.user.first_name" but I have a form object which helps with validation and making everything more modular.
So in the data return I have this on the router-view component:
data: function() {
return {
form: new Form({
first_name: this.$root.user.first_name,
last_name: this.$root.user.last_name,
country: this.$root.user.country,
preffered_currency: this.$root.user.preffered_currency,
email: this.$root.user.email,
})
}
}
The only problem is that everything is undefined. I'm not sure how to get around the problem so any help which be appreciated. Thanks.
I figured a way to do it.
What I forgot to add is that on refresh of the page obviously vue forgets about all of the current stored data so because of that I have to make a request to the backend to get the current user.
So when the ajax request is made to get the current user I created a new Vue object in which all objects can see and assigned it to Window.Event and created a new Vue instance against that. Window.Event = new Vue({});
Now once the ajax request has returned I did Window.Event.$emit('user', this.user) and on the component which needed the user data I just created an $on event with create().
created() {
Window.Event.$on('user', function(user){
this.form.first_name = user.first_name
this.form.last_name = user.last_name
this.form.country = user.country
this.form.preffered_currency = user.preffered_currency
this.form.email = user.email
}.bind(this));
}

laravel api with vue 2 js not returning data - could 'localhost:8000' (or '127.0.0.1:8000') be the issue?

I am using the repo https://github.com/mschwarzmueller/laravel-ng2-vue/tree/03-vue-frontend so I have 100% confidence in the reliability of the code. I can post through the laravel api endpoint through the very simple Vue client, and also through Postman. Through Postman I can retrieve the table data array, but not so in the client app. In POSTMAN:
localhost:8000/api/quotes
works just fine.
IN THE vue 2 js CLIENT APP:
methods: {
onGetQuotes() {
axios.get('http://localhost:8000/api/quotes')
.then(
response => {
this.quotes = (response.data.quotes);
}
)
.catch(
error => console.log(error)
);
}
returns nothing. returning the response to Console.log returns nothing. The Network/XHR tab shows the table data rows, but I am not sure what that means.
I know for sure that this code works for others with their unique api endpoints, which I assume may not use localhost or '127:0.0.1:1080.
Edit: in response to request for more info
public function getQuotes()
{
$quotes = Quote::all();
$response = [$quotes];
return response()->json($response, 200);
}
and the relevant route:
Route::get('/quotes', [
'uses' => 'QuoteController#getQuotes'
]);
Just to confirm: I am using verified github repo code in which the ONLY change is my api endpoint addressas mentioned in the first line of the body of this question. . Note that the Laravel back end is also derived from a related repo in Max's fine tutorial. The running code can be seen at
So I really don't think this is a coding error- but is it a configuration error due to me using local host??
EDIT: It WAS a coding error in the laravel controller as shown below
The reason your code isn't working if because you haven't provided a key for your $quotes in your controller but you're looking for it in your vue file (response.data.quotes).
[$quotes] is essentially [0 => $quotes] so when the json response comes through it be 0: [...] not quotes: [...].
To get this to work you just need to change:
$response = [$quotes];
to:
$response = ['quotes' => $quotes];
Furthermore, just an FYI, you don't need to provide the 200 in response->json() as it's the default and you can just return an array and Laravel automatically return the correct json response e.g.:
public function getQuotes()
{
$quotes = \App\Models\Artist::all();
return compact('quotes'); //<-- This is just another way of writting ['quotes' => $quotes]
}
Obviously, you don't have to if you don't want to.
Hope this helps!

Angular2 + Web API + token based authentication

I am trying to learn Angular2
and I am trying to create a simple blog with authentication.
this here is my add a new post method:
[Authorize]
// POST: api/Post
public PostModel Post([FromBody]PostViewModel model)
{
var post = new PostModel
{
Body = model.Body,
Title = model.Title,
AuthorId = IdentityExtensions.GetUserId(User.Identity),
};
var res = blogRepo.AddPost(post);
return res;
}
everything works fine, but IdentityExtension.GetUserId() do not return the most current logged in user but the first user since the app started.
basically I am looking for a way to make sure that the current user logs out on the server as well as on the client (the client side is just a simple removal of the localStorage.removeItem("jwt");)
also there is a good chance that what I am doing is totally wrong, but I can't access the ApplicationUserManager in this controller.
ok I have found the problem, although I haven't managed to solve it yet but I will update this when i do, and I am writing this as an answer since the problem is totally different from what I asked and thought to be.
the problem is related to sending the authentication hints as Thierry Templier suggested. I have a file that exports headers like this:
export const authHeaders = new Headers();
authHeaders.append('Accept', 'application/json');
authHeaders.append('Content-Type', 'application/json');
authHeaders.append('Authorization', 'Bearer ' + localStorage.getItem('jwt'));
And I Import this header where ever I need it. but I am not sure why it always sends a cached value (i.e the first value stored on the client and it has nothing to do with the server side as my question implies).
to solve this issue I just have to make sure the latest access-token stored on localstorage is sent to the server.
EDIT: for now I am constructing the headings in the constructor.

Resources