fakebackend拦截器错误消息:“用户名“未定义”已被使用”

时间:2019-10-04 12:18:50

标签: angular angular-http-interceptors

我正在遵循这个tutorial来实现一个带有假后端拦截器的简单注册/登录功能。到目前为止,我已经构建了注册组件,用户模型和服务,并具有与虚假API匹配的相应端点。但是,当我将凭据发送到服务器时,出现以下错误:error: {message: "Username "undefined" is already taken"},好像根本没有凭据被发送一样……

假后端:

    ...The imports...

// array in local storage for registered users
    let users = JSON.parse(localStorage.getItem('users')) || [];

    @Injectable()
    export class FakeBackendInterceptor implements HttpInterceptor {
        intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            const { url, method, headers, body } = request;

            // wrap in delayed observable to simulate server api call
            return of(null)
                .pipe(mergeMap(handleRoute))
                .pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
                .pipe(delay(500))
                .pipe(dematerialize());

            function handleRoute() {
                switch (true) {
                    case url.endsWith('/users/register') && method === 'POST':
                        return register();
                    case url.endsWith('/users/authenticate') && method === 'POST':
                        return authenticate();
                    case url.endsWith('/users') && method === 'GET':
                        return getUsers();
                    case url.match(/\/users\/\d+$/) && method === 'GET':
                        return getUserById();
                    case url.match(/\/users\/\d+$/) && method === 'DELETE':
                        return deleteUser();
                    default:
                        // pass through any requests not handled above
                        return next.handle(request);
                }
            }

            // route functions

            function register() {
                const user = body

                if (users.find(x => x.username === user.username)) {
                    return error('Username "' + user.username + '" is already taken')
                }

                user.id = users.length ? Math.max(...users.map(x => x.id)) + 1 : 1;
                users.push(user);
                localStorage.setItem('users', JSON.stringify(users));

                return ok();
            }

            function authenticate() {
                const { username, password } = body;
                const user = users.find(x => x.username === username && x.password === password);
                if (!user) return error('Username or password is incorrect');
                return ok({
                    id: user.id,
                    username: user.username,
                    firstName: user.firstName,
                    lastName: user.lastName,
                    token: 'fake-jwt-token'
                })
            }

            function getUsers() {
                if (!isLoggedIn()) return unauthorized();
                return ok(users);
            }

            function getUserById() {
                if (!isLoggedIn()) return unauthorized();

                const user = users.find(x => x.id == idFromUrl());
                return ok(user);
            }

            function deleteUser() {
                if (!isLoggedIn()) return unauthorized();

                users = users.filter(x => x.id !== idFromUrl());
                localStorage.setItem('users', JSON.stringify(users));
                return ok();
            }

            // helper functions

            function ok(body?) {
                return of(new HttpResponse({ status: 200, body }))
            }

            function unauthorized() {
                return throwError({ status: 401, error: { message: 'Unauthorised' } });
            }

            function error(message) {
                return throwError({ error: { message } });
            }

            function isLoggedIn() {
                return headers.get('Authorization') === 'Bearer fake-jwt-token';
            }

            function idFromUrl() {
                const urlParts = url.split('/');
                return parseInt(urlParts[urlParts.length - 1]);
            }
        }
    }

    export const fakeBackendProvider = {
        // use fake backend in place of Http service for backend-less development
        provide: HTTP_INTERCEPTORS,
        useClass: FakeBackendInterceptor,
        multi: true
    };

注册组件:

ngOnInit() {
    this.registerForm = this.fb.group({
      firstName: ['', Validators.required],
      lastName: ['', Validators.required],
      userName: ['', Validators.required],
      password: [null,[ Validators.required, Validators.minLength(6)]]
    })
  }

  get firstName() { return this.registerForm.get('firstName') }
  get lastName() { return this.registerForm.get('lastName') }
  get userName() { return this.registerForm.get('userName') }
  get password() { return this.registerForm.get('password') }

  onSubmit() {
    if (this.registerForm.invalid) return;
      this.userService.register(this.registerForm.value).subscribe(
        data => {
           console.log(data)
        },
        error => {
           console.log(error)
        });

  }

服务:

constructor(private http: HttpClient) { }

   register(credentials){
    console.log(credentials)
    return this.http.post(`/users/register`, credentials)
  }

这是控制台的一个亮点

snapshot

例如,我尚未实现所有功能,例如消息服务,但是我的问题是,为什么我会从后端得到此响应?寄存器功能设置为可以使我得到200个stauts吗?注意:由于假后端已注册,因此正确设置了app.module。另外,如果我尝试通过此设置获取用户,则会得到401,这是正确的,因为我尚未登录,因此拦截器正在工作。有人可以帮我吗?

1 个答案:

答案 0 :(得分:1)

在表单中,您正在使用userName,而在拦截器中,您正在检查username。如果要在浏览器中清除localStorage,您可能会注意到它第一次起作用!为什么...?

好的,所以第一次您的数组将为空:

let users = JSON.parse(localStorage.getItem('users')) || [];

因此,如果您输入用户名test,则您的有效负载看起来就像...

{ userName: 'test' }

注意大写N ....因此通过:

if (users.find(x => x.username === user.username)) {
  return error('Username "' + user.username + '" is already taken');
}

因为最初数组为空。

然后您执行以下操作:

 user.id = users.length ? Math.max(...users.map(x => x.id)) + 1 : 1;
 users.push(user);
 localStorage.setItem("users", JSON.stringify(users));

所以您现在存储在users中的是

[{userName: 'test'}]

现在它不会第二次通过!由于find现在将undefinedundefined进行比较,因为username的属性在您在find中比较的两个对象中都不存在。...和{ {1}}是真实的,因此它将返回您的undefined === undefined数组中的第一项。

将您的比较更改为:

users

,它将正常工作。哦,将表单控件名称更改为if (users.find(x => x.userName === user.userName)) ...