angularjsonlinesndjsonoboe.js

How to solve CORS error consuming an API using oboe in Angular2 app?


I have API that returns data like this:

{"t":"point","id":817315,"tableid":141,"classid":142,"state":0,"loc":[6850735.34375,24501674.0039063]}
{"t":"line","id":817314,"tableid":204,"classid":2102,"loc":[[6850335.8828125,24501476.50390625],[6850341.48828125,24501476.8828125],[6850362.171875,24501492.21484375],[6850387.4140625,24501508.86328125],[6850442.66796875,24501545.69921875],[6850502.34375,24501584.0078125],[6850558.3359375,24501619.37109375],[6850611.375,24501654.73046875],[6850671.05078125,24501693.04296875],[6850708.62109375,24501687.1484375],[6850735.34375,24501674.00390625]]}

I'm trying to read this with oboe but without success. How to do this? With following code I get error in the end of this question:

    oboe('http://localhost:19100/pn/api/v1/fetch?cgid=22&north=6853000.0&east=24505000&south=6850000.0&west=24500000.0')
    .node('*', (row) => {
        console.log(row);

        return oboe.drop;
    })
    .done(() => {

        return oboe.drop;
    })
    .fail((err) => {
        // error
        console.log('oboe fail ', err);
        return oboe.drop;
    });

Access to XMLHttpRequest at 'http://localhost:19100/pn/api/v1/fetch?cgid=22&north=6853000.0&east=24505000&south=6850000.0&west=24500000.0' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. [http://localhost:4200/main]

When I get fetch with chrome headers look like this:

Request URL: http://localhost:19100/pn/api/v1/fetch?cgid=22&north=6853000.0&east=24505000&south=6850000.0&west=24500000.0
Request Method: GET
Status Code: 200 OK
Remote Address: [::1]:19100
Referrer Policy: no-referrer-when-downgrade
Content-Type: application/json
Date: Mon, 25 Feb 2019 19:55:41 GMT
Server: Microsoft-HTTPAPI/2.0
Transfer-Encoding: chunked
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Host: localhost:19100
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36
cgid: 22
north: 6853000.0
east: 24505000
south: 6850000.0
west: 24500000.0
fetch?cgid=22&north=6853000.0&east=24505000&south=6850000.0&west=24500000.0
/pn/api/v1

Solution

  • As mentioned by @william-lohan, this is a CORS issue. If you have control over the API host then you can enable CORS headers to allow cross-domain requests like the one that you are trying to make. However, the idea of enabling CORS should not be taken lightly as this will expose your API to several common potential XSS vulnerabilities. CORS configurations should be thoroughly tested and reviewed regularly.

    As an alternative, Angular does allow you to specify the proxy configuration that is used for development mode. For example:

    // package.json
    ...
        "scripts": {
            "start": "ng serve --proxy-config proxy.conf.js"
        }
    ...
    
    // proxy.conf.js
    const PROXY_TARGET = 'http://localhost:19100';
    module.exports = [{
        context: ['**/api/**/*'], // May be able to get away with '**/api/**' or less here; haven't tested
        target: PROXY_TARGET,
        changeOrigin: true,
        secure: false,
        logLevel: 'debug',
        autoRewrite: true
    }];
    

    The target URI for your requests should then be changed to use the current page domain ("/pn/api/v1/...") instead of the original domain ("http://localhost:19100/pn/api/v1/...").

    This will only apply when you are using development mode. If your API and UI are accessed through separate domains in any other environment then you will need to implement a solution for those environments as well, such as a reverse proxy or the aforementioned CORS.