CrossOrigin error because of no header found in Angular 6

587 views Asked by At

I have a Access-Control-Allow-Origin header error problem in the Angular side. I was creating a contact us page which once filled up by the user, it will call Spring Boot using REST API and CrossOrigin.

This is a recurring problem. I tried googling and used the solutions available in my code. Yet the problem isn't solved. What should I do to solve this problem? Below is my code:

contact-us.component.html

<table class="doc-loader">
</table>   

<header class="header-holder ">



</header>

<base href="/">


<!--
<form #contactForm="ngForm" method="POST" data-email="[email protected]"
action="https://script.google.com/macros/s/AKfycbwy7DhhmkYPHUi-eozr5tUNAAf2nIPfXk58NLTfz1sODZQCx6k/exec">-->

<form #contactForm="ngForm" (ngSubmit) = "createContactRecord(contactForm)" novalidate>
<div class="col-sm-10 col-sm-offset-1 col-md-9 col-md-offset-1 col-lg-10 col-lg-offset-1">
<div id="content" class="site-content">
    <article>
        <div class="content-1170 center-relative">
            <div class="one_half ">
                <p>We choose to go to the moon in this decade and do the other things, not because they are easy.</p>
                <p>&nbsp;</p>
                <p>Because they are hard, because that goal will serve to organize and measure the best of our energies and skills, because that challenge is one that we are willing to accept, one we are unwilling to postpone and one.</p>
                <p>&nbsp;</p>
                <p>Which we intend to win. With a warning label this big, you know they gotta be fun. Bring me the forms I need to fill out to have her taken away. I decline the title of iron cook and accept the lesser title of zinc saucier, which I just made up. Dinosaurs are extinct today because they lacked opposable thumbs and the brainpower to build a space program. Houston, Tranquillity Base here.</p>
                <p>&nbsp;</p>
                <p><!--#f375ad--> 
                    <span style="color: #43464b;">Phone:</span> <strong>88089542</strong>
                    <br>
                    <span style="color: #43464b;">Email Address:</span> <strong>[email protected]</strong>
                    <br>
                    <span style="color: #43464b;">Hours:</span> <strong>6:00 am – 2:00 am</strong>
                    <br>
                </p>
            </div>
            <div class="one_half last">
                <div class="contact-form"> 

                    <p><input id="name" type="text" name="your-name" placeholder="Name" [(ngModel)]="newContactUs.name" #name="ngModel" ></p>
                    <p><input id="contact-email" type="email" name="your-email" placeholder="Email" [(ngModel)]="newContactUs.contactEmail" #contactEmail="ngModel" ></p>
                    <p><input id="contact-email" type="email" name="your-contact-number" placeholder="Contact Number*Optional" [(ngModel)]="newContactUs.contactNumbers" #contactNumbers="ngModel" ></p>
                    <p><input id="subject" type="text" name="your-subject" placeholder="Subject" [(ngModel)]="newContactUs.subject" #subject="ngModel" ></p>
                    <p><textarea id="message" name="your-message" placeholder="Message" [(ngModel)]="newContactUs.message" #message="ngModel" ></textarea></p>
                   <!-- <p><input type="submit" value="SEND" onClick="SendMail()"></p> -->
                   <p><input type="submit" value="SEND"  (ngSubmit) = "createContactRecord(contactForm)"></p> 

                </div>      
            </div>
            <div class="clear"></div>
        </div>
    </article>
    <div class="thankyou_message" style="display:none;">
        <h2><em>Thanks</em> for contacting us!
          We will get back to you soon!</h2>
      </div>


</div>
</div>
</form>

<div class="clear"></div>



<!--Load JavaScript-->
<script src="/src/assets/js/jquery.js"></script>                                                   
<script src='/src/assets/js/jquery.fitvids.js'></script>
<script src='/src/assets/js/jquery.smartmenus.min.js'></script>        
<!-- <script src='js/imagesloaded.pkgd.js'></script>         -->
<!-- <script src='js/isotope.pkgd.js'></script>         -->
<!-- <script src='js/jquery.carouFredSel-6.0.0-packed.js'></script> -->
<!-- <script src='js/jquery.mousewheel.min.js'></script> -->
<!-- <script src='js/jquery.touchSwipe.min.js'></script> -->
<!-- <script src='js/jquery.easing.1.3.js'></script> -->
<!-- <script src='js/main-headline.js'></script> -->
<script src='/node_modules/sticky-kit/dist/sticky-kit.min.js'></script>
<!-- <script src='js/jquery.ba-throttle-debounce.min.js'></script>                 -->
<script src='/src/assets/js/jquery.nicescroll.min.js'></script>
<script src='/src/assets/js/contactUs.js'></script> 

contact-us.component.ts

import {HostListener, Component, OnInit } from '@angular/core';
import {NgForm, FormGroup, FormControl} from '@angular/forms';
import { ContactUsService } from './contact-us.service';
import { contactUsInfo } from './contactUsInfo';


@Component({
  selector: 'app-contact-us',
  templateUrl: './contact-us.component.html',
  styleUrls: ['./contact-us.component.css']
})
export class ContactUsComponent implements OnInit {

  contactUs: contactUsInfo[];
  newContactUs: contactUsInfo = new contactUsInfo();
  editing: boolean = false;
  editingTodo: contactUsInfo = new contactUsInfo();

  constructor(private contactUsService: ContactUsService,) { 

  }

  ngOnInit(): void {
    /*this.getTodos();*/
  }

 /* getTodos(): void {
    this.contactUsService.getTodos()
      .then(todos => this.contactUs = todos );    
  }*/



  createContactRecord(todoForm: NgForm): void {

    console.log("hello");

    if (this.isValidEmailAddress(this.newContactUs.contactEmail)) {
      this.contactUsService.createTodo(this.newContactUs)
      .then(createTodo => {    
        todoForm.reset();
        this.newContactUs = new contactUsInfo();
        this.contactUs.unshift(createTodo)
      });
    } else
    {
        alert('Your email is not in valid format');
    }



  }

  isValidEmailAddress(emailAddress) {
    var pattern = /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i;
    return pattern.test(emailAddress);
  }



  /*deleteTodo(id: string): void {
    this.contactUsService.deleteTodo(id)
    .then(() => {
      this.contactUs = this.contactUs.filter(todo => todo.id != id);
    });
  }

  updateTodo(contactUsData: contactUsInfo): void {
    console.log(contactUsData);
    this.contactUsService.updateTodo(contactUsData)
    .then(updatedTodo => {
      let existingTodo = this.contactUs.find(todo => todo.id === updatedTodo.id);
      Object.assign(existingTodo, updatedTodo);
      this.clearEditing();
    });
  }

  toggleCompleted(contactUsData: contactUsInfo): void {
    contactUsData.completed = !contactUsData.completed;
    this.contactUsService.updateTodo(contactUsData)
    .then(updatedTodo => {
      let existingTodo = this.contactUs.find(todo => todo.id === updatedTodo.id);
      Object.assign(existingTodo, updatedTodo);
    });
  }

  editTodo(contactUsData: contactUsInfo): void {
    this.editing = true;
    Object.assign(this.editingTodo, contactUsData);
  }

  clearEditing(): void {
    this.editingTodo = new contactUsInfo();
    this.editing = false;
  }*/



}

contact-us.service.ts

import { Injectable } from '@angular/core';
import { contactUsInfo } from './contactUsInfo';
import { Headers, Http } from '@angular/http';

@Injectable({
  providedIn: 'root'
})
export class ContactUsService {

  private baseUrl = 'http://localhost:8080';

  private Url = 'http://localhost:8080/contact/contactus/';

  private headers = new Headers({'Content-Type': 'application/json'});

  constructor(private http: Http) { }

  getTodos():  Promise<contactUsInfo[]> {
    return this.http.get(this.baseUrl + '/contact/contactus/')
      .toPromise()
      .then(response => response.json() as contactUsInfo[])
      .catch(this.handleError);
  }

  /*createTodo(todoData: contactUsInfo): Promise<contactUsInfo> {
    return this.http.post(this.baseUrl + '/contact/contactus/', todoData)
      .toPromise().then(response => response.json() as contactUsInfo)
      .catch(this.handleError);
  }*/

  createTodo(todoData: contactUsInfo): Promise<contactUsInfo> {
    return this.http.post(this.Url, todoData, {headers: this.headers})
      .toPromise().then(response => response.json() as contactUsInfo)
      .catch(this.handleError);
  }

  updateTodo(todoData: contactUsInfo): Promise<contactUsInfo> {
    return this.http.put(this.baseUrl + '/contact/contactus/' + todoData.id, todoData)
      .toPromise()
      .then(response => response.json() as contactUsInfo)
      .catch(this.handleError);
  }

  deleteTodo(id: string): Promise<any> {
    return this.http.delete(this.baseUrl + '/contact/contactus/' + id)
      .toPromise()
      .catch(this.handleError);
  }

  private handleError(error: any): Promise<any> {
    console.error('Some error occured', error);
    return Promise.reject(error.message || error);
  }

}

contactUsInfo.ts

export class contactUsInfo {
  id: string;
  name: string;
  contactEmail: string;
  contactnumber: string;
  subject: string;
  message: string;
  completed: boolean;
  createdAt: Date;
}

ContactUsController.java

package com.royangular.royAngularProject.controllersContact;

import javax.validation.Valid;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import com.royangular.royAngularProject.models.ContactUs;
import com.royangular.royAngularProject.models.Todo;
import com.royangular.royAngularProject.repositories.ContactUsRepository;
import com.royangular.royAngularProject.repositories.TodoRepository;

import java.util.List;

@CrossOrigin(origins = "http://localhost:8080" , allowCredentials = "false")
@RestController
@RequestMapping("/contact")
public class ContactUsController {

     @Autowired
      TodoRepository todoRepository;


    @Autowired
    ContactUsRepository contactUsRepository;


    @GetMapping("/todos")
    public List<Todo> getAllTodos() {
        Sort sortByCreatedAtDesc = new Sort(Sort.Direction.DESC, "createdAt");
        return todoRepository.findAll(sortByCreatedAtDesc);
    }

    @PostMapping("/todos")
    public Todo createTodo(@Valid @RequestBody Todo todo) {
        System.out.println(todo);
        System.out.println(todo.getTitle());
        todo.setCompleted(false);
        return todoRepository.save(todo);
    }

    @PostMapping("/contactus")
    public ContactUs createContact(@Valid @RequestBody ContactUs todo) {
        todo.setCompleted(false);
        return contactUsRepository.save(todo);
    }


    @PostMapping(value="/todos/{id}")
    public ResponseEntity<Todo> getTodoByName(@PathVariable("id") String id) {


        MongoTemplate mongoTemplate = null;


        Query query2 = new Query();
        query2.addCriteria(Criteria.where("name").is("dog").and("age").is(40));


        ContactUs userTest2 = mongoTemplate.findOne(query2, ContactUs.class);


        return todoRepository.findById(id)
                .map(todo -> ResponseEntity.ok().body(todo))
                .orElse(ResponseEntity.notFound().build());
    }

    @GetMapping(value="/todos/{id}")
    public ResponseEntity<Todo> getTodoById(@PathVariable("id") String id) {

        return todoRepository.findById(id)
                .map(todo -> ResponseEntity.ok().body(todo))
                .orElse(ResponseEntity.notFound().build());
    }

    @PutMapping(value="/todos/{id}")
    public ResponseEntity<Todo> updateTodo(@PathVariable("id") String id,
                                           @Valid @RequestBody Todo todo) {
        return todoRepository.findById(id)
                .map(todoData -> {
                    todoData.setTitle(todo.getTitle());
                    todoData.setCompleted(todo.getCompleted());
                    Todo updatedTodo = todoRepository.save(todoData);
                    return ResponseEntity.ok().body(updatedTodo);
                }).orElse(ResponseEntity.notFound().build());
    }

    @DeleteMapping(value="/todos/{id}")
    public ResponseEntity<?> deleteTodo(@PathVariable("id") String id) {
        return todoRepository.findById(id)
                .map(todo -> {
                    todoRepository.deleteById(id);
                    return ResponseEntity.ok().build();
                }).orElse(ResponseEntity.notFound().build());
    }


}

Error From angular 6

zone.js:2969 OPTIONS http://localhost:8080/contact/contactus/ 403
scheduleTask @ zone.js:2969
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:407
onScheduleTask @ zone.js:297
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:401
push../node_modules/zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:232
push../node_modules/zone.js/dist/zone.js.Zone.scheduleMacroTask @ zone.js:255
scheduleMacroTaskWithCurrentZone @ zone.js:1114
(anonymous) @ zone.js:3001
proto.(anonymous function) @ zone.js:1394
(anonymous) @ http.js:1103
push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe @ Observable.js:42
push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe @ Observable.js:28
(anonymous) @ Observable.js:92
ZoneAwarePromise @ zone.js:891
push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.toPromise @ Observable.js:90
push../src/app/pages/contact-us/contact-us.service.ts.ContactUsService.createTodo @ contact-us.service.ts:33
push../src/app/pages/contact-us/contact-us.component.ts.ContactUsComponent.createContactRecord @ contact-us.component.ts:39
(anonymous) @ ContactUsComponent.html:18
handleEvent @ core.js:10258
callWithDebugContext @ core.js:11351
debugHandleEvent @ core.js:11054
dispatchEvent @ core.js:7717
(anonymous) @ core.js:9197
schedulerFn @ core.js:3567
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:209
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next @ Subscriber.js:147
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next @ Subscriber.js:80
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:55
push../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next @ Subject.js:47
push../node_modules/@angular/core/fesm5/core.js.EventEmitter.emit @ core.js:3539
push../node_modules/@angular/forms/fesm5/forms.js.NgForm.onSubmit @ forms.js:3801
(anonymous) @ ContactUsComponent.html:18
handleEvent @ core.js:10258
callWithDebugContext @ core.js:11351
debugHandleEvent @ core.js:11054
dispatchEvent @ core.js:7717
(anonymous) @ core.js:8161
(anonymous) @ platform-browser.js:995
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:3815
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:420
push../node_modules/zone.js/dist/zone.js.Zone.runTask @ zone.js:188
push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:496
invokeTask @ zone.js:1540
globalZoneAwareCallback @ zone.js:1566
contact_us:1 Access to XMLHttpRequest at 'http://localhost:8080/contact/contactus/' from origin 'http://localhost:4200' 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.
contact-us.service.ts:51 Some error occured Response {_body: ProgressEvent, status: 0, ok: false, statusText: "", headers: Headers, …}
push../src/app/pages/contact-us/contact-us.service.ts.ContactUsService.handleError @ contact-us.service.ts:51
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:388
onInvoke @ core.js:3824
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:387
push../node_modules/zone.js/dist/zone.js.Zone.run @ zone.js:138
(anonymous) @ zone.js:872
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:3815
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:420
push../node_modules/zone.js/dist/zone.js.Zone.runTask @ zone.js:188
drainMicroTaskQueue @ zone.js:595
push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:500
invokeTask @ zone.js:1540
globalZoneAwareCallback @ zone.js:1566
error (async)
customScheduleGlobal @ zone.js:1666
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:407
onScheduleTask @ zone.js:297
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:401
push../node_modules/zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:232
push../node_modules/zone.js/dist/zone.js.Zone.scheduleEventTask @ zone.js:258
(anonymous) @ zone.js:1831
(anonymous) @ http.js:1102
push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe @ Observable.js:42
push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe @ Observable.js:28
(anonymous) @ Observable.js:92
ZoneAwarePromise @ zone.js:891
push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.toPromise @ Observable.js:90
push../src/app/pages/contact-us/contact-us.service.ts.ContactUsService.createTodo @ contact-us.service.ts:33
push../src/app/pages/contact-us/contact-us.component.ts.ContactUsComponent.createContactRecord @ contact-us.component.ts:39
(anonymous) @ ContactUsComponent.html:18
handleEvent @ core.js:10258
callWithDebugContext @ core.js:11351
debugHandleEvent @ core.js:11054
dispatchEvent @ core.js:7717
(anonymous) @ core.js:9197
schedulerFn @ core.js:3567
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:209
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next @ Subscriber.js:147
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next @ Subscriber.js:80
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:55
push../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next @ Subject.js:47
push../node_modules/@angular/core/fesm5/core.js.EventEmitter.emit @ core.js:3539
push../node_modules/@angular/forms/fesm5/forms.js.NgForm.onSubmit @ forms.js:3801
(anonymous) @ ContactUsComponent.html:18
handleEvent @ core.js:10258
callWithDebugContext @ core.js:11351
debugHandleEvent @ core.js:11054
dispatchEvent @ core.js:7717
(anonymous) @ core.js:8161
(anonymous) @ platform-browser.js:995
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:3815
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:420
push../node_modules/zone.js/dist/zone.js.Zone.runTask @ zone.js:188
push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:496
invokeTask @ zone.js:1540
globalZoneAwareCallback @ zone.js:1566
core.js:1673 ERROR Error: Uncaught (in promise): Response with status: 0  for URL: null
    at resolvePromise (zone.js:814)
    at resolvePromise (zone.js:771)
    at zone.js:873
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:3815)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
    at drainMicroTaskQueue (zone.js:595)
    at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:500)
    at invokeTask (zone.js:1540)

enter image description here

2

There are 2 answers

1
Efe On

You can use proxies to make a request when you are working locally. Here is the reference

0
Yassine Ben Hamida On

As @Efe stated you need to use proxies when handling requests to your backend application, i will try to explain some steps:

You need to start by creating a proxy.conf.json file that will contain the following

{
    "/api/*": {
      "target": "http://localhost:8080",
      "secure": false,
      "logLevel": "debug",
      "pathRewrite": {"^/api" : ""}
    }
}

then updating you angular.json file "start" attribute from "start": "ng serve"

to "start": "ng serve --proxy-config proxy.conf.json"

Note that in order to automatically use the proxy you should use npm start rather than ng serve when running the angular app otherwise it won't run it.

Finally calling an api becomes such as below :

  export class MyService{ 
        constructor(private http: HttpClient) { }       
        getAll(){
            return this.http.get<any[]>("/api/mydata/")
        }
}

You can read more on angular proxies from this article.