表示路径相同但参数不同的路线

时间:2016-11-01 23:48:37

标签: angularjs node.js express

我有两种方法:

  • validateRegistration(),它调用app.get(' / users /:email',todo)

  • login(),它调用app.get(' / users /:username',todo)

validateRegistration()工作正常,但是当调用login()时,它返回null,但是如果我在server.js中注释掉app.get(' / users /:email',todo) ,login()返回预期的响应。似乎两者都不能在server.js中一起存在

参见下面的相关代码

registerPage.html



<div class="container" ng-show="show">
		<form name="registerForm" novalidate>

			<h2>Registration</h2>
			<span>All fields required</span>
			<br>
			<br>
			<label>First Name</label>
			<br>
			<input class="form-control" type="text" ng-model="user.fName" name="fName" required placeholder="First Name">
			<div ng-messages="registerForm.fName.$error">
				<div class="errorMsg" ng-message="required">Required</div>
			</div>
			
			<br>
			<label>Last Name</label>
			<input class="form-control" type="text" ng-model="user.lName" name="lName" required placeholder="Last Name">
			<div ng-messages="registerForm.lName.$error">
				<div class="errorMsg" ng-message="required">Required</div>
			</div>

			<br>
			<label>Email</label>
			<input class="form-control" ng-model="user.email" ng-change="validateEmail(user.email)" type="email" name="emailAdd" required placeholder="Email">
			<span class="errorMsg">{{emailExistsMsg}}</span>

			<div ng-messages="registerForm.emailAdd.$error">
				<div class="errorMsg" ng-message="email">Invalid email address</div>
				<div class="errorMsg" ng-message="required">Required</div>
			</div>

			<br>
			<label>Username</label>
			<input class="form-control" ng-model="user.username" ng-change="validateUsername(user.username)" type="text" name="uName" required placeholder="Username">
			<span class="errorMsg">{{usernameExistsMsg}}</span>
			<div ng-messages="registerForm.uName.$error">
				<div class="errorMsg" ng-message="required">Required</div>
			</div>

			<br>
			<label>Password</label>
			<input class="form-control" ng-minlength="6" type="password" ng-model="user.password" name="password" required placeholder="Password">
			<div ng-messages="registerForm.password.$error">
				<div class="errorMsg" ng-message="minlength">Password should be 6 character minimum</div>
				<div class="errorMsg" ng-message="required">Required</div>
			</div>

			<br>
			<button class="btn btn-info" ng-click="addUser(user)" ng-disabled="registerForm.$invalid">Register</button>
			<br>
			<br>
			<a href="#/signIn">Already registered?......<strong>Log In</strong></a>
	</form>
</div>
&#13;
&#13;
&#13;

registerController.js

&#13;
&#13;
myApp.controller('RegisterController', ['$scope', '$http', '$location', function($scope, $http, $location) {
	console.log("Register controller");

	$scope.addUser = function(user) {
		console.log("Add user called");
		$http.post('/users', {fname: user.fName, lname: user.lName, email: user.email, username: user.username, password: user.password}).success(function(response) {
			console.log("Add user response username: " + response.username);
		});

		this.validateRegistration(user.email);
	};

	$scope.validateEmail = function(email) {
		console.log("Validate email called");
		$http.get('/users/' + email).success(function(response) {
			if(response != null) {
				$scope.emailExistsMsg = response.email + " already exists";
			} else {
				$scope.emailExistsMsg = "";
			}
		});
	};

	$scope.validateRegistration = function(email) {
		$http.get('/users/' + email).success(function(response) {
			if(response != null) {
				console.log("Registration successful");
				$scope.registrationMsg = "Congratulations " + email + ". Registration successful";
				console.log($scope.registrationMsg);
				$location.path("/registrationStatus");

			} else {
				console.log("Registration not successful: " + response);
				$scope.registrationMsg = "Error with registration. Please try again or contact administrator.";
				console.log($scope.registrationMsg);
				$location.path("/registrationStatus");
			}
		});
	};
}]);
&#13;
&#13;
&#13;

signinPage.html

&#13;
&#13;
<div class="container" ng-show="show">

	<br>
	<form name="signInForm" novalidate>
		<h2>Sign In</h2>
		<br>
		<label>Username</label>
		<input class="form-control" ng-model="user.username" type="text" name="username" required placeholder="Username">
		<br>
		<label>Password</label>
		<input class="form-control" ng-model="user.password" type="password" name="password" required placeholder="Password">
		<br>
		<button class="btn btn-info" ng-click="logIn(user.username, user.password)" ng-disabled="signInForm.$invalid">Sign In</button>
		<br>
		<br>
		<a href="#/register">Not registered?......<strong>Register</strong></a>
	</form>

</div>
&#13;
&#13;
&#13;

signinController.js

&#13;
&#13;
myApp.controller('SignInController', ['$scope', '$http', '$location', function($scope, $http, $location) {
	console.log("Sign in controller");

	$scope.logIn = function(username, password) {
		console.log("Sign in called");

		$http.get('/users/' + username).success(function(response) {
			if(response != null) {
				if(username == response.username && password == response.password) {
					console.log("Successful log in");
					this.isDisabled = false;
					$location.path("/playSet");
				}
			} else {
				console.log("User not found: " + response);
			}
		});
	};
}]);
&#13;
&#13;
&#13;

server.js

&#13;
&#13;
var express = require('express');
var app = express();
var mongojs = require('mongojs');
var db = mongojs('tracks', ['tracks']);
var db1 = mongojs('setlist', ['setlist']);
var db2 = mongojs('users', ['users']);
var bodyParser = require('body-parser');

app.use(express.static(__dirname = '\public'));
app.use(bodyParser.json());

app.get('/users/:email', function(req, res) {
	var email = req.params.email;
	console.log("Existing email validation: " + email);
	db2.users.findOne({email: email}, function(err, doc) {
		res.json(doc);
	});
});

app.get('/users/:username', function(req, res) {
	var username = req.params.username;
	console.log("User: " + username);
	db2.users.findOne({username: username}, function(err, doc) {
		res.json(doc);
	});
});

app.listen(3000);
console.log("Server running on port 3000");
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分:3)

您不能有两条不同的路线:

app.get('/users/:email', ...);
app.get('/users/:username', ...);

因为第二个不会被击中,因为第一个匹配相同的东西。您有以下选择:

  1. 更改一个路径,使其与另一个路径唯一。
  2. 将它们合并到一个路由处理程序中,并设计如何从其他条件(查询参数,cookie,会话状态等)中确定要执行哪个逻辑块。
  3. 使用更复杂的路由定义(可能包括正则表达式),以便您实际告诉每个路由定义两条路由之间的区别。
  4. 如果(我只是从您的上下文中猜测一下),您尝试支持两种识别用户的方式(一个是用户名,另一个是电子邮件地址),那么我和建议您将它们组合到一个路由处理程序中,然后检查:username值以查看它是用户名还是电子邮件地址,并在您的路由中相应地执行操作。如果用户名中不允许@符号,但电子邮件地址中需要req.params.username符号,则可以使用此功能。然后,您可以检查@是否包含// single route handler to handle either a username or email lookup app.get('/users/:username', function(req, res) { var username = req.params.username; if (username.indexOf("@") !== -1) { console.log("Existing email validation: " + username); db2.users.findOne({email: username}, function(err, doc) { res.json(doc); }); } else { console.log("User: " + username); db2.users.findOne({username: username}, function(err, doc) { res.json(doc); }); } }); 符号,如果是,则转移到电子邮件地址逻辑。

    // single route handler to handle either a username or email lookup
    app.get('/users/:username', function(req, res) {
        // lookup either email address or username
        let name = req.params.username;
        let lookupObj = name.indexOf("@") !== -1 ? {email: name} : {username: name};
        db2.users.findOne(lookupObj, function(err, doc) {
            res.json(doc);
        });
    });
    

    或者,或许多一点干:

    app.get('/users/email/:email', ...);
    app.get('/users/userID/:username', ...);
    

    或者,您可以使用唯一路径分隔路线:

    allScriptsTimeout

答案 1 :(得分:1)

这个问题已经发布 4 年多了,我也遇到了类似的问题。

我想谈谈我是如何解决这个问题的。它可能会有所帮助。简而言之,我将控制器转换为中间件。

我最初拥有的

app.get('/users/:email', ...);
app.get('/users/:id', ...);

我删除了

app.get('/users/:email', ...)

并制作成

app.get('/users', getUserByEmail, ...otherControllers)

然后,在 getUserByEmail 中,我检查 email 对象上是否存在 req.query 属性,并且如果它是查询对象上的唯一属性,则通过以下方式搜索用户电子邮件,否则,执行下一个函数以移动到下一个控制器/中间件。

 if(req.query.email !== undefined && Object.keys(req.query).length === 1){
   ... code to get user by email
   end if block with return
  }
  next()

答案 2 :(得分:0)

这些不是唯一的路线。

与给定路径匹配的第一个路径是使用的路径,无论提供的参数如何。

此处您的路由/users/包含email参数,后跟相同的路由/users/,其中username参数永远不会被评估。

如果要使用这种路由方式,则应该有一个/users/路由接受参数,然后在该路由中评估参数以确定它是email还是{ {1}},然后在数据库上执行相应的查找。这不是一种简单或万无一失的方法,并且限制了某人可以将其电子邮件地址用作用户名等的可能性。因此,您应强烈考虑使用唯一路线,例如username或类似的路线。

就我个人而言,我认为您的问题因为您似乎希望使用/users/email/:email进行注册和登录而更加困惑。您可能应该使用/users//login/之类的内容,尤其是以后您可以使用/register/来获取用户列表。但是,如果必须使用相同的路线,可以将它们分隔为/users/get,因为post更为常见无论如何,还有注册类型的场景。

总的来说,感觉您需要花费更多时间来评估整体API的使用和目的,以确定构建端点的正确方法。