Hafiz Siddiq
Hafiz Siddiq

Reputation: 699

Proxy configuration is not working in angular 6

I have metronic_v5.5.2 Angular Version and I am trying to integrate Its angular version with my backend API.

As I am pretty new to all this, Now the issue is with my proxy configuration that is not working according to my expectations.

The following is the code of proxyconfig.json file

{
    "/api": {
        "target": "https://localhost:5001",
        "secure": false,
        "changeOrigin": true,
        "logLevel": "debug"
    }
}

Image is showing that the request is routing to the URL "https://localhost:5001/api/auth/login" POST /api/auth/login -> https://localhost:5001

But In browsers' console this request is actually routing to the URL http://localhost:4200/api/auth/login which return 401 error. I am unable to route on clicking of button to the url: https://localhost:5001/api/auth/login

Following is the HTML Code

<!--begin::Form-->
<form class="m-login__form m-form" name="form" (ngSubmit)="f.form.valid && submit()" #f="ngForm" novalidate>
    <div class="form-group">
        <mat-form-field>
            <mat-label>Email</mat-label>
            <input matInput type="email" name="email" placeholder="Email address" autocomplete="off" [(ngModel)]="model.email" #email="ngModel" email="true" required>
        </mat-form-field>
    </div>
    <div class="form-group">
        <mat-form-field>
            <mat-label>Password</mat-label>
            <input matInput minlength="4" type="password" name="password" placeholder="Password" autocomplete="off" [(ngModel)]="model.password" #password="ngModel" required>
        </mat-form-field>
    </div>
</form>
<!--end::Form-->

<!--begin::Action-->
<div class="m-login__action m-login__action--fit">
    <a href="javascript:;" (click)="forgotPasswordPage($event)" class="m-link">
        <span translate="AUTH.GENERAL.FORGOT_BUTTON">Forgot Password?</span>
    </a>
    <m-spinner-button [options]="spinner" (click)="submit()">{{'AUTH.LOGIN.BUTTON' | translate}}</m-spinner-button>
</div>

Following is the login.component.ts code

submit() {
        this.spinner.active = true;
        if (this.validate(this.f)) {
            this.authServiceDb.logindb(this.model).subscribe(response => {
                    this.router.navigate(['/']);
                    this.alertify.success('Logged In Successfully');
                    this.spinner.active = false;
                    this.cdr.detectChanges();
            }, error => {
                this.alertify.error(error);
            });
        }
    }

function the code for authdb exported class is given blow, Edit

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '../../../node_modules/@angular/http';
import { map, catchError } from 'rxjs/operators';
import { throwError } from '../../../node_modules/rxjs';
import { tokenNotExpired, JwtHelper } from 'angular2-jwt';

@Injectable({
    providedIn: 'root'
})
export class AuthdbService {
    baseUrl = 'api/auth/';
    userToken: any;
    decodedTokenn: any;
    jwtHelper: JwtHelper = new JwtHelper();
    constructor(private http: Http) { }
public logindb(model: any) {
    return this.http.post(this.baseUrl + 'login', model, this.requestOptions()).pipe(map((response: Response) => {
      const user = response.json();
      if (user) {
        localStorage.setItem('token', user.tokenString);
        this.decodedTokenn = this.jwtHelper.decodeToken(user.tokenString);
        this.userToken = user.tokenString;
      }
    })).pipe(catchError(this.handleError));
  }
  register(model: any) {
    return this.http.post(this.baseUrl + 'register', model, this.requestOptions()).pipe(catchError(this.handleError));
  }
  loggedIn() {
    return tokenNotExpired('token');
  }
  private requestOptions() {
    const headers = new Headers({
      'Content-type': 'application/json'});
    return new RequestOptions({headers: headers});
  }
  private handleError(error: any) {
    const applicationError = error.headers.get('Application-Error');
    if (applicationError) {
      return throwError(applicationError);
    }
    const serverError = error.json();
    let modelStateErrors = '';
    if (serverError) {
      for (const key in serverError) {
        if (serverError[key]) {
          modelStateErrors += serverError[key] + '\n';
        }
      }
    }
    return throwError(
      modelStateErrors || 'Server Eroor'
    );
  }
}

And In My package.json I have the following code

{
    "name": "default",
    "version": "0.0.0",
    "license": "MIT",
    "scripts": {
        "ng": "ng",
        "start": "ng serve --proxy-config proxyconfig.json",
        "build": "ng build --prod",
        "test": "ng test",
        "lint": "ng lint",
        "e2e": "ng e2e"
    },
    "private": true,
    "dependencies": {
        "@angular/animations": "^6.1.0",
        "@angular/cdk": "^6.4.0",
        "@angular/common": "^6.1.0",
        "@angular/compiler": "^6.1.0",
        "@angular/forms": "^6.1.0",
        "@angular/http": "^6.1.0",
        "@angular/platform-browser": "^6.1.0",
        "@angular/platform-browser-dynamic": "^6.1.0",
        "@angular/platform-server": "^6.1.0",
        "@angular/router": "^6.1.0",
        "@kolkov/angular-editor": "^0.10.3",
        "@ng-bootstrap/ng-bootstrap": "^2.2.0",
        "@ngx-loading-bar/core": "^2.1.1",
        "@ngx-translate/core": "^10.0.2",
        "@types/lodash": "^4.14.112",
        "alertifyjs": "^1.11.1",
        "angular-in-memory-web-api": "^0.6.0",
        "angular2-jwt": "^0.2.3",
        "chart.js": "^2.7.2",
        "classlist.js": "^1.1.20150312",
        "core-js": "^2.5.7",
        "hammerjs": "^2.0.8",
        "lodash": "^4.17.10",
        "material-design-icons": "^3.0.1",
        "ng2-charts": "^1.6.0",
        "ngx-auth": "4.0.0",
        "ngx-highlightjs": "^2.0.4",
        "ngx-perfect-scrollbar": "^6.2.0",
        "ngx-permissions": "^5.0.0",
        "object-path": "^0.11.4",
        "rxjs-compat": "^6.2.2",
        "rxjs-tslint": "^0.1.5",
        "web-animations-js": "^2.3.1",
        "zone.js": "^0.8.26"
    },
    "devDependencies": {
        "@angular-devkit/build-angular": "^0.7.0",
        "@angular/cli": "^6.0.8",
        "@angular/compiler-cli": "^6.1.0",
        "@angular/core": "^6.1.0",
        "@angular/language-service": "^6.1.0",
        "@angular/material": "^6.4.0",
        "@angular/material-moment-adapter": "^6.4.0",
        "@types/jasmine": "^2.8.8",
        "@types/jasminewd2": "^2.0.3",
        "@types/node": "^10.5.2",
        "codelyzer": "^4.4.2",
        "jasmine": "^3.1.0",
        "jasmine-core": "^3.1.0",
        "jasmine-spec-reporter": "~4.2.1",
        "karma": "~2.0.4",
        "karma-chrome-launcher": "^2.2.0",
        "karma-coverage-istanbul-reporter": "^2.0.1",
        "karma-jasmine": "^1.1.2",
        "karma-jasmine-html-reporter": "^1.2.0",
        "moment": "^2.22.2",
        "protractor": "^5.3.2",
        "rxjs": "^6.2.2",
        "ts-node": "^6.0.3",
        "tslint": "~5.9.1",
        "typescript": "2.7.2"
    }
}

Upvotes: 14

Views: 48571

Answers (6)

Rachit
Rachit

Reputation: 61

Same issue occur to me as well for my Angular app with base url and i got the solution by adding parameter for base_href.

We need to specify the Angular app to use the base url by changing package.json in 'start' command by adding --base-href=/your-application-url/

    "start": "ng serve --proxy-config proxyconfig.json --deploy-url=/your-application-baseurl/ --base-href=/your-application-baseurl/"

"Package.json" after addition will be

    {
"name": "default",
"version": "0.0.0",
"license": "MIT",
"scripts": {
    "ng": "ng",
    "start": "ng serve --proxy-config proxyconfig.json --deploy-url=/your-application-baseurl/ --base-href=/your-application-baseurl/",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
},

Upvotes: 0

Ravindra Vairagi
Ravindra Vairagi

Reputation: 1083

To configure proxy in Angular follow below steps -

Step 1. In angular root folder where package.json file exist create "proxy.conf.json" and add below code -

{
  "/api/*": {
    "target": "http://xxx.xxx.xxx.xxx:80/api/",  // API URL or any URL for Proxy
    "secure": false,
    "logLevel": "debug",
    "changeOrigin": true
  }
}

Step 2. then update angular.json file, Add property "proxyConfig" property at architect -> serve -> builder -> options -

"projects": {
        ...
        "angularPracticeProj": {
                "projectType": "application",
                "schematics": {},
                ...
                "architect": {
                        ...
                        "serve": {
                                ...
                                "builder": "@angular-devkit/build-angular:dev-server",
                                  "options": {
                                    "browserTarget": "angularPracticeProj:build",
                                    "proxyConfig": "proxy.conf.json"        <==== angular proxy
                                  },
                                ...
                                }
                        ...
                        }
                    }
            }
            
        

If you are working with NodeJS / ExpressJS REST API then update the app/root file from where you are loading express of nodejs-

Step 3(Optional). In nodejs or ExpressJS root file where - app root is defined add below code -

const app = express();
            // angular app set as start
            app.use(express.static(process.cwd() + "/../dist/angularPracticeProj/")); <= angular project's published/dist index file path
            app.get('/', (req, res) => {
            res.sendFile(process.cwd() + "/../dist/angularPracticeProj/index.html")   <= angular project's published/dist index file path
    });

Upvotes: 0

Balazs F.
Balazs F.

Reputation: 410

Add "--ssl" parameter to ng serve:

"start": "ng serve --proxy-config proxyconfig.json --ssl",

because you want to build a secure connection:

"target": "https://localhost:5001",

source: https://www.devdungeon.com/content/how-serve-angular-locally-over-https

Upvotes: 0

Mandakh
Mandakh

Reputation: 1223

It took me a couple of hours to fix incorrect routing of POST /api/auth/login to https://localhost:5001 which is in the image you provided.

Following config fixes the routing of POST /api/auth/login to https://localhost:5001/api/auth/login.

{
    "/api": {
        "target": "https://localhost:5001/api",
        "changeOrigin": true,
        "logLevel": "debug",
        "pathRewrite": { "^/api" : "" }
    }
}

Upvotes: 5

confused human
confused human

Reputation: 421

I had this same issue and adding proxyConfig option to the serve target did the job.

Go to angular.json -> within serve add the key:value pair "proxyConfig": "proxy.conf.json"

like this -

"architect": {
  "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
      "browserTarget": "your-application-name:build",
      "proxyConfig": "proxy.conf.json"
    },

btw, I got this from here

Upvotes: 10

rmcsharry
rmcsharry

Reputation: 5562

You said you are new to this, so let me explain something simple first.

When you call http.post the first parameter is the url that will be contacted. So:

this.http.post(this.baseUrl + 'login', ...

will become

this.http.post('api/auth/login', ...

because you set baseUrl and added 'login':

baseUrl = 'api/auth/';

But your code does not say which protocol to use (http or https) NOR which domain:port to call (eg. http://mydomain:port/api/auth/login).

Therefore Angular will default to 'http' and to the domain and port that IT is using, which is localhost:4200. So your request then becomes:

http://localhost:4200/api/auth/login

That is why you see that in the console. Angular is completely ignoring your proxy file. I think the reason is either the name, or location (it should normally be in your project's root folder) or you have not told Angular to load it.

You need to tell Angular to actually use it when it starts up. So in package.json you need something like this:

"start": "ng serve --proxy-config proxyconfig.json"

This tells Angular-CLI that when you use the npm run start (or just npm start) command to start the app, it should load the proxy data from that json file in the root folder.

I would advise reading this tutorial also.

Also, I think you have /* missing from your proxyconfig:

{
    "/api/*": {
        "target": "http://localhost:5001",
        "secure": false,
        "changeOrigin": true,
        "logLevel": "debug"
    }
}

Upvotes: 4

Related Questions