2

The error I am getting seems to be a CORS issue.

I am trying to make a POST request to my RESTful API through HttpClient as follows:

import {Component, OnInit} from '@angular/core';
import {Observable} from "rxjs/Observable";
import {HttpClient, HttpParams, HttpHeaders} from "@angular/common/http";

import { Test }             from './test';
import { TestResponse }     from './test.response';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';

import * as _ from 'lodash';

@Component({
    selector: 'my-tests',
    templateUrl: './tests.component.html',
    styleUrls: ['./tests.component.css']
})

export class TestsComponent implements OnInit {

    // URL to web api
    private url = 'http://172.19.0.5/api/tests';

    tests$: Observable<Test[]>;

    private httpheadersPost = new HttpHeaders().set("Content-Type", "application/json");

    constructor(private http:HttpClient) {
    }

    ngOnInit() {
        // console.log(this.httpheadersPost);
        this.tests$ = this.http
            .get<TestResponse[]>(this.url)
            .do(console.log)
            .map(data => _.values(data["hydra:member"]));
    }

    // Implementation of the add() function
    add(name: string): void {
        // console.log('header:'+this.httpheadersPost);
        // console.log(this.httpheadersPost);
      name = name.trim();
      if (!name) { return; }
      this.http.post(this.url, {"name":name}, {"headers":this.httpheadersPost} )
        .subscribe(
            val => {
                console.log("POST call successful value returned in body", val);
            },
            response => {
                console.log("POST call in error", response);
            },
            () => {
                console.log("The POST observable is now completed.");
            }
        );
    }


}

This is the config of my nginx server of my RESTful API:

server {

    server_name symfony.dev;
    root /var/www/symfony/public;

    location / {
        add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization,Lang';
        #add_header 'Access-Control-Allow-Headers' '*';
        add_header 'Access-Control-Allow-Methods' 'POST,GET,PUT,DELETE,OPTIONS';
        add_header 'Access-Control-Allow-Origin' '*';
        try_files $uri /index.php$is_args$args;

    }

    location ~* \.(jpg|jpeg|gif|css|png|js|ico|html|eof|woff|ttf)$ {
        add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization,Lang';
        #add_header 'Access-Control-Allow-Headers' '*';
        add_header 'Access-Control-Allow-Methods' 'POST,GET,PUT,DELETE,OPTIONS';
        add_header 'Access-Control-Allow-Origin' '*';

        if (-f $request_filename) {
            expires 30d;
            access_log off;
        }
    }

    location ~ \.php$ {
        add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization,Lang';
        #add_header 'Access-Control-Allow-Headers' '*';
        add_header 'Access-Control-Allow-Methods' 'POST,GET,PUT,DELETE,OPTIONS';
        add_header 'Access-Control-Allow-Origin' '*';
        fastcgi_pass php:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    error_log /var/log/nginx/symfony_error.log;
    access_log /var/log/nginx/symfony_access.log;
}

The RESTful API and the angular application are created through docker-compose so containers are not having the same IP addresses.

The error I getting is:

**OPTIONS http://172.19.0.5/api/tests **

XMLHttpRequest cannot load http://172.19.0.5/api/tests. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4203' is therefore not allowed access. The response had HTTP status code 405.

The error in IMO is strange. In fact, I already provided the headers + nginx server of the RESTful API is having Access-Control-Allow-Origin which is already set.

Thanks for your help.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Amine Jallouli
  • 3,919
  • 8
  • 36
  • 73
  • web service is developed using `java` or `asp.net` or? – Aravind Aug 26 '17 at 18:00
  • 1
    The server the response is being sent to must implement support the OPTIONS method, but the 405 status code in the response indicates the server currently says it doesn’t allow OPTIONS requests. For more details see the answer at https://stackoverflow.com/questions/43871637/no-access-control-allow-origin-header-is-present-on-the-requested-resource-whe/43881141#43881141 – sideshowbarker Aug 26 '17 at 18:04
  • Are you sure your server does not respond with error? – Sharikov Vladislav Aug 26 '17 at 18:08
  • The RESTful API is created by a Symfony3.4 with the [api-platform](https://github.com/api-platform/api-platform) – Amine Jallouli Aug 27 '17 at 01:48

1 Answers1

1

Well the problem is that CORS doesn't work this way. When browser wants to test CORS on an API it will send a OPTIONS request to it. This request should respond with the CORS header and a http code 204.

So you would need to update you nginx config something like below. It is not exact, but should get you going

server {

    server_name symfony.dev;
    root /var/www/symfony/public;

    location / {

        # Match host using a hostname if you like
        #if ($http_origin ~* (https?://.*\.tarunlalwani\.com(:[0-9]+)?$)) {
        #   set $cors "1";
        #}
        set $cors "1";

        # OPTIONS indicates a CORS pre-flight request
        if ($request_method = 'OPTIONS') {
           set $cors "${cors}o";
        }

        # OPTIONS (pre-flight) request from allowed
        # CORS domain. return response directly
        if ($cors = "1o") {
           add_header 'Access-Control-Allow-Origin' '$http_origin' always;
           add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
           add_header 'Access-Control-Allow-Credentials' 'true' always;
           add_header 'Access-Control-Allow-Headers' 'Origin,Content-Type,Accept' always;
           add_header Content-Length 0;
           add_header Content-Type text/plain;
           return 204;
        }

        add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization,Lang';
        #add_header 'Access-Control-Allow-Headers' '*';
        add_header 'Access-Control-Allow-Methods' 'POST,GET,PUT,DELETE,OPTIONS';
        add_header 'Access-Control-Allow-Origin' '*';
        try_files $uri /index.php$is_args$args;

    }

    location ~* \.(jpg|jpeg|gif|css|png|js|ico|html|eof|woff|ttf)$ {
        add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization,Lang';
        #add_header 'Access-Control-Allow-Headers' '*';
        add_header 'Access-Control-Allow-Methods' 'POST,GET,PUT,DELETE,OPTIONS';
        add_header 'Access-Control-Allow-Origin' '*';

        if (-f $request_filename) {
            expires 30d;
            access_log off;
        }
    }

    location ~ \.php$ {
        add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization,Lang';
        #add_header 'Access-Control-Allow-Headers' '*';
        add_header 'Access-Control-Allow-Methods' 'POST,GET,PUT,DELETE,OPTIONS';
        add_header 'Access-Control-Allow-Origin' '*';
        fastcgi_pass php:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    error_log /var/log/nginx/symfony_error.log;
    access_log /var/log/nginx/symfony_access.log;
}

I recently used a similar config to enable CORS for grafana (No response from Grafana via AJAX). So this should work for you also

Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265