Sagar Gautam
Sagar Gautam

Reputation: 9369

TypeError: "NetworkError when attempting to fetch resource."

I've found a lot of question similar to my problem but I don't get solution that's why I've asked here.

I've just started learning front end development using React. I've made separate app for front end and backend running at different ports.

Backend : Laravel framework app running at incomeexpense.stacklearning.com/

Frontend : React app running at localhost:3000/

I've a form like this:

import React,{Component} from 'react';

export default class Register extends Component{
constructor(props){
    super(props);

    this.state = {
        name: '',
        email: '',
        password: '',
        confirm_password: ''
    }
}

updateInput = (event) =>{
    const name = event.target.name;
    const value = event.target.value;

    this.setState({[name]: value});
}

handleSubmit = (event)=>{
    event.preventDefault();
    fetch('http://incomeexpense.stacklearning.com/api/users', {
        method: 'POST',
        body: JSON.stringify({
            name: this.state.name,
            email: this.state.email,
            password: this.state.password,
            confirm_password: this.state.confirm_password
        }),
        headers: {
            "Content-Type": "application/json",
            "Origin": "localhost:3000",
        }
    }).then(function (response) {
        console.log(response);
    },function (error) {
        console.log(error);
    });
}

render(){
    return(
        <div className="limiter">
            <div className="container-login100">
                <div className="wrap-login100 p-l-85 p-r-85 p-t-55 p-b-55">
                    <form className="login100-form validate-form flex-sb flex-w" onSubmit={this.handleSubmit}>
                        <span className="login100-form-title p-b-32">
                            Sign Up
                        </span>
                        <span className="txt1 p-b-11">
                            Name
                        </span>
                        <div className="wrap-input100 validate-input m-b-36" >
                            <input className="input100" type="text" name="name" value={this.state.name} onChange={this.updateInput}/>
                            <span className="focus-input100"></span>
                        </div>
                        <span className="txt1 p-b-11">
                            Email
                        </span>
                        <div className="wrap-input100 validate-input m-b-36">
                            <input className="input100" type="text" name="email" value={this.state.email} onChange={this.updateInput}/>
                            <span className="focus-input100"></span>
                        </div>
                        <span className="txt1 p-b-11">
                            Password
                        </span>
                        <div className="wrap-input100 validate-input m-b-36">
                            <input className="input100" type="password" name="password" value={this.state.password} onChange={this.updateInput}/>
                            <span className="focus-input100"></span>
                        </div>
                        <span className="txt1 p-b-11">
                            Confirm Password
                        </span>
                        <div className="wrap-input100 validate-input m-b-18">
                            <input className="input100" type="password" name="confirm_password" value={this.state.confirm_password} onChange={this.updateInput}/>
                            <span className="focus-input100"></span>
                        </div>
                        <div className="container-login100-form-btn">
                            <button className="login100-form-btn">
                                Register
                            </button>
                        </div>
                        <div className="flex-sb-m w-full p-b-48 m-t-60 text-center">
                            <label>
                                Already have an account ?
                                <a className="txt3 m-l-5" href="/login">
                                    Sign In Now
                                </a>
                            </label>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    );
}
}

I've following routes,

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

Route::post('users',array( 'middleware'=>'cors','uses'=>'Auth\RegisterController@registerUser'));
Route::get('users',array( 'middleware'=>'cors','uses'=>'Auth\RegisterController@getUsers'));

Here is CORS middleware,

<?php

namespace App\Http\Middleware;

use Closure;

class CORS
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        header('Access-Control-Allow-Origin: http://localhost:3000/');
        header('Access-Control-Allow-Credentials: true');

        // ALLOW OPTIONS METHOD
        $headers = [
            'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
            'Access-Control-Allow-Headers'=> 'Content-Type, X-Auth-Token, Origin'
        ];

        if($request->getMethod() == "OPTIONS") {
            // The client-side application can set only headers allowed in Access-Control-Allow-Headers
            return Response::make('OK', 200, $headers);
        }

        $response = $next($request);
        foreach($headers as $key => $value)
            $response->header($key, $value);

        return $next($request);
    }
}

Finally here is user creating function

protected function create(array $data)
{
    return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => bcrypt($data['password']),
    ]);
}

protected function registerUser(Request $request)
{
    $data = $request->all();
    return response()->json($this->create($data));
}

When I send the post request from react app following error is shown at console

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://incomeexpense.stacklearning.com/api/users. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

TypeError: "NetworkError when attempting to fetch resource." Register.js:39 Cross-Origin Request Blocked:

The Same Origin Policy disallows reading the remote resource at http://incomeexpense.stacklearning.com/api/users. (Reason: CORS request did not succeed).

I know this error is due to different domain and browser prevent resource access to different domain.

I just want to know what I need need to do at front and at back end to make things right

PS: back end code works perfectly while sending request from postman.

Upvotes: 4

Views: 33765

Answers (1)

Johnathan Maravilla
Johnathan Maravilla

Reputation: 139

URI Schema Mismatch

The Origin request header set within the headers interface of your fetch request contains the host: localhost:3000. The Access-Control-Allow-Origin CORS header that is configured within the CORS middleware contains the host: http://localhost:3000/. The URI scheme/host/port tuple defined must be an exact match in both the fetch request and CORS middlewares.

Change both of your URLs to http://localhost:3000

See: Fetch Spec, CORS Spec and CORS for Developers

Chrome Bug

Just to note, Chrome does not support CORS Requests for localhost. You can find the documented Chrome bug here. There are some workarounds listed within the bug, if need.

Upvotes: 4

Related Questions