У меня проблемы с пониманием того, как правильно использовать DSL Ktor для маршрутизация запросов. Проблема в том, что когда я тестирую свой API и пытаюсь GET /nomenclature/articles/categories
, который должен вернуть список всех категорий статей, вместо этого я получаю Invalid article specified
сообщение, которое я возвращаю для маршрута /nomenclature/articles/{articleId}
, когда параметр articleId
недействителен.
Вот мой код:
route("/nomenclature") {
method(HttpMethod.Get) {
handle { call.respondText("The resource you accessed is not a valid REST resource, but a parent node. Children nodes include articles, categories, subcategories and so on.") }
}
route("articles") {
route("categories") {
get("{categoryId?}") {
val categoryIdParam = call.parameters["categoryId"]
if (categoryIdParam != null) {
val categoryId = categoryIdParam.toIntOrNull()
if (categoryId != null) {
val category = articlesDAO.findCategoryById(categoryId)
if (category != null) call.respond(category)
else call.respondText("Category not found", status = HttpStatusCode.NotFound)
} else call.respondText("Invalid category ID specified", status = HttpStatusCode.BadRequest)
} else {
val categories = articlesDAO.getCategories()
if (categories != null) call.respond(categories)
else call.respondText("No categories found", status = HttpStatusCode.NotFound)
}
}
}
route("subcategories") {
get("{subcategoryId?}") {
val subcategoryIdParam = call.parameters["subcategoryId"]
if (subcategoryIdParam != null) {
val subcategoryId = subcategoryIdParam.toIntOrNull()
if (subcategoryId != null) {
val subcategory = articlesDAO.findSubcategoryById(subcategoryId)
if (subcategory != null) call.respond(subcategory)
else call.respondText("Subcategory not found", status = HttpStatusCode.NotFound)
} else call.respondText("Invalid subcategory ID specified", status = HttpStatusCode.BadRequest)
} else {
val subcategories = articlesDAO.getCategories()
if (subcategories != null) call.respond(subcategories)
else call.respondText("No subcategories found", status = HttpStatusCode.NotFound)
}
}
}
get("types") {
val articleTypes = articlesDAO.getArticleTypes()
if (articleTypes != null) call.respond(articleTypes)
else call.respondText("No article types found", status = HttpStatusCode.NotFound)
}
get("wholePackagings") {
val wholePackagings = articlesDAO.getWholePackagings()
if (wholePackagings != null) call.respond(wholePackagings)
else call.respondText("No whole packagings found", status = HttpStatusCode.NotFound)
}
get("fractionsPackagings") {
val fractionsPackagings = articlesDAO.getFractionPackagings()
if (fractionsPackagings != null) call.respond(fractionsPackagings)
else call.respondText("No fractions packagings found", status = HttpStatusCode.NotFound)
}
get("{articleId?}") {
val articleIdParam = call.parameters["articleId"]
if (articleIdParam != null) {
val articleId = articleIdParam.toIntOrNull()
if (articleId != null) {
val article = articlesDAO.findArticleById(articleId)
if (article != null) call.respond(article) else call.respondText("No article found", status = HttpStatusCode.NotFound)
} else call.respondText("Invalid article ID specified", status = HttpStatusCode.BadRequest)
} else {
val articles = articlesDAO.getArticles()
if (articles != null) call.respond(articles) else call.respondText("No articles found", status = HttpStatusCode.NotFound)
}
}
}
}
Было бы здорово, если бы кто-нибудь мог мне помочь, предоставив базовый, но в некоторой степени исчерпывающий пример того, как использовать все сопоставители и обработчики маршрутов Ktor, в том числе во вложенных ресурсах.
РЕДАКТИРОВАТЬ: я переписал маршрутизацию, используя другой подход, но мне все равно хотелось бы знать, почему моя предыдущая версия не работала должным образом. Вот мой второй подход, который, похоже, работает, как ожидалось (я его тестировал):
routing {
route("/v1") {
route("stock") {
get {
val stock = stockDAO.getAllStock()
if (stock != null) call.respond(stock) else call.respondText("No stock found", status = HttpStatusCode.NotFound)
}
get("{locationId}") {
val locationIdParam = call.parameters["locationId"]
if (locationIdParam != null) {
val locationId = locationIdParam.toIntOrNull()
if (locationId != null) {
val stock = stockDAO.getStockByLocationId(locationId)
if (stock != null) call.respond(stock) else call.respondText("No stock found", status = HttpStatusCode.NotFound)
} else call.respondText("ERROR: Invalid location ID specified.", status = HttpStatusCode.BadRequest)
}
}
}
route("nomenclature") {
get {
call.respondText("The resource you accessed is not a valid REST resource, but a parent node. Children nodes include articles, categories, subcategories and so on.")
}
route("articles") {
get {
val articles = articlesDAO.getArticles()
if (articles != null) call.respond(articles) else call.respondText("No articles found", status = HttpStatusCode.NotFound)
}
get("{articleId}") {
val articleIdParam = call.parameters["articleId"]
if (articleIdParam != null) {
val articleId = articleIdParam.toIntOrNull()
if (articleId != null) {
val article = articlesDAO.findArticleById(articleId)
if (article != null) call.respond(article) else call.respondText("No article found", status = HttpStatusCode.NotFound)
} else call.respondText("Invalid article ID specified", status = HttpStatusCode.BadRequest)
}
}
route("categories") {
get {
val categories = articlesDAO.getCategories()
if (categories != null) call.respond(categories)
else call.respondText("No categories found", status = HttpStatusCode.NotFound)
}
get("{categoryId}") {
val categoryIdParam = call.parameters["categoryId"]
if (categoryIdParam != null) {
val categoryId = categoryIdParam.toIntOrNull()
if (categoryId != null) {
val category = articlesDAO.findCategoryById(categoryId)
if (category != null) call.respond(category)
else call.respondText("Category not found", status = HttpStatusCode.NotFound)
} else call.respondText("Invalid category ID specified", status = HttpStatusCode.BadRequest)
}
}
}
route("subcategories") {
get {
val subcategories = articlesDAO.getSubcategories()
if (subcategories != null) call.respond(subcategories)
else call.respondText("No subcategories found", status = HttpStatusCode.NotFound)
}
get("{subcategoryId}") {
val subcategoryIdParam = call.parameters["subcategoryId"]
if (subcategoryIdParam != null) {
val subcategoryId = subcategoryIdParam.toIntOrNull()
if (subcategoryId != null) {
val subcategory = articlesDAO.findSubcategoryById(subcategoryId)
if (subcategory != null) call.respond(subcategory)
else call.respondText("Subcategory not found", status = HttpStatusCode.NotFound)
} else call.respondText("Invalid subcategory ID specified", status = HttpStatusCode.BadRequest)
}
}
}
get("types") {
val articleTypes = articlesDAO.getArticleTypes()
if (articleTypes != null) call.respond(articleTypes)
else call.respondText("No article types found", status = HttpStatusCode.NotFound)
}
get("wholePackagings") {
val wholePackagings = articlesDAO.getWholePackagings()
if (wholePackagings != null) call.respond(wholePackagings)
else call.respondText("No whole packagings found", status = HttpStatusCode.NotFound)
}
get("fractionsPackagings") {
val fractionsPackagings = articlesDAO.getFractionPackagings()
if (fractionsPackagings != null) call.respond(fractionsPackagings)
else call.respondText("No fractions packagings found", status = HttpStatusCode.NotFound)
}
}
}
}
}