AT-2017
AT-2017

Reputation: 3149

Insecure HTTP Request With Angular

I am trying to learn Angular with ASP.NET Core and had a basic project start-up. Now I run into a very basic issue that I guess, require few modifications. I created a web api project and hosted it in IIS - Internal server. So I used the api as follows in Angular:

import { Component, Inject } from '@angular/core';
import { Http } from '@angular/http';

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

export class AppComponent {
    title = 'Our First Angular App';
    public values: object[];

    constructor(private http: Http) {
      this.http.get('http://192.168.10.100/api/values').subscribe(result => { //Calling the web api here as jSon
        this.values = result.json() as object[];
        }, error => console.error(error));
    }
}

The above doesn't get data in the front-end with Angular. Instead it threw an exception when debugged with browser's inspect element:

http://192.168.10.100/api/values - http request was insecure

I can understand, it may require https or some kind of security to be integrated. But for the time being, is there any way that I can make the above code working with http request? I am including the configuration files below if those could be helpful:

angular.json:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "OurFirstAngularApp": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "wwwroot",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css",
              "C:\\Users\\AT\\Documents\\Visual Studio 2017\\Projects\\OurFirstAngularApp\\OurFirstAngularApp\\node_modules\\bootstrap\\dist\\css\\bootstrap.min.css"
            ],
            "scripts": [
              "C:\\Users\\AT\\Documents\\Visual Studio 2017\\Projects\\OurFirstAngularApp\\OurFirstAngularApp\\node_modules\\bootstrap\\dist\\js\\bootstrap.min.js"
            ]
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "OurFirstAngularApp:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "OurFirstAngularApp:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "OurFirstAngularApp:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.spec.json",
            "karmaConfig": "src/karma.conf.js",
            "styles": [
              "src/styles.css"
            ],
            "scripts": [],
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ]
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "src/tsconfig.app.json",
              "src/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    },
    "OurFirstAngularApp-e2e": {
      "root": "e2e/",
      "projectType": "application",
      "prefix": "",
      "architect": {
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "OurFirstAngularApp:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "OurFirstAngularApp:serve:production"
            }
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": "e2e/tsconfig.e2e.json",
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "OurFirstAngularApp"
}

tsconfig.json:

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "module": "es2015",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "importHelpers": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ]
  }
}

N.B: The above api is working fine when requested I mean getting jSon data perfectly.

Update 1: Startup.cs

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, 
    // visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();

        app.UseDefaultFiles();
        app.UseStaticFiles();
        //app.Run(async (context) =>
        //{
        //  await context.Response.WriteAsync("Hello World!");
        //});
    }
}

Update 2: jSon data - Raw jSon Data

Now I got it. Basically it was making a http call and for security reason, it required https. So I tried with an https service that contains raw jSon data. But when I've done the following:

public default: object[];

constructor(private http: Http) {
    this.http.get('https://jsonplaceholder.typicode.com/todos/1/').subscribe(result => {
        this.default = result.json() as object[];
    }, error => console.error(error));
}

Finally in the front-end with Angular:

<tr *ngFor="let value of default">
   <td>{{ value.userId }}</td>
   <td>{{ value.title }}</td>
</tr>

The above threw an exception when used the browser's inspect element, something like this - Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

Upvotes: 0

Views: 3066

Answers (2)

Stephen R. Smith
Stephen R. Smith

Reputation: 3400

Try using the Elvis operator on your display loop:

<tr *ngFor="let value of default">
   <td>{{ value?.userId }}</td>
   <td>{{ value?.title }}</td>
</tr>

The ?. after the item (in this case, value) ensures that Angular won't try to render the data until the data shows up, so value?.userId will work where value.userId will fail as value is undefined when the view is rendered, and Angular has no knowledge of the .userID attribute until the fetch completes, by which it's already thrown the error.

Also, when using http and result.json(), you will get a single array of your data objects, so you shouldn't need as object[]; I'd also be inclined to type values as any[], and see if that doesn't work.

public values: any[];

constructor(private http: Http) {
  this.http.get('http://192.168.10.100/api/values').subscribe(result => { //Calling the web api here as json
    this.values = result.json();
    }, error => console.error(error));
}

Upvotes: 1

Gopal Meena
Gopal Meena

Reputation: 105

You can enable cross-origin in your serverside code, it will be useful for you try it

Upvotes: 0

Related Questions