Uber REST - Car, Driver, Passenger Entity
Hubert Wang
2016-09-21
Codes and Files Structure
- Github Code Repository
- Uber REST designed before
- Files Structure:
- Result Visualization:Postman and Unit Test
- Note that only Car entity’s sample codes are given here, other entities’ codes are in Github.
GET
GET /api/cars
Get cars list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | // fake data
var cars = [{
id: 1,
year: 2012,
maker: "BMW",
model: "9 series",
doorNum: 4,
passNum: "123456",
license: "mycar1",
driverID: 1111111,
insurance: "1000000"
}, {
id: 2,
year: 2016,
maker: "Porsche",
model: "911 TURBO",
doorNum: 2,
passNum: "543210",
license: "coolCar",
driverID: 555555,
insurance: "10000000"
}];
router.route('/car')
.get(function(req,res) {
res.json(cars);
})
|
- Line 1~22: Define fake data for cars Object, properties: id, year, maker, model, door#, pass#, license, driverID, and insurance.
- Line 24~27: Response body: cars list.
Unit Test Result
Unit Test Code:
// Test GET /api/cars
exports.car_should_return_cars = function(done){
supertest(app)
.get('/api/cars')
.expect(200)
.end(done);
};
Result: passing
Postman Result
Result: response body contains cars array.
GET /api/cars/:id
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | router.route('/cars/:id/')
.get(function(req, res){
var id = req.params.id;
var carObj = cars.filter(function(element) {
return element.id == id;
})[0];
if(carObj === undefined) {
console.log("No car ID found!");
res.end();
} else {
res.json(carObj);
res.end();
}
})
|
- Line 3: Get id from request parameters.
- Line 4~6: Filter by car ID to get car Object.
- Line 7~9: If corresponding id is not found, print alert in console.
- Line 10~13: Else, print car Object.
Unit Test Result
Unit Test Code:
exports.car_should_return_json = function(done){
supertest(app)
.get('/api/cars/1/')
.expect(200)
.end(function(err,response){
console.log(err);
console.log(response.body);
assert.ok(!err);
assert.ok(typeof response.body === 'object');
return done();
});
};
Result: passing
Postman Result
Result: response body contains car Object.
GET /api/drivers/:id/car
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // get drive's car info
router.route('/drivers/:id/car')
.get(function(req, res){
var id = req.params.id;
var driverObj = drivers.filter(function(element) {
return element.id == id;
})[0];
if (driverObj === undefined) {
// driver id not found
console.log("No driver ID found!");
res.sendStatus(400)
.end();
} else {
// find car object
var carObj = cars.filter(function(element) {
return element.id == driverObj.carID;
})[0];
if (carObj === undefined) {
// car id not found
console.log("No car ID found!");
res.sendStatus(400)
.end();
} else {
// print car Object
res.json(carObj)
.end();
}
}
})
|
- Line 5~7: Get driver Object according to driverID.
- Line 8~12: If driver ID not found, bad request.
- Line 15~17: Get car Object by carID in driver Object.
- Line 18~22: If car ID not found, bad request.
- Line 24~27: Response with car Object.
Postman Result
Result: 200(OK), response body contains car Object, which is get via driver ID.
POST
POST /api/cars
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // car property list, for POST to use when no Object in Array
var carsPropList = {id:"", year:"", maker:"", model:"",
doorNum:"", passNum:"", license:"",
driverID:"", insurance:""};
router.route('/car')
.post(function(req,res) {
var reqBody = req.body;
var newCar = new Object();
for (var prop in carsPropList) {
// id should not be changed
if (prop === "id") {newCar[prop] = cars.length+1;}
else {newCar[prop] = reqBody[prop];}
}
cars.push(newCar);
res.sendStatus(200);
console.log(cars);
})
|
- Line 2~4: Property list of cars are used in Line 38, helps to filter properties posted.
- Line 6~18: Filter the properties in request body and keep id unchanged.
Unit Test Result
Unit Test Code:
exports.car_should_create_car = function(done){
supertest(app)
.get('/api/cars')
.send({license: 'new license'})
.expect(200)
.end(function(err,response){
console.log(err);
console.log(response.body);
assert.ok(!err);
assert.ok(typeof response.body === 'object');
return done();
});
};
Result: Passing
Postman Result
Sent: car info with some property not exists in property list.
Result: Only properties contained in propertyList will be taken.
PATCH
PATCH /api/cars/:id
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | router.route('/car/:id/')
.patch(function(req, res){
var id = req.params.id;
var carObj = cars.filter(function(element) {
return element.id == id;
})[0];
if(carObj === undefined) {
console.log("No car ID found!");
res.sendStatus(400)
.end();
} else {
var reqBody = req.body;
for (var prop in carObj) {
// id should not be changed
if (prop === "id") {continue;}
// don't change undefined prop in req body
if (reqBody[prop] !== undefined) {
carObj[prop] = reqBody[prop];
}
}
console.log(cars);
res.sendStatus(200)
.end();
}
})
|
- Line 3: Get id from request parameters.
- Line 4~6: Filter car Object by id.
- Line 6~10: If car ID not found, bad request.
- Line 15: Avoid the change of id.
- Line 17~19: Find changed properties in request body. And only change those mentioned properties' value. If certain property is not mentioned in request body (that is, undefined), keep it unchanged.
Postman Result
Sent: Only two properties contained in request body. The result should be: only these two properties are changed and others keep unchanged.
Result: correct.
PUT
PUT /api/cars/:id
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | router.route('/car/:id/')
.put(function(req, res){
var id = req.params.id;
var carObj = cars.filter(function(element) {
return element.id == id;
})[0];
if(carObj === undefined) {
console.log("No car ID found!");
res.sendStatus(400)
.end();
} else {
var reqBody = req.body;
for (var prop in carObj) {
// id should not be changed
if (prop === "id") {continue;}
else {carObj[prop] = reqBody[prop];}
}
console.log(cars);
res.sendStatus(200)
.end();
}
})
|
- Line 13~17: Here is only one difference between PATCH and PUT -- in PUT, if certain property is not mentioned/defined in request body, then the corresponding property will be set to undefined.
Postman Result
Sent: Only two properties contained in request body. The result should be: All properties are updated according to the request body.
Result: Correct.
DELETE
DELETE /api/cars/:id
1 2 3 4 5 6 7 8 9 10 11 | router.route('/car/:id/')
.delete(function(req, res){
var id = req.params.id;
var filtered = cars.filter(function(element) {
return element.id != id;
});
cars = filtered
console.log(cars);
res.sendStatus(200);
res.end();
})
|
- Line 4~6: Use filter to leave out car Object by ID.
Postman Result
Result: the original car list and the list after DELETE car?id=1.
Update After Class
DATED AFTER CLASS - Error Handling:
+ Return 404 instead of 400 when id not found
GET /api/cars/3999
404
{
"statusCode": 404,
"errorCode": "bad id",
"errorMsg": "3999 is not a valid ID"
}
GET api/drivers/1/car
is not proper, because one driver can have many cars. YetGET api/cars/1/drive
makes sense.