REST架构中如何实现文章草稿功能?HTTP方法该如何选择
Great question—handling drafts in REST can feel a bit nuanced, especially when your existing API uses non-standard method mappings (usually PUT is for updates and POST for creation, but we’ll work within your setup seamlessly!). Let’s break this down into two parts: picking the right HTTP method, and building a RESTful implementation.
First: Choosing the Right HTTP Method
Given your current workflow (PUT for creating published articles, POST for updating published articles), here’s how to map draft operations consistently:
- Creating a new draft (from scratch): Use
POSTto/articles/drafts. Why? POST is designed for non-idempotent resource creation where the client doesn’t specify the resource ID—perfect for a draft that hasn’t been promoted to a full article yet. This keeps it distinct from your PUT-based published article creation flow. - Updating an existing draft:
- If you’re overwriting the entire draft content, use
PUTto/articles/drafts/{draftId}(PUT is idempotent, so calling it multiple times gives the same result—ideal for full replacements). - If you’re only updating parts of the draft (like tweaking the title or adding a paragraph),
PATCHis more semantically correct. - If you want to stick strictly to your existing update pattern (using POST for published articles), you can also use POST to
/articles/drafts/{draftId}—just be explicit in your API docs about the behavior (e.g., "POST updates the draft content").
- If you’re overwriting the entire draft content, use
- Creating a draft from an existing published article: Use
PUTto/articles/{articleId}/draft(idempotent, since this overwrites any existing draft for that article) orPOSTto/articles/{articleId}/draftsif you want to save multiple draft versions for the same article.
Second: RESTful Implementation of Draft Functionality
There are two robust approaches, depending on your backend needs and how you want to track drafts:
Approach 1: Drafts as a State of the Article Resource
Treat drafts simply as a status attribute on your existing Article resource (with values like draft or published). This is the simplest setup if you don’t need to track multiple draft versions:
- Create a draft: Send a PUT request to
/articles(same as your published creation flow) but includestatus: "draft"in the request body. For extra clarity, you can use a query parameter like/articles?status=draftto separate draft and published creation endpoints. - Update a draft: Send a POST request to
/articles/{articleId}(matching your existing published update flow) and keep thestatusset to"draft". - Publish a draft: Send a POST request to
/articles/{articleId}/publish—this is a valid REST pattern for state transitions. Make sure this endpoint is idempotent (calling it multiple times doesn’t change the result after the first publish, e.g., it won’t republish or throw an error).
Approach 2: Drafts as Standalone Sub-Resources
If you need to track multiple draft versions per article or keep drafts completely separate from published content in your database:
- Create a new standalone draft: POST to
/draftswith the draft content. The API returns a uniquedraftId. - Update a draft: Use PUT to
/drafts/{draftId}for full overwrites, or PATCH for partial updates. - Link a draft to an existing article: POST to
/articles/{articleId}/drafts/{draftId}to associate the draft with a published article (useful if you’re editing an existing piece). - Publish a draft: POST to
/drafts/{draftId}/publish—this creates or updates the correspondingArticleresource with the draft content, and marks the draft aspublished(or archives it in your backend).
Key REST Principles to Stick To
- Resource orientation: Always treat drafts as either a state of articles or their own distinct resources—avoid vague, action-based endpoints like
/save-draft. - Idempotency: Use PUT for operations where repeated requests have the same effect (like overwriting a single draft), and POST for non-idempotent actions (like creating a new draft version).
- Consistency: Since your method mappings are non-standard, make sure your API documentation clearly explains each endpoint’s purpose and behavior to avoid confusion for other developers.
内容的提问来源于stack exchange,提问作者leciro

