Странное поведение при вызове ExpressJS REST-маршрута
Я делаю простой REST-сервер, который оборачивается вокруг API-интерфейсов TMDb. И я использую модуль MovieDB Node, который имеет функции для прямого вызова API TMDb, предоставляя только ключ API.
У меня есть следующая структура папок приложения.
myproject
|
---configuration.json
---index.js
---app.js
---/routes
|
--- index.js
--- /movie
|
--- index.js
В myproject/index.js
У меня есть скрипт, который просто запускает сервер Express, и app.js
где я инициализирую маршруты.
MyProject/app.js
Вот как маршруты инициализируются.
var myApp = require("express")(),
configuration = require("./configuration.json");
myApp.locals.tmdbApiKey = configuration.tmdbApiKey;
myApp.use('/api', require('./routes'));
Как показано выше, сервер будет иметь корень API как localhost:9000/api/
(Я запускаю его в порту 9000
).
MyProject / маршруты /index.js
Вот как я загружаю маршруты для movie
,
var router = require('express').Router();
router.use('/movie', require('./movie'));
MyProject / маршруты / фильм /index.js
И наконец, я определил конечные точки следующим образом.
var router = require('express').Router();
router.get('/genrelist', function(req, res) {
var tmdb = require('moviedb')(req.app.locals.tmdbApiKey);
tmdb.genreList(function(err, tmdbRes) {
if (err)
res.send(err);
res.json(tmdbRes);
});
});
---
---
использование
Теперь звоню http://localhost:9000/api/movie/genrelist
должен ответить мне списком жанров, которые предоставляет TMDb API, через moviedb
"s genreList()
метод, если мое понимание маршрутов и карты маршрута правильное.
Тем не менее, я получаю следующий ответ.
{
"original": null,
"response": {
"req": {
"method": "GET",
"url": "https://api.themoviedb.org/3/movie/genrelist"
},
"header": {
"access-control-allow-origin": "*",
"cache-control": "public, max-age=28800",
"content-type": "application/json;charset=utf-8",
"date": "Wed, 15 Jun 2016 11:33:51 GMT",
"etag": "\"37a6259cc0c1dae299a7866489dff0bd\"",
"server": "openresty",
"status": "404 Not Found",
"x-memc": "MISS",
"x-memc-age": "0",
"x-memc-expires": "28800",
"x-memc-key": "35bba1a0c9464e4e471cdb466209d8b3",
"x-ratelimit-limit": "40",
"x-ratelimit-remaining": "38",
"x-ratelimit-reset": "1465990436",
"content-length": "84",
"connection": "Close"
},
"status": 404,
"text": "{\"status_code\":34,\"status_message\":\"The resource you requested could not be found.\"}"
},
"status": 404
}
Если вы видите значение response.req.url
Звонил https://api.themoviedb.org/3/movie/genrelist
что, очевидно, неверно, так как TMDb API не имеет такой конечной точки.
Однако, если я поменяю router.get
в myproject/routes/movie/index.js
что-то вроде этого:
var router = require('express').Router();
router.get('/top_rated', function(req, res) {
var tmdb = require('moviedb')(req.app.locals.tmdbApiKey);
tmdb.miscTopRatedMovies(function(err, tmdbRes) {
if (err)
res.send(err);
res.json(tmdbRes);
});
});
Это работает просто отлично, обратите внимание, что я также изменил вызов genreList()
в miscTopRatedMovies()
, Шокирующе, если я продолжу звонить genreList()
как есть, так и извлекает список top_rated
фильмы.
Даже страшно то, что я делаю console.log()
в методе GET и ничего не регистрируется. Даже отладка сервера с помощью node-debug
не прерывает выполнение, если я устанавливаю точку останова в GET. Поэтому я чувствую, что мои вызовы REST через REST-клиент напрямую преобразуются в вызовы API TMDb (возможно, из-за идентичных сигнатур REST), а MovieDB вообще не вызывается, хотя я не уверен на 100%.
Итак, чтобы определить, что-то не так с самим модулем MovieDB, я создал простой файл JS, который напрямую использует MovieDB, и запустил его с node
команда, и она работала нормально для всех методов, которые я использую.
Так что плохого в том, что я здесь делаю?
Любая помощь приветствуется.
1 ответ
Я нашел, в чем проблема, и это было глупо.
В моих маршрутах Кино у меня была одна конечная точка следующим образом.
router.get('/:movieId', function(req, res) {
// Call tmdb.movieInfo()
});
И остальные конечные точки также начались с /
, следующее.
router.get('/popular', function(req, res) {
// Call tmdb.movieInfo()
});
Ясно, что это плохой дизайн и вызовет проблемы, так как /:movieId
будет вызван, когда передан действительный идентификатор фильма, но у меня также есть другие пункты, которые используют ключевые слова (точно такие же, как и TMDb), поэтому, когда я попробовал GET на /popular
, MovieDB внутренне вызывает API, как определено TMDb (/api/movie/popular
является допустимой конечной точкой для TMDb), и, следовательно, я получил результаты правильно.
Однако, если я сделаю GET на /genres
мой API подумал о слове genres
как /:movieId
, из-за идентичной подписи, и, поскольку такого идентификатора не существует, произошел сбой.
Теперь я исправил свою конечную точку как
router.get('/info/:movieId', function(req, res) {
// Call tmdb.movieInfo()
});
И все работает как положено.
Извлеченный урок, никогда не имейте одинаковых конечных точек, где используются значения параметров и ключевые слова.