0

I have api on localhost (xampp) / codeigniter and im trying to access it via angular 4 and the browser keeps showing this error in the console. api works fine in postman.

[Firefox]:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://lvh.me/ci-abc/api/get_alltasks. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

[Chrome]:

Failed to load http://lvh.me/ci-abc/api/get_alltasks: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

I have tried changing API url to localhost and 127.0.0.1 as well but didn't work. I am a beginner developer so pardon me if im missing something.

Service function in Angular 4

gettasks()
  {
    return this.http.get('http://lvh.me/ci-abc/api/get_alltasks')
    .map(res=>res.json());
  }

API function in codeigniter

function get_alltasks_get()
    {
        {
            $result = $this->todo_model->get_alltasks();

            if ($result) {
                $this->response($result, 200);
            } else {
                $this->response("No record found", 404);
            }
        }
    }
Yousuf Khan
  • 103
  • 13

3 Answers3

1

It's not Angular problem, the problem caused because you're not in the same domain as your server is, for example, if you try to send a request to example.com from johndoe.com you will get the error and it's browser that blocks the request!

The browser first makes a header request and if the request is allowed, the next request with the real method type will be issued.

For CodeIgniter, try adding OPTIONS to the allowed methods.

header("Access-Control-Allow-Methods: GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Content-Length, Accept-Encoding");

Take a look at this answer

Mohammad Kermani
  • 5,188
  • 7
  • 37
  • 61
0

CORS on PHP

Browsers send specific HTTP headers for cross-site requests initiated from within XMLHttpRequest or the Fetch API. It also expects to see specific HTTP headers sent back with cross-site responses.

An overview of these headers, including sample JavaScript code that initiates requests and processes responses from the server, as well as a discussion of each header, can be found in the HTTP Access Control (CORS) article and should be read as a companion article to this one.

and should be read as a companion article to this one. This article covers processing Access Control Requests and formulating Access Control Responses in PHP.

If you don't have access to configure Apache, you can still send the header from a PHP script. It's a case of adding the following to your PHP scripts:

<?php
header("Access-Control-Allow-Origin: *");
M0ns1f
  • 2,705
  • 3
  • 15
  • 25
  • `header("Access-Control-Allow-Origin: *");` I put this in the constructor of my API controller and it worked! thanks – Yousuf Khan Dec 16 '17 at 12:28
  • and when you add headding to your php script put it in the top @YousufKhan Mark it as an answer and give it an upvote then – M0ns1f Dec 16 '17 at 12:30
0

I've just spend sometime on this and i found out a couple things:

  • start with studying your request you do from angular to the backend. In the request headers there is a key called 'origin: ...' this is the origin that is asked for.
  • Codeigniter uses a concept called 'filters' which can be compared to laravel's middleware or angulars interceptors. They do something with the request. In this case add a header.
  • You need to register those filters in Config/Filters.php for the application to use them.

So here is what i did:

  • Create a new CorsFilter.php under App\Filters

use CodeIgniter\config\Services;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;


class CorsFilter implements FilterInterface
{
    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {


    }

    public function before(RequestInterface $request, $arguments = null)
    {
        if (array_key_exists('HTTP_ORIGIN', $_SERVER)) {
            $origin = $_SERVER['HTTP_ORIGIN'];
        } else if (array_key_exists('HTTP_REFERER', $_SERVER)) {
            $origin = $_SERVER['HTTP_REFERER'];
        } else {
            $origin = $_SERVER['REMOTE_ADDR'];
        }
        $allowed_domains = array(
            'http://localhost:4200',
            // your origin from request headers goes here
        );


        if (in_array($origin, $allowed_domains)) {
            header('Access-Control-Allow-Origin: ' . $origin);
        }
        //these headers are always needed for an api call
        header("Access-Control-Allow-Headers: Origin, X-API-KEY, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Authorization, observe, enctype, Content-Length, X-Csrf-Token");
        header("Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS");
        header("Access-Control-Allow-Credentials: true");
        header("Access-Control-Max-Age: 3600");
        header('content-type: application/json; charset=utf-8');
        $method = $_SERVER['REQUEST_METHOD'];
        //this handles the required 'ok' for the preflight check
        if ($method == "OPTIONS") {
            header("HTTP/1.1 200 OK CORS");
            die();
        }

    }


}

register the filter in App\config\Filters.php


namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Filters\CSRF;
use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\Honeypot;
use CodeIgniter\Filters\InvalidChars;
use CodeIgniter\Filters\SecureHeaders;
use App\Filters\CorsFilter;

class Filters extends BaseConfig
{
    /**
     * Configures aliases for Filter classes to
     * make reading things nicer and simpler.
     *
     * @var array
     */
    public $aliases = [
        'csrf'          => CSRF::class,
        'toolbar'       => DebugToolbar::class,
        'honeypot'      => Honeypot::class,
        'invalidchars'  => InvalidChars::class,
        'secureheaders' => SecureHeaders::class,
        'cors'          => CorsFilter::class
    ];

    /**
     * List of filter aliases that are always
     * applied before and after every request.
     *
     * @var array
     */
    public $globals = [
        'before' => [
            'cors'
            // 'honeypot',
            // 'csrf',
            // 'invalidchars',
        ],
        'after' => [
            'toolbar',
            // 'honeypot',
            // 'secureheaders',
        ],
    ];

    /**
     * List of filter aliases that works on a
     * particular HTTP method (GET, POST, etc.).
     *
     * Example:
     * 'post' => ['foo', 'bar']
     *
     * If you use this, you should disable auto-routing because auto-routing
     * permits any HTTP method to access a controller. Accessing the controller
     * with a method you don’t expect could bypass the filter.
     *
     * @var array
     */
    public $methods = [];

    /**
     * List of filter aliases that should run on any
     * before or after URI patterns.
     *
     * Example:
     * 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
     *
     * @var array
     */
    public $filters = [];
}

Now every request from the frontend is allowed into the backend. Hope this makes sense and helps anyone struggling with this.