NodeJS와 Restify를 사용하여 RESTful API 설계
RESTful API는 Resources 및 Representations라는 두 가지 주요 개념으로 구성됩니다. 리소스는 데이터와 연결되거나 URI로 식별되는 모든 개체일 수 있으며(여러 URI가 동일한 리소스를 참조할 수 있음) HTTP 메서드를 사용하여 조작할 수 있습니다. 표현은 리소스가 표시되는 방식입니다. 이 튜토리얼에서는 RESTful API 디자인에 대한 몇 가지 이론적 정보를 다루고 NodeJS를 사용하여 샘플 블로그 애플리케이션 API를 구현합니다.
리소스
RESTful API에 적합한 리소스를 선택하는 것은 디자인의 중요한 부분입니다. 먼저 비즈니스 도메인을 분석한 다음 비즈니스 요구 사항과 관련하여 사용할 리소스의 양과 유형을 결정해야 합니다. 블로그 API를 설계하는 경우 Posts, Users 및 Comments를 사용할 수 있습니다. 다음은 리소스 이름이며 이와 관련된 데이터는 리소스 자체입니다.
으아아아자원 동사
필요한 자원을 파악한 후 자원 운영을 진행할 수 있습니다. 여기서의 작업은 HTTP 메서드를 나타냅니다. 예를 들어 기사를 작성하려면 다음 요청을 할 수 있습니다.
으아아아동일하게 다음 요청을 하면 기존 기사를 볼 수 있습니다.
으아아아기존 기사를 업데이트하는 것은 어떻습니까? 나는 당신이 말하는 것을 들었습니다:
페이로드를 사용하여 /articles/update/123456789012에 또 다른 POST 요청을 할 수 있습니다.
더 좋을 수도 있지만 URI가 점점 더 복잡해지고 있습니다. 앞서 말했듯이 작업은 HTTP 메서드를 참조할 수 있습니다. 즉, update 작업을 URI에 넣는 대신 HTTP 메서드에서 선언하는 것입니다. 예:
으아아아그런데 이 예에서는 태그 및 카테고리 필드가 표시됩니다. 필수 필드일 필요는 없습니다. 공백으로 두고 나중에 설정할 수 있습니다.
기사가 오래되면 삭제해야 하는 경우도 있습니다. 이 경우 /articles/123456789012에 대한 DELETEHTTP 요청을 사용할 수 있습니다.
HTTP 방법은 표준 개념입니다. 이를 작업으로 사용하면 간단한 URI를 갖게 되며 이 간단한 API는 행복한 소비자를 얻는 데 도움이 됩니다.
글에 댓글을 삽입하고 싶다면 어떻게 해야 하나요? 기사를 선택하고 선택한 기사에 새 댓글을 추가할 수 있습니다. 이 문을 사용하면 다음 요청을 사용할 수 있습니다.
으아아아위 형태의 리소스를 하위 리소스라고 합니다. 댓글은 기사의 하위 리소스입니다. 위의 Comments 페이로드는 Articles의 하위 항목으로 데이터베이스에 삽입됩니다. 때로는 서로 다른 URI가 동일한 리소스를 참조하는 경우도 있습니다. 예를 들어 특정 댓글을 보려면 다음을 사용할 수 있습니다.
으아아아또는:
으아아아버전 관리
일반적으로 API 기능은 소비자에게 새로운 기능을 제공하기 위해 자주 변경됩니다. 이 경우 동일한 API의 두 가지 버전이 동시에 존재할 수 있습니다. 이 두 기능을 분리하려면 버전 제어를 사용할 수 있습니다. 버전 관리는 두 가지 형태로 제공됩니다
-
URI 버전: URI에 버전 번호를 제공할 수 있습니다. 예를 들어
/v1.1/articles/123456789012
. - 헤더 버전: 헤더에 버전 번호를 제공하고 URI를 변경하지 마세요. 예:
사실 버전은 리소스의 개념이 아닌 리소스의 표현만 변경합니다. 따라서 URI 구조를 변경할 필요가 없습니다. v1.1에서는 Article에 새로운 필드가 추가되었을 수 있습니다. 그러나 여전히 기사를 반환합니다. 두 번째 옵션에서는 URI가 단순하게 유지되며 소비자는 클라이언트 구현에서 해당 URI를 변경할 필요가 없습니다.
소비자가 버전 번호를 제공하지 않는 상황에 대비한 전략을 설계하는 것이 매우 중요합니다. 버전이 제공되지 않으면 오류가 발생하거나 첫 번째 버전으로 응답을 반환할 수 있습니다. 최신 안정 버전을 기본 버전으로 사용하는 경우 소비자의 클라이언트 구현에 많은 버그가 있을 수 있습니다.
는
을 의미합니다.는 API가 리소스를 표시하는 방식을 나타냅니다. API 엔드포인트를 호출하면 리소스가 반환됩니다. 리소스는 XML, JSON 등 모든 형식이 될 수 있습니다. 새로운 API를 설계하는 경우 JSON을 사용하는 것이 가장 좋습니다. 그러나 XML 응답을 반환하는 기존 API를 업데이트하는 경우 JSON 응답에 다른 버전을 제공할 수 있습니다.
RESTful API 설계에 대한 충분한 이론적 정보. Restify를 사용하여 블로그 API를 설계하고 구현하여 실제 사용법을 살펴보겠습니다.
블로그 REST API
디자인
RESTful API를 설계하려면 비즈니스 도메인을 분석해야 합니다. 그런 다음 리소스를 정의할 수 있습니다. Blog API에는 다음이 필요합니다.
- 만들기, 업데이트, 삭제, 보기 기사
-
특정 기사에 대한 댓글 작성, 업데이트, 삭제, 보기, 댓글
-
사용자 생성, 업데이트, 삭제, 보기
이 API에서는 기사나 댓글을 작성하기 위해 사용자를 인증하는 방법을 다루지 않습니다. 인증 부분에 대해서는 AngularJS 및 NodeJS에 대한 토큰 기반 인증 튜토리얼을 참조할 수 있습니다.
리소스 이름이 준비되었습니다. 리소스 작업은 간단한 CRUD입니다. API 개요는 아래 표를 참조하세요.
리소스 이름 | HTTP 동사 | HTTP 방식 |
---|---|---|
기사 | 기사 작성 기사 업데이트 기사 삭제 기사 보기 |
POST /articles with Payload PUT /articles/123 with Payload DELETE /articles/123 GET /article/123 |
댓글 | 댓글 작성 댓글 업데이트 댓글 삭제 댓글 보기
|
POST /articles/123/comments with payload PUT /comments/123 with payload DELETE /comments/123 GET /comments/123 |
사용자 | 사용자 만들기 사용자 업데이트 사용자 삭제 사용자 보기 |
POST /users with Payload PUT /users/123 with Payload DELETE /users/123 GET /users/123 |
项目设置
在此项目中,我们将使用 NodeJS 和 Restify。资源将保存在 MongoDB 数据库中。首先,我们可以在Restify中将资源定义为模型。
文章
var mongoose = require("mongoose"); var Schema = mongoose.Schema; var ArticleSchema = new Schema({ title: String, slug: String, content: String, author: { type: String, ref: "User" } }); mongoose.model('Article', ArticleSchema);
评论
var mongoose = require("mongoose"); var Schema = mongoose.Schema; var CommentSchema = new Schema({ text: String, article: { type: String, ref: "Article" }, author: { type: String, ref: "User" } }); mongoose.model('Comment', CommentSchema);
用户
不会对用户资源进行任何操作。我们假设我们已经知道能够对文章或评论进行操作的当前用户。
您可能会问这个猫鼬模块来自哪里。它是作为 NodeJS 模块编写的最流行的 MongoDB ORM 框架。该模块包含在项目的另一个配置文件中。
现在我们可以为上述资源定义 HTTP 动词。您可以看到以下内容:
var restify = require('restify') , fs = require('fs') var controllers = {} , controllers_path = process.cwd() + '/app/controllers' fs.readdirSync(controllers_path).forEach(function (file) { if (file.indexOf('.js') != -1) { controllers[file.split('.')[0]] = require(controllers_path + '/' + file) } }) var server = restify.createServer(); server .use(restify.fullResponse()) .use(restify.bodyParser()) // Article Start server.post("/articles", controllers.article.createArticle) server.put("/articles/:id", controllers.article.updateArticle) server.del("/articles/:id", controllers.article.deleteArticle) server.get({path: "/articles/:id", version: "1.0.0"}, controllers.article.viewArticle) server.get({path: "/articles/:id", version: "2.0.0"}, controllers.article.viewArticle_v2) // Article End // Comment Start server.post("/comments", controllers.comment.createComment) server.put("/comments/:id", controllers.comment.viewComment) server.del("/comments/:id", controllers.comment.deleteComment) server.get("/comments/:id", controllers.comment.viewComment) // Comment End var port = process.env.PORT || 3000; server.listen(port, function (err) { if (err) console.error(err) else console.log('App is ready at : ' + port) }) if (process.env.environment == 'production') process.on('uncaughtException', function (err) { console.error(JSON.parse(JSON.stringify(err, ['stack', 'message', 'inner'], 2))) })
在此代码片段中,首先迭代包含控制器方法的所有控制器文件,并初始化所有控制器,以便执行对 URI 的特定请求。之后,为基本的CRUD操作定义了具体操作的URI。 Article 上的其中一项操作也有版本控制。
例如,如果您在 Accept-Version 标头中将版本声明为 2
,则将执行 viewArticle_v2
。 viewArticle
和 viewArticle_v2
都执行相同的工作,显示资源,但它们以不同的格式显示文章资源,正如您在 中看到的那样title
字段如下。最后,服务器在特定端口上启动,并应用一些错误报告检查。我们可以继续使用控制器方法对资源进行 HTTP 操作。
article.js
var mongoose = require('mongoose'), Article = mongoose.model("Article"), ObjectId = mongoose.Types.ObjectId exports.createArticle = function(req, res, next) { var articleModel = new Article(req.body); articleModel.save(function(err, article) { if (err) { res.status(500); res.json({ type: false, data: "Error occured: " + err }) } else { res.json({ type: true, data: article }) } }) } exports.viewArticle = function(req, res, next) { Article.findById(new ObjectId(req.params.id), function(err, article) { if (err) { res.status(500); res.json({ type: false, data: "Error occured: " + err }) } else { if (article) { res.json({ type: true, data: article }) } else { res.json({ type: false, data: "Article: " + req.params.id + " not found" }) } } }) } exports.viewArticle_v2 = function(req, res, next) { Article.findById(new ObjectId(req.params.id), function(err, article) { if (err) { res.status(500); res.json({ type: false, data: "Error occured: " + err }) } else { if (article) { article.title = article.title + " v2" res.json({ type: true, data: article }) } else { res.json({ type: false, data: "Article: " + req.params.id + " not found" }) } } }) } exports.updateArticle = function(req, res, next) { var updatedArticleModel = new Article(req.body); Article.findByIdAndUpdate(new ObjectId(req.params.id), updatedArticleModel, function(err, article) { if (err) { res.status(500); res.json({ type: false, data: "Error occured: " + err }) } else { if (article) { res.json({ type: true, data: article }) } else { res.json({ type: false, data: "Article: " + req.params.id + " not found" }) } } }) } exports.deleteArticle = function(req, res, next) { Article.findByIdAndRemove(new Object(req.params.id), function(err, article) { if (err) { res.status(500); res.json({ type: false, data: "Error occured: " + err }) } else { res.json({ type: true, data: "Article: " + req.params.id + " deleted successfully" }) } }) }
您可以在下面找到 Mongoose 端基本 CRUD 操作的说明:
-
createArticle:这是对从请求正文发送的
articleModel
的简单保存操作。可以通过将请求正文作为构造函数传递给模型来创建新模型,例如vararticleModel = new Article(req.body)
。 -
viewArticle:为了查看文章详细信息,URL 参数中需要提供文章 ID。
findOne
带有 ID 参数足以返回文章详细信息。 -
updateArticle:文章更新是一个简单的查找查询并对返回的文章进行一些数据操作。最后,需要通过发出
save
命令将更新后的模型保存到数据库中。 -
deleteArticle:
findByIdAndRemove
是通过提供文章 ID 来删除文章的最佳方法。
上面提到的 Mongoose 命令只是通过 Article 对象进行静态方法,该对象也是 Mongoose 模式的引用。
comment.js
var mongoose = require('mongoose'), Comment = mongoose.model("Comment"), Article = mongoose.model("Article"), ObjectId = mongoose.Types.ObjectId exports.viewComment = function(req, res) { Article.findOne({"comments._id": new ObjectId(req.params.id)}, {"comments.$": 1}, function(err, comment) { if (err) { res.status(500); res.json({ type: false, data: "Error occured: " + err }) } else { if (comment) { res.json({ type: true, data: new Comment(comment.comments[0]) }) } else { res.json({ type: false, data: "Comment: " + req.params.id + " not found" }) } } }) } exports.updateComment = function(req, res, next) { var updatedCommentModel = new Comment(req.body); console.log(updatedCommentModel) Article.update( {"comments._id": new ObjectId(req.params.id)}, {"$set": {"comments.$.text": updatedCommentModel.text, "comments.$.author": updatedCommentModel.author}}, function(err) { if (err) { res.status(500); res.json({ type: false, data: "Error occured: " + err }) } else { res.json({ type: true, data: "Comment: " + req.params.id + " updated" }) } }) } exports.deleteComment = function(req, res, next) { Article.findOneAndUpdate({"comments._id": new ObjectId(req.params.id)}, {"$pull": {"comments": {"_id": new ObjectId(req.params.id)}}}, function(err, article) { if (err) { res.status(500); res.json({ type: false, data: "Error occured: " + err }) } else { if (article) { res.json({ type: true, data: article }) } else { res.json({ type: false, data: "Comment: " + req.params.id + " not found" }) } } }) }
当您向某个资源 URI 发出请求时,控制器中声明的相关函数将被执行。控制器文件中的每个函数都可以使用 req 和 res 对象。这里的评论资源是文章的子资源。 所有的查询操作都是通过Article模型进行的,以便找到子文档并进行必要的更新。但是,每当您尝试查看 Comment 资源时,即使 MongoDB 中没有集合,您也会看到一个 Comment 资源。
其他设计建议
- 选择易于理解的资源,以便消费者轻松使用。
- 让业务逻辑由消费者实现。例如,文章资源有一个名为 slug 的字段。 消费者不需要将此详细信息发送到 REST API。这种 slug 策略应该在 REST API 端进行管理,以减少 API 和消费者之间的耦合。消费者只需要发送标题详细信息,您就可以在REST API端根据您的业务需求生成slug。
- 为您的 API 端点实施授权层。未经授权的消费者可以访问属于其他用户的受限数据。在本教程中,我们没有介绍用户资源,但您可以参阅使用 AngularJS 和 NodeJS 进行基于令牌的身份验证,以获取有关 API 身份验证的更多信息。
- 用户 URI 而不是查询字符串。
/articles/123
(好),/articles?id=123
(差)。 - 不保留状态;始终使用即时输入/输出。
- 使用名词来表示您的资源。您可以使用 HTTP 方法来操作资源。
最后,如果您按照这些基本规则设计 RESTful API,您将始终拥有一个灵活、可维护、易于理解的系统。
위 내용은 NodeJS와 Restify를 사용하여 RESTful API 설계의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











프론트 엔드 개발시 프론트 엔드 열지대 티켓 인쇄를위한 자주 묻는 질문과 솔루션, 티켓 인쇄는 일반적인 요구 사항입니다. 그러나 많은 개발자들이 구현하고 있습니다 ...

기술 및 산업 요구에 따라 Python 및 JavaScript 개발자에 대한 절대 급여는 없습니다. 1. 파이썬은 데이터 과학 및 기계 학습에서 더 많은 비용을 지불 할 수 있습니다. 2. JavaScript는 프론트 엔드 및 풀 스택 개발에 큰 수요가 있으며 급여도 상당합니다. 3. 영향 요인에는 경험, 지리적 위치, 회사 규모 및 특정 기술이 포함됩니다.

JavaScript는 현대 웹 개발의 초석이며 주요 기능에는 이벤트 중심 프로그래밍, 동적 컨텐츠 생성 및 비동기 프로그래밍이 포함됩니다. 1) 이벤트 중심 프로그래밍을 사용하면 사용자 작업에 따라 웹 페이지가 동적으로 변경 될 수 있습니다. 2) 동적 컨텐츠 생성을 사용하면 조건에 따라 페이지 컨텐츠를 조정할 수 있습니다. 3) 비동기 프로그래밍은 사용자 인터페이스가 차단되지 않도록합니다. JavaScript는 웹 상호 작용, 단일 페이지 응용 프로그램 및 서버 측 개발에 널리 사용되며 사용자 경험 및 크로스 플랫폼 개발의 유연성을 크게 향상시킵니다.

동일한 ID로 배열 요소를 JavaScript의 하나의 객체로 병합하는 방법은 무엇입니까? 데이터를 처리 할 때 종종 동일한 ID를 가질 필요가 있습니다 ...

Console.log 출력의 차이의 근본 원인에 대한 심층적 인 논의. 이 기사에서는 Console.log 함수의 출력 결과의 차이점을 코드에서 분석하고 그에 따른 이유를 설명합니다. � ...

이 기사에서 시차 스크롤 및 요소 애니메이션 효과 실현에 대한 토론은 Shiseido 공식 웹 사이트 (https://www.shiseido.co.jp/sb/wonderland/)와 유사하게 달성하는 방법을 살펴볼 것입니다.

JavaScript를 배우는 것은 어렵지 않지만 어려운 일입니다. 1) 변수, 데이터 유형, 기능 등과 같은 기본 개념을 이해합니다. 2) 마스터 비동기 프로그래밍 및 이벤트 루프를 통해이를 구현하십시오. 3) DOM 운영을 사용하고 비동기 요청을 처리합니다. 4) 일반적인 실수를 피하고 디버깅 기술을 사용하십시오. 5) 성능을 최적화하고 모범 사례를 따르십시오.

프론트 엔드에서 VSCODE와 같은 패널 드래그 앤 드롭 조정 기능의 구현을 탐색하십시오. 프론트 엔드 개발에서 VSCODE와 같은 구현 방법 ...
