React and Express iTunes Search API :: Error: Request failed with status code 404
React and Express iTunes Search API :: Error: Request failed with status code 404
我目前正在使用 API 创建 iTunes 搜索应用程序,但在尝试获取数据以组合结果组件时遇到困难。
在其他资源中,我参考了以下信息:
iTunes Search API
请看下面我的代码:
后端 - 控制器 - index.js
// Requiring Express.
const express = require("express");
// Requiring fetch from Node Fetch.
const fetch = require("node-fetch");
exports.getController =
("/search",
(req, res) => {
fetch(
`https://itunes.apple.com/search?term=${req.query.name}&limit=30&media=${req.query.type}`
)
.then((res) => res.json())
.then((results) => {
res.send(results);
});
});
后端 - 路由 - index.js
// Requiring Express.
const express = require("express");
// Requiring Router from Express.
const router = express.Router();
// Requiring controllers from the controllers folder's index.js.
const { getController } = require("../controllers/index.js");
router.get("/search", getController);
// Exporting controllers to server.js.
module.exports = router;
后端 - server.js
// Requiring Express.
const express = require("express");
// Requiring Morgan.
const morgan = require("morgan");
// Requiring CORS.
const cors = require("cors");
// Initializing express with variable "app".
const app = express();
// Requiring the routes index.js file.
const routes = require("./routes/index.js");
// Requiring Helmet.
const helmet = require("helmet");
/**
* Enabling App usages.
*/
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.json());
app.use(morgan("start"));
app.use(cors());
app.use(helmet());
app.use("/", routes);
const path = require("path");
if (process.env.NODE_ENV === "production") {
app.use(express.static("frontend/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "frontend", "build", "index.html"));
});
}
const PORT = process.env.PORT || 8080;
app.listen(PORT);
console.log(
"Navigate to http://localhost:8080/search. Server is listening on port",
PORT
);
app.use(function (err, req, res, next) {
console.log(err.stack);
res.status(500).send("Something broke!");
});
前端 - search.js
// Imported react libraries and hooks.
import React, { useState, useEffect } from "react";
import axios from "axios";
// Imported Link from React Router Dom.
import { Link } from "react-router-dom";
// Imported components from React Bootstrap.
import { Row, Dropdown, ButtonGroup, Button } from "react-bootstrap";
// Imported icons from FontAwesome.
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faSearch } from "@fortawesome/free-solid-svg-icons";
// Imported components.
import Results from "./results.js";
const Search = () => {
const [name, setName] = useState("");
const [type, setType] = useState("");
const [results, setResults] = useState([]);
const [favourites, setFavourites] = useState([]);
const addToFav = (fav) => {
setFavourites([...favourites, fav]);
};
useEffect(() => {
localStorage.setItem("Favourites", JSON.stringify(favourites));
}, [favourites]);
const submitSearch = (e) => {
e.preventDefault();
axios
.get(`/search/${name}/${type}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
})
.then((res) => {
const queryAdded = res.data.results;
setResults(queryAdded ? queryAdded : []);
})
.catch((err) => {
console.log(err);
});
};
let nameEntry = "";
const nameSubmit = (e) => {
const entry = e.target.value;
nameEntry = entry;
setName(nameEntry);
};
const categories = [
{ name: "MUSIC", value: "music" },
{ name: "MUSIC VIDEO", value: "musicVideo" },
{ name: "APPS", value: "software" },
{ name: "EBOOK", value: "ebook" },
{ name: "AUDIO BOOK", value: "audiobook" },
{ name: "PODCAST", value: "podcast" },
{ name: "MOVIES", value: "movie" },
{ name: "TV SHOW", value: "tvShow" },
{ name: "SHORT FILM", value: "shortFilm" },
];
return (
<div id="searchcontainer">
<div id="searchcontent">
<div id="searchinput">
<input
type="text"
placeholder="Search..."
name="name"
onChange={nameSubmit}
/>
<Link to={`/search`}>
<button id="searchbutton" type="submit" onClick={submitSearch}>
<FontAwesomeIcon icon={faSearch} title="Search" />
</button>
</Link>
</div>
<Dropdown as={ButtonGroup}>
<Button variant="info" size="sm">
CATEGORIES
</Button>
<Dropdown.Toggle
split
variant="info"
id="dropdown-split-basic"
drop="bottom"
/>
<Dropdown.Menu>
{categories.map((category, i) => (
<Dropdown.Item
as="button"
key={i}
id="searchcategories"
value={category.value}
checked={type === category.value}
onChange={(e) => setType(e.currentTarget.value)}
>
{category.name}
</Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
</div>
<div className="search-page">
<div className="container-fluid">
<Row md={5}>
{results.length !== 0 ? (
results.map((content) => (
<Results addToFav={addToFav} content={content} />
))
) : (
<h1></h1>
)}
</Row>
</div>
</div>
</div>
);
};
// Exported search.js to landing.js.
export default Search;
不幸的是,我收到以下错误:
我已经尝试了几件事,但似乎没有任何效果。事实上,我认为我的所有操作可能会使代码过于复杂。
如果有人愿意提供任何帮助,我将不胜感激。
有几个问题:
- 当前,您正在向 React 应用地址 (http://localhost:3000) 发送请求。您需要将请求发送到 NodeJS 应用程序。
axios
.get(`http://localhost:8080/search/${name}/${type}`, { // add the address of NodeJS application
- 如果你想发送这样的数据
/search/${name}/${type}
,那么在后台,req.query
是行不通的。您应该使用 req.params
并相应地更改您的路线。阅读 Express 文档 here。或者,您需要将前端部分的 URL 更改为 /search/?name={name}&type=${type}
- 最后,在日志中,URL 是
http://localhost:3000/search/korn
。缺少 1 个参数,这可能会给您的后端应用程序带来错误的 URL。
https://itunes.apple.com/search?term=${req.query.name}&limit=30&media=${req.query.type}
可能会导致 https://itunes.apple.com/search?term=korn&limit=30&media=undefined
您需要一种机制来处理丢失的数据。
我目前正在使用 API 创建 iTunes 搜索应用程序,但在尝试获取数据以组合结果组件时遇到困难。
在其他资源中,我参考了以下信息: iTunes Search API
请看下面我的代码:
后端 - 控制器 - index.js
// Requiring Express.
const express = require("express");
// Requiring fetch from Node Fetch.
const fetch = require("node-fetch");
exports.getController =
("/search",
(req, res) => {
fetch(
`https://itunes.apple.com/search?term=${req.query.name}&limit=30&media=${req.query.type}`
)
.then((res) => res.json())
.then((results) => {
res.send(results);
});
});
后端 - 路由 - index.js
// Requiring Express.
const express = require("express");
// Requiring Router from Express.
const router = express.Router();
// Requiring controllers from the controllers folder's index.js.
const { getController } = require("../controllers/index.js");
router.get("/search", getController);
// Exporting controllers to server.js.
module.exports = router;
后端 - server.js
// Requiring Express.
const express = require("express");
// Requiring Morgan.
const morgan = require("morgan");
// Requiring CORS.
const cors = require("cors");
// Initializing express with variable "app".
const app = express();
// Requiring the routes index.js file.
const routes = require("./routes/index.js");
// Requiring Helmet.
const helmet = require("helmet");
/**
* Enabling App usages.
*/
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.json());
app.use(morgan("start"));
app.use(cors());
app.use(helmet());
app.use("/", routes);
const path = require("path");
if (process.env.NODE_ENV === "production") {
app.use(express.static("frontend/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "frontend", "build", "index.html"));
});
}
const PORT = process.env.PORT || 8080;
app.listen(PORT);
console.log(
"Navigate to http://localhost:8080/search. Server is listening on port",
PORT
);
app.use(function (err, req, res, next) {
console.log(err.stack);
res.status(500).send("Something broke!");
});
前端 - search.js
// Imported react libraries and hooks.
import React, { useState, useEffect } from "react";
import axios from "axios";
// Imported Link from React Router Dom.
import { Link } from "react-router-dom";
// Imported components from React Bootstrap.
import { Row, Dropdown, ButtonGroup, Button } from "react-bootstrap";
// Imported icons from FontAwesome.
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faSearch } from "@fortawesome/free-solid-svg-icons";
// Imported components.
import Results from "./results.js";
const Search = () => {
const [name, setName] = useState("");
const [type, setType] = useState("");
const [results, setResults] = useState([]);
const [favourites, setFavourites] = useState([]);
const addToFav = (fav) => {
setFavourites([...favourites, fav]);
};
useEffect(() => {
localStorage.setItem("Favourites", JSON.stringify(favourites));
}, [favourites]);
const submitSearch = (e) => {
e.preventDefault();
axios
.get(`/search/${name}/${type}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
})
.then((res) => {
const queryAdded = res.data.results;
setResults(queryAdded ? queryAdded : []);
})
.catch((err) => {
console.log(err);
});
};
let nameEntry = "";
const nameSubmit = (e) => {
const entry = e.target.value;
nameEntry = entry;
setName(nameEntry);
};
const categories = [
{ name: "MUSIC", value: "music" },
{ name: "MUSIC VIDEO", value: "musicVideo" },
{ name: "APPS", value: "software" },
{ name: "EBOOK", value: "ebook" },
{ name: "AUDIO BOOK", value: "audiobook" },
{ name: "PODCAST", value: "podcast" },
{ name: "MOVIES", value: "movie" },
{ name: "TV SHOW", value: "tvShow" },
{ name: "SHORT FILM", value: "shortFilm" },
];
return (
<div id="searchcontainer">
<div id="searchcontent">
<div id="searchinput">
<input
type="text"
placeholder="Search..."
name="name"
onChange={nameSubmit}
/>
<Link to={`/search`}>
<button id="searchbutton" type="submit" onClick={submitSearch}>
<FontAwesomeIcon icon={faSearch} title="Search" />
</button>
</Link>
</div>
<Dropdown as={ButtonGroup}>
<Button variant="info" size="sm">
CATEGORIES
</Button>
<Dropdown.Toggle
split
variant="info"
id="dropdown-split-basic"
drop="bottom"
/>
<Dropdown.Menu>
{categories.map((category, i) => (
<Dropdown.Item
as="button"
key={i}
id="searchcategories"
value={category.value}
checked={type === category.value}
onChange={(e) => setType(e.currentTarget.value)}
>
{category.name}
</Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
</div>
<div className="search-page">
<div className="container-fluid">
<Row md={5}>
{results.length !== 0 ? (
results.map((content) => (
<Results addToFav={addToFav} content={content} />
))
) : (
<h1></h1>
)}
</Row>
</div>
</div>
</div>
);
};
// Exported search.js to landing.js.
export default Search;
不幸的是,我收到以下错误:
我已经尝试了几件事,但似乎没有任何效果。事实上,我认为我的所有操作可能会使代码过于复杂。
如果有人愿意提供任何帮助,我将不胜感激。
有几个问题:
- 当前,您正在向 React 应用地址 (http://localhost:3000) 发送请求。您需要将请求发送到 NodeJS 应用程序。
axios
.get(`http://localhost:8080/search/${name}/${type}`, { // add the address of NodeJS application
- 如果你想发送这样的数据
/search/${name}/${type}
,那么在后台,req.query
是行不通的。您应该使用req.params
并相应地更改您的路线。阅读 Express 文档 here。或者,您需要将前端部分的 URL 更改为/search/?name={name}&type=${type}
- 最后,在日志中,URL 是
http://localhost:3000/search/korn
。缺少 1 个参数,这可能会给您的后端应用程序带来错误的 URL。https://itunes.apple.com/search?term=${req.query.name}&limit=30&media=${req.query.type}
可能会导致https://itunes.apple.com/search?term=korn&limit=30&media=undefined
您需要一种机制来处理丢失的数据。