I have an angular-5 component with the following form:
<form (ngSubmit)="onSubmit()" #contactForm="ngForm">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" placeholder="Your first name" id="name" required
[(ngModel)]="model.name" name="name" #name="ngModel"/>
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Name is required
</div>
<label for="number">Number</label>
<input type="text" class="form-control" placeholder="Your phone number" id="number"
[(ngModel)]="model.number" name="number"/>
<label for="email">Email</label>
<input type="text" class="form-control" placeholder="Your email address" id="email" required
[(ngModel)]="model.email" name="email" #email="ngModel"/>
<div [hidden]="email.valid || email.pristine"
class="alert alert-danger">
Email is required
</div>
<label for="comment">Comment</label>
<textarea type="text" class="form-control" placeholder="Your enquiry" id="comment" required
[(ngModel)]="model.comment" name="comment" #comment="ngModel"></textarea>
<div [hidden]="comment.valid || comment.pristine"
class="alert alert-danger">
You need to say something
</div>
</div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
There's other stuff around it, but this is the essence.
This is handled by the typescript component:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ContactPostService } from "../contact-post.service";
import {Contact} from "../contact";
@Component({
selector: 'app-contact-form',
templateUrl: './contact-form.component.html',
styleUrls: ['./contact-form.component.css']
})
export class ContactFormComponent implements OnInit, OnDestroy {
model: Contact = new Contact();
submitted = false;
constructor(private postService: ContactPostService) {}
onSubmit() {
console.log('from the form: ' + this.model.name + ', ' + this.model.number + ', ' + this.model.email + ', ' + this.model.comment);
this.postService.saveContact(this.model)
.subscribe(data => {
console.log(data);
});
this.submitted = true;
}
ngOnInit() { }
ngOnDestroy() { }
newContact() {
this.model = new Contact();
}
}
Then there is the service referred to that does the actual posting:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Contact } from './contact';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
import { catchError } from 'rxjs/operators';
@Injectable()
export class ContactPostService {
private API_ENDPOINT = 'https://ovo5xmxf7e.execute-api.ap-southeast-2.amazonaws.com/prod/ContactFormLambda';
constructor(private http: HttpClient) {}
saveContact(form: any) {
console.log('from the form: ' + form.name + ', ' + form.number + ', ' + form.email + ', ' + form.comment)
let contact: Contact = {
subject: 'Enquiry from ZenithWebFoundry',
name: form.name,
number: form.number,
email: form.email,
comment: form.comment
};
return this.http.post(this.API_ENDPOINT, contact)
.pipe(
catchError((error) => this.handleError(error))
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
return new ErrorObservable(
'Something bad happened; please try again later.');
}
}
Basically, its to post four fields and a subject value to a lambda, I have written in AWS. I have tested the Lambda from the gateway and I know that it works (I get the emails that it sends. What seems to be the problem is the API gateway for the Lambda. As soon as I enable CORS, I get the following errors in the client console (Chrome Developer Tools)
POST https://ovo5xmxf7e.execute-api.ap-southeast-2.amazonaws.com/prod/ContactFormLambda 500 () /contact:1 Failed to load https://ovo5xmxf7e.execute-api.ap-southeast-2.amazonaws.com/prod/ContactFormLambda: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://zenithwebfoundry.com' is therefore not allowed access. The response had HTTP status code 500. main.630e523b47c705dd5494.bundle.js:1 Backend returned code 0, body was: [object ProgressEvent]
I find that the OPTIONS works fine:
Request
URL:https://ovo5xmxf7e.execute-api.ap-southeast-2.amazonaws.com/prod/ContactFormLambda
Request Method:OPTIONS
Status Code:200
Remote Address:54.230.243.44:443
Referrer Policy:no-referrer-when-downgrade
Response Headers
access-control-allow-headers:Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
access-control-allow-methods:DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
access-control-allow-origin:*
content-length:0
content-type:application/json
date:Tue, 06 Feb 2018 10:05:33 GMT
status:200
via:1.1 6884828476070d32978b45d03c1cc437.cloudfront.net (CloudFront)
x-amz-cf-id:DQ4SqBJgRRU9HG4jOLu03Jvg555B9Jv_J3KH9oczNWojhiIN14aCwA==
x-amzn-requestid:450ff8a0-0b25-11e8-850f-b3335987eeef
x-cache:Miss from cloudfront
Note how it returns with the "access-control-allow-origin:*" header response, so I would have thought that the POST following this would be OK, but the POST fails with the errors above
I started with this setup, just to allow any origin:
And got a success message:
Same thing happened when I changed out '*' with my domain origin 'http://zenithwebfoundry.com'
So how do you set up your gateway with CORS so that the POST is not blocked? What am I doing wrong?

