it-swarm-pt.tech

React + Laravel 5.8.33 + Axios: erros ao registrar o usuário com uma solicitação axios.post; esclarecendo o problema do código

Atualização

Verificar minha guia de rede em minhas ferramentas de desenvolvimento do firefox me dá o seguinte:

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

Por que o método GET? Tentando alterá-lo das ferramentas, ele fornece que POST não é permitido. Além disso, ao enviar a solicitação, ele fornece as seguintes informações:

Atualização

Comecei a fazer alterações no arquivo bootstrap.js, onde meus axios são necessários, mas não tive sucesso. Eu tentei mudar

window.axios = require('axios');

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

para

window.axios = require('axios');

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

mas realmente, não consigo chegar a um ponto. Não consigo entender como o tutorial vinculado nos meus comentários funcionou e estou começando a ter uma escassez de idéias sobre o que procurar. Portanto, qualquer ajuda é apreciada; se alguém puder apontar para uma referência válida que diga, veja, este é um problema não resolvido, implementarei o projeto py com um código diferente; mas se não, esse problema não deve permanecer sem solução. Se é um pequeno erro da minha parte, então onde exatamente é? Obrigado a todos.

Nota: nas minhas postagens originais, não mostrei como são minhas rotas da web. Como estou usando React de dentro do Laravel (eu usei no terminal php artisan preset react;) minhas rotas da web foram do código pré-configurado laravel

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

para o novo código que chama o aplicativo React:

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

pdate: Eu tentei (de ontem) alterar minha conf do Apache2 e meu problema permanece. Não sei se isso deve ser considerado uma mudança:

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: Tentei alterar minha solicitação de publicação do 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('/')

... Mas então eu recebo

nome de cabeçalho inválido


Original Como mencionei antes em outro post, atualmente estou estudando React e Laravel. Estou tentando criar um aplicativo básico de registro com React como front-end e Laravel como back-end. Este post é sobre erros que surgem quando eu preencho o formulário de registro e tento enviá-lo; o usuário não recebe registrado e recebo vários erros, dependendo do que estou tentando.

Se eu tentar:

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

Eu entro no 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 

Se eu tentar

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

então recebo (acredito que isso seja um erro em relação à definição de rota incorreta):

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

Se eu usar

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

Eu recebo:

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

Não tenho mais certeza (não posso esclarecer) se tenho um problema de CORS (embora eu tenha tomado ações que devem evitar esses problemas) ou algum outro problema de roteamento ou passagem de dados ou apenas uma questão sintática. Eu iria para o problema do CORS (embora não tenha idéia do que se trata essa notificação popper.js.map). Estou postando o código abaixo.


Atualização1:

Acabei de executar meu código no navegador Chrome navegador com o

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

e eu peguei o

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

Parece que tenho um problema de CORS ... e não consigo entender desde ontem e durante todo o dia de hoje como lidar com isso.


Algum código:

O componente My App (pai) contém uma função que é passada para um componente Register (filho); esta função lida com o processo de registro

        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'))

O componente My Register apenas contém o formulário e retorna os dados de entrada. Usando um comando console.log, estou verificando se os dados estão realmente disponíveis no meu aplicativo e dentro da minha função de registro. Se solicitado, posso postar o código.

No meu back-end, tenho:

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', '[email protected]');
            Route::post('/user/register', '[email protected]');
        });

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);
        }
    }

Então, novamente, não posso esclarecer qual é exatamente o problema e o procedimento de registro não funciona.

12
Constantine Black

você tentou usar o token csrf como um parâmetro de postagem? caso contrário, você pode definir o csrf token e token nos parâmetros pós da sua solicitação axios. Isso resolverá o seu problema.

0
Kiran Maniya

Vou postar aqui como descobri o que estava acontecendo com o meu aplicativo de registro simples, porém simples do Laravel-React-Axios. Nas postagens acima, que tentaram resolver o problema, apenas alguns comentários de ClueMediator foram úteis para entender o problema nos bastidores e alguns comentários informativos e úteis de Quentin no meu post. Eu tenho que observar aqui, que até onde eu vi, todas as outras postagens e discussões no github sobre axios e laravel e .js front-end não se concentraram nisso) (ou se o fizeram, fizeram sem prestar muita atenção).

Primeiramente, é possível ver no meu primeiro post que alterar a solicitação de post do localhost: 8000 para apenas o nome da API/rota parecia ter como efeito a remoção de alguns dos cors; como eu estava executando o projeto em um ou dois servidores por vez, os cors podiam voltar em função de onde o artesão estava servindo o aplicativo.

Segundo, um erro interno de 500 estava aparecendo mesmo nos casos em que os cors haviam sido reduzidos; isso foi devido a erros no tutorial com o qual eu estava aprendendo e tinha a ver com a construção incompleta das migrações.

Ao ponto. Parece que o axios está sempre tentando enviar, junto com a solicitação que eu estava tendo no meu código (uma solicitação de postagem neste exemplo), uma solicitação de opções. O que fiz para verificar o problema foi alterar meu host e porta, pois o artesão estava servindo e, juntos, meu código para corresponder à rota corretamente. Então, verificando a guia de rede no console, vi que, embora a solicitação de postagem tenha sido enviada corretamente, eu ainda tinha cors porque a solicitação axios.options estava indo por padrão para o host local: 8000, but Eu não estava está veiculando meu aplicativo a partir daí. A especificação do artesão para servir a partir daí e a correção da construção das migrações resolveram o problema.

É importante sublinhar algo aqui: o artisan serve no localhost: 8000 na primeira vez em que você o abre/mas ao abrir um segundo servidor, ele passa pela próxima porta disponível, como normalmente faria. Onde não fosse pelos erros no código de migração, eu provavelmente teria pego o problema originado do artesão e onde ele estava servindo. Mas, por causa de uma relação com defeito no meu banco de dados, mesmo assim, eu estava recebendo um erro 500 como erro interno do servidor, o que me levou a abrir outro servidor e depois descobrir que o axios sempre envia uma solicitação de opções apenas para o host local: 8000, até se meu front-end e back-end concordavam um com o outro, muitas alterações no código produziram inconsistências. Então, em conclusão, depois de lidar com código incorreto (algo que eu deveria ter visto mais rápido do que vi), era apenas uma questão de definir corretamente os axios e o artesão para concordar.

Qualquer observação sobre como a lógica acima poderia melhorar seria ótima.

Obrigado a todos.

0
Constantine Black

Eu tenho instalar https://github.com/barryvdh/laravel-cors

para questão CORS É trabalho para mim

E melhor não usar o cabeçalho axios padrão em alguns casos, não funciona para mim, use o carregamento manual do cabeçalho

opções const = {método: 'POST', cabeçalhos: {'X-CSRF-TOKEN': 'xxx'}, dados: dados, URL,}; axios (opções);

0
rully martanto