Я служу Angular от localhost:4200
и Express от localhost:3000
. В моем маршруте localhost:4200/sign-up
у меня есть форма с <form action=https://localhost:3000/users/sign-up>
.
<form #form [formGroup]="userForm" method="POST" action="https://localhost:3000/users/sign-up">
. . .
. . .
<input type="submit" value="Submit" (click)="form.submit()" [disabled]="!userForm.valid || !usernameIsUnique">
</form>
. После отправки формы я обрабатываю отправку в Express, сохраняю данные (используя user.save()
) и простопроверьте, как все работает, завершите маршрут, отправив ответ с res.json(JSON.parse('{"foo": "bar"}')
.
exports.user_create_post = [
. . .
(req,res,next) => {
var user = new UserObj(
{ . . . });
user.save(function(err) { . . . });
res.json(JSON.parse('{"foo": "bar"}'));
}]
После res.json()
мой URL остается на https://localhost:3000/users/sign-up
, и у меня появляется консольная ошибка: Content Security Policy: The page’s settings blocked the loading of a resource at https://localhost:3000/favicon.ico (“default-src”).
(Для простоты здесь я постараюсь рассмотреть проблему Content Security Policy
в отдельном посте).
Предполагая, что ошибок не было, должен ли URL оставаться на https://localhost:3000/users/sign-up
после ответа res.json()
, или URL браузера должен вернуться к referrer
, то есть localhost:4200/sign-up
? Другими словами, в обычном случае без ошибок, действительно ли при отправке формы URL-адрес браузера изменяется на URL-адрес, указанный в свойстве action
(https://localhost:3000/users/sign-up
)? Или он отправляет данные на URL-адрес свойства action
(https://localhost:3000/users/sign-up
), но сохраняет URL-адрес браузера на referrer
URL (localhost:4200/sign-up
)?
Если действительно отправка формы изменяет URL-адресна https://localhost:3000/users/sign-up
, означает ли это, что res.json()
также отправляется на https://localhost:3000/users/sign-up
(вместо localhost:4200/sign-up
)? Если это так, это объясняет, почему у меня проблемы. Кроме того, предполагая, что res.json()
отправлено на https://localhost:3000/users/sign-up
, а не на реферер (localhost:4200/sign-up
), как я могу перенаправить на localhost:4200/sign-up
И отправить ответ JSON на localhost:4200/sign-up
(учитывая, что только один ответразрешено за запрос)?
Спасибо!
===========================
ОБНОВЛЕНИЕ ОБНОВЛЕНИЕОБНОВЛЕНИЕ ОБНОВЛЕНИЕ
Я внес отличные изменения, предложенные @John Mgbako, но теперь возникла новая проблема, заключающаяся в том, что myu server пытается сохранить один и тот же документ два раза за запрос POST
(см. Подробностиниже). Теперь у меня есть:
ШАБЛОН
<form #f="ngForm" [formGroup]="userForm" (ngSubmit)="doSignUp(f)">
<ng-container *ngFor="let key of keyArr; index as i">
<label [hidden]='key[1]'> {{key[2]}}
<div>
<input *ngIf="key[1]==='password' type='password' [formControlName]='key[0]' id={{key[0]}} name={{key[0]}}/>
<input *ngIf="key[1]!=='password' type='text' [formControlName]='key[0]' id={{key[0]}} name={{key[0]}}/>
</div>
</label>
<br/>
</ng-container>
<button>Submit</button>
</form>
КОМПОНЕНТ
@Injectable()
export class SignupComponent implements OnInit, OnChanges {
data: Object;
keys: string[];
keyArr: any[] = [];
formCtls: any = {};
userForm: FormGroup;
cookieValue: string;
constructor(private member: MemberService,
private fb: FormBuilder,
private cs: CookieService,
private router: Router,
private route: ActivatedRoute) { }
ngOnChanges() {
// IF COOKIE EXISTS THEN ALREADY SIGNED UP, SO REDIRECT . . .
console.log("IN ON_CHANGES");
const cookie = this.cs.get("SESSIONID");
if (cookie) {
console.log(`ID: ${JSON.stringify(cookie)}`);
debugger;
this.router.navigateByUrl('../two-fa',{relativeTo: this.route})
}
}
ngOnInit() {
this.member.getSignupForm().subscribe((data)=>{
this.data = data;
this.keys = Object.keys(data["authData"]);
this.keys.forEach((key,idx) => {
let datArr = [];
this.formCtls[key] = new FormControl('', {updateOn: 'blur'});
if (key !== '_id') {
datArr.push(key,
data["authData"][key]["attr"]["hidden"],
data["authData"][key]["attr"]["label"]);
} else {
datArr.push(key,true,'');
}
if (key === 'password' || key === 'hash') {
let datArr = [];
this.formCtls['password2'] = new FormControl('');
datArr.push('password2', false, 'Password (again): ');
this.keyArr.push(datArr);
}
});
this.userForm = new FormGroup(this.formCtls);
if (this.data) this.got_data = true;
console.log("OnInit Data: " + this.data_string);
this.cs.set('member-cookie','{login-name: ' + data["authData"]["username"]["value"].pop() + '}');
this.cookieValue = this.cs.get('member-cookie');
console.log ("Cookie: " + this.cookieValue);
//Set up observable on the Username Input, to check if Unique
this.formCtls['username'].valueChanges.pipe(
filter((text: String) =>text.length > 2),
tap(text=>console.log("Text 1: " + text)),
debounceTime(10),
distinctUntilChanged(),
switchMap((text: String) =>this.member.getUnique(text.toLowerCase()))
).subscribe(r=> {console.log(`Result from unique get(): ${r}`);
this.usernameIsUnique = (r > 0) ? false : true; // r is # of instances in DB
console.log(`Unique? (length: ${r}): ${this.usernameIsUnique}`); });
});
}
doSignUp(f: NgForm) {
this.member.postSignupForm(f).subscribe((res)=>console.log(`RES: ${JSON.stringify(res)}`));
}
}
АВТОСЕРВИС (ОБСЛУЖИВАНИЕ ЧЛЕНА)
@Injectable({
providedIn: 'root'
})
export class MemberService {
host_url: string = "https://localhost:3000/users/";
signup_url: string = this.host_url+"sign-up";
data: string = '';
constructor(private http: HttpClient) { }
getSignupForm(): Observable<any> {
return this.http.get(this.signup_url,{responseType: 'json'})
}
postSignupForm(f: NgForm): Observable<any> {
return this.http.post(this.signup_url, f.value);
}
getUserIdFromRoute(route: ActivatedRoute): Observable<string> {
return route.paramMap.pipe(
map((params: ParamMap) => params.get('id'))
)
}
getUnique(s: String): Observable<any> {
return this.http
.get(`${this.host_url}unique?username=${s}`, {responseType: 'json'})
}
}
МАРШРУТ СЕРВЕРА
. . .
. . .
user.save().then(()=> {
res.cookie("SESSIONID", user.generateJWT(), {httpOnly:true, secure:true});
. . .
. . .
** ПРОБЛЕМА (С) ЕСТЬ / СЕЙЧАС:
- СЕРВЕР СДЕЛАЕТ, ЧТОБЫ ПОПРОБОВАТЬ, ЧТОБЫ СОХРАНИТЬ ЖЕ ДОКУМЕНТ 2 раза на ЗАПРОС ПОЧТЫ. (Он сохраняется правильно в MongoDB, затем через некоторое время я получаю сообщение об ошибке Dup Key на стороне сервера, когда сервер снова пытается сохранить тот же документ).
- Без элемента
BUTTON
ЭЛЕМЕНТ, НИЧЕГО НЕ ПРОИСХОДИТ, КОГДА НАХОДЯТСЯВЕРНУТЬСЯ В ВХОДНЫЕ ЭЛЕМЕНТЫ - С
BUTTON
ЭЛЕМЕНТОМ, ПОЧТИ ПОЧЕМУ, ЕСЛИ ФОРМА ПРЕДСТАВЛЯЕТСЯ ДВАЖДЫ. ВОЗМОЖНО, ЭТО ОДИН ЗАПРОС, КОГДА ДУМАЕТ ENTER
/ ВЗРЫВ ИЗ ПРОШЛОГО INPUT
И ОДИН ЗАПРОС, КОГДА НАЖИМАЕТ НА КНОПКУ SUBMIT
? (КСТАТИ, КАК ФОРМА ЗНАЕТ КНОПКУ «КНОПКА»?). - МОЕ ЖЕЛАННОЕ ПОВЕДЕНИЕ, ЧТО ФОРМА ПРЕДСТАВЛЯЕТ ТОЛЬКО, КОГДА КНОПКА
SUBMIT
НАЖИМАЕТСЯ, НЕ КОГДА ПОЛЬЗОВАТЬСЯ RETURN
ВХОДЫ. **
Есть идеи, как исправить это странное поведение, при котором сервер пытается сохранить документ дважды за POST
запрос?
ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ Добавление res.send('done') after
res.cookie () `решило проблему (т. Е. Серверная часть больше не пытается сохранить документ дважды)!