-1

I try to send a post request to a bank's API and i get this error:

Access to XMLHttpRequest at 'https://api_url' from origin 'https://client_url' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Is there any workaround for this problem, as long as i cannot, by myself, enable cors in the API?

This app is in MEAN stack (Mongo-Express-Angular-Node)

v_char
  • 145
  • 1
  • 5
  • 13

2 Answers2

-1

When no control on Backend API one should manage to to proxify it so the Client URL and the Backend one share the same domain.

In your case and depending on your server environment your can either :

  • Make Bank calls logic into Express (http client, request node module, etc.) and expose it as Endpoints
  • Do it the ugly way :), by using a NodeJS full http proxy (https://github.com/chimurai/http-proxy-middleware)
  • Use lightweight HTTP Proxy (over Nginx, Httpd, etc.)

All of the three alternatives presume that your server environment have access to the Backend API

Edit

In pseudo-code it is something like this :

ExpressJS

app.get('/internal/bank/balance', function (req, res, next) {
  const balance = request('https://distantbank/api/balance')
  res.send(balance);
});

Angular

const internalBankAPIUrl= '/internal/bank/';

getBalance() {
  return this.http.get(`${internalBankAPIUrl}/balance`);
}
Neji Sghair
  • 174
  • 5
-1

Below is my logic:

Backend - NodeJS

app.js

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');

const app = express();

app.use(cors());
app.use(bodyParser.urlencoded({ extended: true, limit: '50mb'}));
app.use(bodyParser.json({limit: '50mb'}));

app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization, *');
    if (req.method === 'OPTIONS'){
        res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, PATCH, DELETE, OPTIONS');
        res.setHeader('Access-Control-Allow-Credentials', true);
        return res.status(200).json({});
    }
    next();
});

const bankApi = require('./routes/bankApi');
app.use('/bank-endpoint', bankApi);

// Start the server

const port =  process.env.PORT || app.get('port') || 2020;
app.listen(port, () => console.log(`Server is listening on port ${port}`)); 

bankApi.js

const express = require('express');
const router = require('express-promise-router')();
const request = require('request');
const BankAPIURL = 'https://bankAPIURl.com'

const data = ''

router.get('/bank-endpoint', async (req, res) => {

await request(BankAPIURL, (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body)
    data = body 
    res.json({data});
  }
});

});  

Frontend - Angular8

Data - Component + HTML

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

@Component({
  selector: 'app-service',
  template: '{{bankData}}'
})
export class ServiceComponent implements OnInit {
  public apiBaseUrl: string = 'https://your-internal-domain-name';
  private bankData: any;
  private BankToken = 'this-is-my-secret-bank-auth-token';
  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  };

  jsonHeader = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json; charset=utf-8',
      Authorization: 'Bearer ' + this.BankToken
    })
  };

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.http.get<any>(this.apiBaseUrl + '/bank-endpoint').subscribe(data => {
      this.bankData = data;
      console.log(this.bankData);
    });
  }
}

So you can see in my answer, I built a custom server + API in order to perform external API requests from my internal server. in app.js, I include the cors package to handle CORS request. For safety purposes, I also set couple headers. Then I load my routes where my internal API queries the external bank's API. Then I define my internal endpoint /bank-endpoint that when called with in turn call the external endpoint with CORS options already defined. Finally I start my server.

Next, in bankApi.js, That is where I define my internal API endpoint that calls the external api endpoint from the bank. After getting the data back, I return it as JSON to be consumed on the frontend with Angular.

In the frontend, I simply create a component that will call the API endpoint and display the result back to the user in HTML template {{bankData}}. In a more organized project architecture, you will define your HTTP calls to your internal endpoint inside an Angular Service and then simply include the service into your component and then call the service that will execute the HTTP request.

I do not guarantee that this specific example will work. All I wanted to do is give you a radmap/logic/flow. Please reach out if you have more questions you need answered.

AllJs
  • 1,760
  • 4
  • 27
  • 48
  • I don't understand why an answer would get voted down in this situation and comment gets voted up? This is just an alternative answer, or a personal perspective that we offer to the person who asked the question, without refuting other answers. – AllJs Feb 07 '20 at 11:30