8

I'm trying to make 'POST' request in react but i'm getting a few problems regarding CORS. I was just following what console says and fix them in server side [which is PHP] and client side everything works fine when the status is 200 but when status 400 it shows

login:1 Failed to load http://192.168.0.102/API/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 400. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I've tried to add mode: 'no-cors' but that's doesn't work it shows

Uncaught (in promise) SyntaxError: Unexpected end of input

Server Side 'PHP Slimframework' headers:

$app->add(function ($req, $res, $next) {
    $response = $next($req, $res);
    return $response
        ->withHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
        ->withHeader('Origin', 'http://localhost:3000')
        ->withHeader('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, X-Auth-Token')
        ->withHeader('Access-Control-Allow-Credentials', 'true')
        ->withHeader('Access-Control-Request-Headers', 'Origin, X-Custom-Header, X-Requested-With, Authorization, Content-Type, Accept')
        ->withHeader('Access-Control-Expose-Headers', 'Content-Length, X-Kuma-Revision')
        ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});

Client Side

src/actions/userActions.js

export function loginUsers(userData) {
    return new Promise((resolve, reject) =>{
            fetch(URL,{
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json',
                },
                credentials: 'include',
                //mode: 'no-cors', // if it's on it will show Uncaught (in promise) SyntaxError: Unexpected end of input
                body: JSON.stringify(userData),
            })
                .then((response) => response.json())
                .then((responseJson) =>{
                    resolve(responseJson);
                })
                .catch((error) =>{
                    reject(error)
                })
        })
}

src/components/layout.js

import React, {Component} from 'react';
import { loginUsers } from '../actions/usersAction';

class Layout extends Component {
    constructor(props){
        super(props);
        this.state = {
            username: '',
            password: '',
        };
        this.handleLogin = this.handleLogin.bind(this);
        this.onChange = this.onChange.bind(this);
    }

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


handleLogin(){
        if (this.state.username && this.state.password){
            loginUsers(this.state).then((result) =>{
                let responseJSON = result;
                console.log(responseJSON);
            });
        }
    }

    render() {
        return (
            <div className="App">
                <input type="text" onChange={this.onChange} name="username" />
                <input type="password" onChange={this.onChange} name="password" />
                <button onClick={this.handleLogin}>Sign in</button>
            </div>
        );
    }
}




export default Layout;

here screenshot getting this error only with bad request like 400 enter image description here

Please let me know if I miss out any information.

If this has already been asked, I would greatly appreciate if you are able to point me in the right direction.

Thank you so much!

Liam
  • 6,517
  • 7
  • 25
  • 47
  • your destination has no port?any redirections? – Black.Jack Jan 29 '18 at 11:07
  • 2
    Start by finding out what makes your API respond with a 400 in the first place ... – CBroe Jan 29 '18 at 11:11
  • @Black.Jack no there's no redirections as you see in my layout component I just console the result of both response errors and success. if I make a success request it will works fine and will shows the response in console but when the status is 400 i'm getting that error – Liam Jan 29 '18 at 11:11
  • @CBroe I meant to do a 400 bad request because I want to display the response message of the bad request – Liam Jan 29 '18 at 11:14
  • CORS headers are cut from response if http code is > 399 – Máxima Alekz Aug 29 '23 at 19:30

3 Answers3

10

The problem is with the request you are making!

The server will not set the 'Access-Control-Allow-Origin' header when you make a bad request, it just rejects it and in turn causing the CORS error.

Fix the bad request cause, missing parameter usually and you are good to go!!!

Arjun
  • 3,248
  • 18
  • 35
  • 1
    Okay, how can I apply same headers for bad requests. Also the bad request is for wrong login details so it should be 400. – Liam Jan 29 '18 at 11:21
  • 2
    If the exceptions are not handled in your request lifecycle, you wont be able to show CORS headers. Hence, as long as you can handle them, you should be able to punch in your CORS middleware – Friedrich Roell Jan 29 '18 at 11:35
  • @FriedrichRoell thank you for your reply, I noticed that the problem is only when I throw an exception. It's not related to http_error_code. BTW i'm using slim framework. is there's anyway to send headers with Exception? – Liam Jan 29 '18 at 13:14
3

The problem is with your "php exceptions" on the server-side, When you are throwing an error the headers are not set.

You have to set a few header when you throw the exceptions:

$c = new \Slim\Container();
$c['errorHandler'] = function ($c) {
    return function ($request, $response, $exception) use ($c) {
        return $c['response']->withStatus(500)
    ->withHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
    ->withHeader('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, X-Auth-Token')
    ->withHeader('Access-Control-Allow-Credentials', 'true')
    ->withHeader('Access-Control-Expose-Headers', 'Content-Length, X-Kuma-Revision')
    ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS')
    ->write(exception->getMessage());
                             
    };
};
Adam
  • 6,447
  • 1
  • 12
  • 23
0

You need to add to your object headers a key Access-Control-Allow-Origin with the value http://localhost:3000 (your front end URL), or remove

-> withHeader('Access-Control-Allow-Origin', 'http://localhost:3000')

in your backend (but this is a security issue)

Tolotra Raharison
  • 3,034
  • 1
  • 10
  • 15
  • I already added it in the backend and still getting same error while I'm doing 400 bad request. – Liam Jan 29 '18 at 13:12