web-dev-qa-db-fra.com

React + Laravel 5.8.33 + Axios: erreurs lors de l'enregistrement de l'utilisateur avec une demande axios.post; clarifier le problème du code

Mise à jour

Vérifier mon onglet réseau dans mes dev-tools de firefox me donne ceci:

Response headers (290 B)    
Raw headers
Access-Control-Allow-Origin 
*
Allow   
POST
Cache-Control   
no-cache, private
Connection  
close
Content-Type    
text/html; charset=UTF-8
Date    
Sat, 31 Aug 2019 09:45:04 GMT
Date    
Sat, 31 Aug 2019 09:45:04 GMT
Host    
localhost:8000
X-Powered-By    
PHP/7.2.19-0ubuntu0.18.04.2
Request headers (438 B) 
Raw headers
* Accept: */* *
Accept-Encoding 
gzip, deflate
Accept-Language 
en-US,en;q=0.5
Access-Control-Request-Headers  
x-csrf-token,x-requested-with,x-xsrf-token
Access-Control-Request-Method   
POST
Connection  
keep-alive
Host    
localhost:8000
Origin  
http://127.0.0.1:8000
Referer 
http://127.0.0.1:8000/register
User-Agent  
Mozilla/5.0 (X11; Ubuntu; Linu…) Gecko/20100101 Firefox/68.0

Pourquoi la méthode GET? En essayant de le changer à partir des outils, il donne que POST n'est pas autorisée. De plus, lors de la soumission de la demande, elle donne les informations suivantes:

Mise à jour

J'ai commencé à apporter des modifications au fichier bootstrap.js, où mon axios est requis, mais je n'ai pas réussi. J'ai essayé de changer

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

à

window.axios = require('axios');

window.axios.defaults.headers.common = {
    'X-Requested-With': 'XMLHttpRequest',
    'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
};

mais vraiment, je ne peux pas arriver à un point. Je ne peux pas comprendre comment le tutoriel lié dans mes commentaires a fonctionné et je commence à manquer d'idées sur quoi regarder. Donc, toute aide est appréciée; si quelqu'un peut pointer vers une référence valide qui dit, regardez, c'est un problème non résolu, alors j'implémenterai py project avec un code différent; mais sinon, ce problème ne devrait pas rester non résolu. Si c'est une erreur mineure de ma part, alors où est-elle exactement? Merci à tous.

Remarque: Sur mes messages d'origine, je n'ai pas montré à quoi ressemblent mes itinéraires Web. Depuis que j'utilise React depuis Laravel (j'ai utilisé dans le terminal php artisan preset react;) mes itinéraires web sont passés du code préconfiguré laravel

Route::get('/', function () {
    return view('welcome');
});

au nouveau code qui appelle l'application React:

Route::view('/{path?}', 'app');

pdate: J'ai essayé (depuis hier) de changer ma conf Apache2 et mon problème persiste. Je ne sais pas si cela doit être considéré comme un changement:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/api/user/register. (Reason: missing token ‘x-requested-with’ in CORS header ‘Access-Control-Allow-Headers’ from CORS preflight channel).

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/api/user/register. (Reason: CORS request did not succeed).

Source map error: request failed with status 404
Resource URL: http://127.0.0.1:8002/js/app.js
Source Map URL: popper.js.map

pdate2: J'ai essayé de changer ma demande de publication axios:

const dataofuser={
    name:data.name,
    email:data.email,
    password:data.password
}


 const instance = axios.create({
     method:'post',
     baseURL: 'http://localhost:8000/api/user/',
     timeout: 1000,
     headers: {'Access-Control-Allow-Origin': '*' , 'Access-Control-Allow-Methods ':  'POST, GET, OPTIONS, PUT, DELETE','Access-Control-Allow-Headers':  'Content-Type, X-Auth-Token, Origin, Authorization','X-Requested-With': 'XMLHttpRequest' }
 });

instance          .post("register/create",dataofuser)
           .then(response => {
            console.log(response);
            return response;
          })
           .then(json => {
            if (json.data.success) {
              alert(`Registration Successful!`);
              history.Push('/')

... Mais alors je reçois

nom d'en-tête invalide


Original Comme je l'ai mentionné précédemment dans un autre article, je suis actuellement en autoformation React et Laravel. J'essaie de créer une application d'enregistrement de base avec React en tant que front-end et Laravel en tant que back-end. Ce message concerne les erreurs qui surviennent lorsque je remplis le formulaire d'inscription et essaie de le soumettre; l'utilisateur ne reçoit pas enregistré et j'obtiens plusieurs erreurs selon ce que j'essaye.

Si j'essaye:

axios
          .post("http://localhost:8000/api/user/register", {
              name: data.name,
              email: data.email,
              password: data.password
          })

J'entre dans la console:

> Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/api/user/register. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

>Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/api/user/register. (Reason: CORS request did not succeed).

>Source map error: request failed with status 404
Resource URL: http://127.0.0.1:8000/js/app.js
Source Map URL: popper.js.map

>[object Object] Error: Network Error 

Si j'essaye

axios
  .post("/user/register", {
      name: data.name,
      email: data.email,
      password: data.password
  })

alors j'obtiens (je crois que c'est une erreur concernant une mauvaise définition d'itinéraire):

Source map error: request failed with status 404
Resource URL: http://127.0.0.1:8000/js/app.js
Source Map URL: popper.js.map

Si j'utilise

axios
  .post("/api/user/register", {
      name: data.name,
      email: data.email,
      password: data.password
  })

Je reçois:

Source map error: request failed with status 404
Resource URL: http://127.0.0.1:8000/js/app.js
Source Map URL: popper.js.map

[object Object] Error: Request failed with status code 500

Je ne sais plus (je ne peux pas clarifier) ​​si j'ai un problème CORS (bien que j'aie pris des mesures qui devraient empêcher de tels problèmes) ou un autre problème de routage ou de transmission de données ou simplement syntaxique. J'irais pour le problème CORS (même si je n'ai aucune idée de ce qu'est cette notification popper.js.map). Je poste le code ci-dessous.


pdate1:

Je viens d'exécuter mon code dans le navigateur Chrome avec le

 axios
          .post("http://localhost:8000/api/user/register", {
              name: data.name,
              email: data.email,
              password: data.password
          })

et j'ai le

Access to XMLHttpRequest at 'http://localhost:8000/api/user/register' from Origin 'http://127.0.0.1:8000' 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.
app.js:70270 [object Object] Error: Network Error
app.js:371 POST http://localhost:8000/api/user/register net::ERR_FAILED

Il semble que j'ai un problème CORS ... et je ne peux pas comprendre hier et aujourd'hui comment le gérer.


Du code:

Mon composant App (parent) contient une fonction qui est transmise à un composant Register (enfant); cette fonction gère le processus d'enregistrement

        import React, {Component} from 'react'
        import ReactDOM from 'react-dom'
        import {BrowserRouter, Route, Switch } from 'react-router-dom'
        // import {Link} from 'react-router-dom'
        import Header from './Header'
        import Intro from './Intro'
        import Register from './Register'
        import Login from './Login'
        import Userpage from './Userpage'
        import Footer from './Footer'
        import Science from './Science'
        import Literature from './Literature'
        // import {AppState} from 'react-native'


        class App extends Component {

            constructor(props){
                super(props);
                this.state={
                    isLoggedIn:false,
                    user:{},
                    data_user:'',
                    data_username:''
                }

                this.username_Callback=this.username_Callback.bind(this)
                this._registerUser=this._registerUser.bind(this)



            }

            componentDidMount() {
                let state = localStorage["appState"];
                if (state) {
                  let AppState = JSON.parse(state);
                  console.log(AppState);
                  this.setState({ isLoggedIn: AppState.isLoggedIn, user: AppState });
                }
          }

            _registerUser(data){

                $("#email-login-btn")
                  .attr("disabled", "disabled")
                  .html(
                    '<i class="fa fa-spinner fa-spin fa-1x fa-fw"></i><span class="sr-only">Loading...</span>'
                  );



                // var formData = new FormData(); 
                // formData.append('data.name');
                // formData.append('data.email');
                // formData.append('data.password');

                console.log(data)
                console.log(data.name)
                console.log(data.email)
                console.log(data.password)
                // console.log(formData)



                axios
                  .post("http://localhost:8000/api/user/register", {
                      name: data.name,
                      email: data.email,
                      password: data.password
                  })
                  .then(response => {
                    console.log(response);
                    return response;
                  })
                  .then(json => {
                    if (json.data.success) {
                      alert(`Registration Successful!`);
                      history.Push('/')


                      let userData = {
                        name: json.data.data.name,
                        id: json.data.data.id,
                        email: json.data.data.email,
                        auth_token: json.data.data.auth_token,
                        timestamp: new Date().toString()
                      };
                      let appState = {
                        isLoggedIn: true,
                        user: userData
                      };
                      // save app state with user date in local storage
                      localStorage["appState"] = JSON.stringify(appState);
                      this.setState({
                        isLoggedIn: appState.isLoggedIn,
                        user: appState.user
                      });
                    } else {
                      alert(`Registration Failed!`);
                      $("#email-login-btn")
                        .removeAttr("disabled")
                        .html("Register");
                    }
                  })
                  .catch(error => {
                    alert("An Error Occured!" + error);
                    console.log(`${data} ${error}`);
                    $("#email-login-btn")
                      .removeAttr("disabled")
                      .html("Register");
                  });

          };



render(){
                return(


                    <BrowserRouter>

                        <Header listNameFromParent={this.state.data_username} />

                        <Footer />

                        <Switch>
                            <Route exact path='/' component={Intro} />
                            <Route path='/register' render={props=><Register {...props} registerUser={this._registerUser}/>}/>

                            <Route path='/login' render={props=><Login {...props} loginUser={this._loginUser}/>}/>
                            <Route path='/userpage' component={Userpage}/>
                            <Route path='/science' component={Science}/>
                            <Route path='/literature' component={Literature}/>

                        </Switch>


                    </BrowserRouter>




                    )
            }
        }

        ReactDOM.render(<App />, document.getElementById('app'))

Mon composant Register contient simplement le formulaire et renvoie les données d'entrée. En utilisant une commande console.log, je vérifie que les données sont bien disponibles dans mon application et dans ma fonction d'enregistrement. Si on me le demande, je peux poster le code.

À mon back-end, j'ai:

api.php

<?php

        use Illuminate\Http\Request;

        // header('Access-Control-Allow-Origin: *');
        // //Access-Control-Allow-Origin: *
        // header('Access-Control-Allow-Methods:  POST, GET, OPTIONS, PUT, DELETE');
        // header('Access-Control-Allow-Headers:  Content-Type, X-Auth-Token, Origin, Authorization');
        /*
        |--------------------------------------------------------------------------
        | API Routes
        |--------------------------------------------------------------------------
        |
        | Here is where you can register API routes for your application. These
        | routes are loaded by the RouteServiceProvider within a group which
        | is assigned the "api" middleware group. Enjoy building your API!
        |
        */

        Route::middleware('auth:api')->get('/user', function (Request $request) {
            return $request->user();
        });


        Route::group(['middleware' => ['jwt.auth','api-header']], function () {

            // all routes to protected resources are registered here  
            Route::get('users/list', function(){
                $users = App\User::all();

                $response = ['success'=>true, 'data'=>$users];
                return response()->json($response, 201);
            });
        });
        Route::group(['middleware' => 'api-header'], function () {

            // The registration and login requests doesn't come with tokens 
            // as users at that point have not been authenticated yet
            // Therefore the jwtMiddleware will be exclusive of them
            Route::post('/user/login', 'UserController@login');
            Route::post('/user/register', 'UserController@register');
        });

API.php (middleware)

<?php

        namespace App\Http\Middleware;

        use Closure;

        class API
        {
            /**
             * Handle an incoming request.
             *
             * @param  \Illuminate\Http\Request  $request
             * @param  \Closure  $next
             * @return mixed
             */
            public function handle($request, Closure $next)
            {
                $response = $next($request);
                $response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Content-Range, Content-Disposition, Content-Description, X-Auth-Token');
                $response->header('Access-Control-Allow-Origin','*');
                $response->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
                $response->header('Access-Control-Allow-Headers',' Origin, Content-Type, Accept, Authorization, X-Request-With');
                $response->header('Access-Control-Allow-Credentials',' true');
                //add more headers here
                return $response;
            }
        }

UserController

<?php

    namespace App\Http\Controllers;

    use Illuminate\Http\Request;
    use App\User;
    use JWTAuth;
    use JWTAuthException;


    class UserController extends Controller
    {
        private function getToken($email, $password)
        {
            $token = null;
            //$credentials = $request->only('email', 'password');
            try {
                if (!$token = JWTAuth::attempt( ['email'=>$email, 'password'=>$password])) {
                    return response()->json([
                        'response' => 'error',
                        'message' => 'Password or email is invalid',
                        'token'=>$token
                    ]);
                }
            } catch (JWTAuthException $e) {
                return response()->json([
                    'response' => 'error',
                    'message' => 'Token creation failed',
                ]);
            }
            return $token;
        }
public function register(Request $request)
        { 


            $validator = Validator::make($request->all(), [
                'name' => 'required|max:255',
                'email' => 'required',
                'password' => 'required'
            ]);
            if ($validator->fails()) {
                return response()->json(['errors'=>$validator->errors()],422);
            }





            $payload = [
                'password'=>\Hash::make($request->password),
                'email'=>$request->email,
                'name'=>$request->name,
                'auth_token'=> ''
            ];




            $user = new \App\User($payload);
            if ($user->save())
            {

                $token = self::getToken($request->email, $request->password); // generate user token

                if (!is_string($token))  return response()->json(['success'=>false,'data'=>'Token generation failed'], 201);

                $user = \App\User::where('email', $request->email)->get()->first();

                $user->auth_token = $token; // update user token

                $user->save();

                $response = ['success'=>true, 'data'=>['name'=>$user->name,'id'=>$user->id,'email'=>$request->email,'auth_token'=>$token]];        
            }
            else
                $response = ['success'=>false, 'data'=>'Couldnt register user'];


            return response()->json($response, 201);
        }
    }

Encore une fois, je ne peux pas clarifier le problème et la procédure d'enregistrement ne fonctionne pas.

12
Constantine Black

avez-vous essayé d'utiliser le jeton csrf comme paramètre de publication? sinon ce que vous pouvez faire est de régler le csrf token et token dans les paramètres de publication de votre demande axios. Cela résoudra votre problème.

0
Kiran Maniya

Je posterai ici comment j'ai compris ce qui se passait avec mon application d'enregistrement simple mais encore Laravel-React-Axios. À partir des articles ci-dessus qui ont tenté de résoudre le problème, seuls certains commentaires de ClueMediator ont été utiles sur la façon de comprendre le problème dans les coulisses et certains commentaires informatifs de Quentin sur mon article. Je dois noter ici que, pour autant que je l'ai vu, tous les autres messages et discussions github sur axios et laravel et .js front-end ne se sont pas concentrés sur cela du tout (ou s'ils l'ont fait, ils l'ont fait sans y porter une attention sérieuse).

Tout d'abord, on peut voir dans mon premier message que le changement de la demande de message de localhost: 8000 au nom de l'api/route semble avoir pour effet la suppression de certains des cors; comme je dirigeais le projet sur un ou deux serveurs à la fois, les cors pouvaient revenir en fonction de l'endroit où l'artisan servait l'application.

Deuxièmement, une erreur interne de 500 apparaissait même dans les cas où les cors avaient été réduits; cela était dû à des erreurs dans le didacticiel dont j'apprenais et concernait une construction incomplète des migrations.

Jusqu'au point. Il semble qu'axios essaie toujours d'envoyer, avec la demande que j'avais dans mon code (une demande de publication dans cet exemple) une demande d'options. Ce que j'ai fait pour vérifier le problème était de changer mon hôte et mon port pendant que l'artisan servait et ensemble mon code pour correspondre correctement à l'itinéraire. Ensuite, en vérifiant l'onglet réseau sur la console, j'ai vu que bien que la demande de publication ait été bien envoyée, j'avais toujours des cors car la demande axios.options allait par défaut à l'hôte local: 8000, mais je n'étais pas ne sert plus mon application à partir de là. Spécifier un artisan pour servir à partir de là, et corriger la construction des migrations, a résolu le problème.

Il est important de souligner quelque chose ici: artisan sert à localhost: 8000 la première fois que vous l'ouvrez/mais en ouvrant un deuxième serveur, il va sur le prochain port disponible comme d'habitude. Où pas pour les erreurs dans le code des migrations, j'aurais probablement pris le problème d'origine artisanale et où il servait. Mais, à cause d'une relation défectueuse avec ma base de données, même alors, j'obtenais une erreur 500 en tant qu'erreur de serveur interne, ce qui m'a fait ouvrir un autre serveur, puis découvrir que axios envoie toujours une demande d'options uniquement à localhost: 8000, même si mon front-end et mon back-end étaient d'accord l'un sur l'autre, avoir de nombreuses modifications dans le code produisait des incohérences. Donc, en conclusion, après avoir traité un mauvais code (quelque chose que j'aurais dû voir plus vite que moi), il s'agissait seulement de mettre correctement les axios et l'artisan en accord.

Toute observation sur la façon dont la logique ci-dessus pourrait être améliorée serait excellente.

Merci à tous.

0
Constantine Black

J'ai installé https://github.com/barryvdh/laravel-cors

pour CORS issue C'est du travail pour moi

Et mieux vaut ne pas utiliser l'en-tête axios par défaut dans certains cas, cela ne fonctionne pas pour moi, utilisez le chargement manuel de l'en-tête

const options = {méthode: 'POST', en-têtes: {'X-CSRF-TOKEN': 'xxx'}, data: data, url,}; axios (options);

0
rully martanto