Reputation: 427
every now and then I come to this question, google around for some time without getting a definitive answer and let it be.
Problem:
I want to update an existing resource, but the logic how this update works is on the backend side.
Let's assume a product should only be visible for a set time. Keeping it simple. The time "from" is stored in the database along the product data: product.visibleFromDate and the duration (eg. 30 days) is just a variable or configured somewhere (not in DB).
Now I want to call the backend telling it to update the visibleFromDate to "now": /api/product/:id/updatevisibility In this case I don't want to send a body because the server should determine what value "now" really is.
I actually don't really care if the server answers with the updated resource or no content.
HTTP Request
GET
POST
PUT
PATCH
Of course I could just send an empty object, the whole resource or some nonsense and ignore it on the backend side, but still I feel like I am missing this "trigger" type of requests which only need the type of resource, id and action.
Upvotes: 6
Views: 3029
Reputation: 3014
my other answer did not satisfy you, so i will try the same but from a different viewpoint.
you are data engineer:
{}
to be consistentyou are an operational backend engineer.
curl
won't send a body if you don't give one, for example.semantics are not hard-coded rules. they are there to guide you and keep you in the line as much as possible. the problem is that they don't have solid implementation details. they are also "opinions" of a group of people which has pretty fine shape anyone can accept.
PS: It is said, "POST can be used on an already-existing data to append". sure it is, but the question in scope asks about changing a field, not creating a new one.
Upvotes: -1
Reputation: 3014
You would definitely want POST over GET for authorization/authentication purposes.
You don't need to have a body for a POST request. Your endpoint will just listen for a request, it will extract :id
, and then run your time update function.
PUT and PATCH are semantic equivalents to POST. Unless you programmed the backend to differentiate them, there won't be any difference. You don't even need them at all.
A single empty-body POST will be enough for your endpoint. But you may consider using empty-body PATCH just as a meaningful endpoint. In both cases, your backend will extract the :id
and then just run the same function (after auth* if any)
EDIT: Seems not all people can grasp what I have, so here are a working nodejs/express backend and curl requests to use. you don't need a request body, and all behave the same, except semantics and security over GET.
this is the server code:
const express = require('express');
const app = express();
const port = 3000
const updatetime = async (id)=>{
let newdate=Date.now();
console.log(`updating resource ${id} to have a new date ${newdate}`);
return Promise.resolve("done")
}
const processrequest=async (req, res) => {
console.log(req.method);
console.log(req.headers);
console.log(req.headers.authorization);
console.log(req.body)
console.log(req.params)
try{
let result=await updatetime(req.params.id);
console.log(result);
res.status(200).send("time updated")
}catch{
res.status(500).send("something went wrong")
}
}
app.get( '/:id/updatetime', (req, res) => processrequest(req,res))
app.post( '/:id/updatetime', (req, res) => processrequest(req,res))
app.put( '/:id/updatetime', (req, res) => processrequest(req,res))
app.patch('/:id/updatetime', (req, res) => processrequest(req,res))
app.listen(port, () => {
console.log(`listening on port ${port}`)
})
test all endpoint without a body, all works because magic:
curl -X GET -H "Authorization: Basic" localhost:3000/123qwe/updatetime
time updated
curl -X POST -H "Authorization: Basic" localhost:3000/123qwe/updatetime
time updated
curl -X PUT -H "Authorization: Basic" localhost:3000/123qwe/updatetime
time updated
curl -X PATCH -H "Authorization: Basic" localhost:3000/123qwe/updatetime
time updated
server output for all request types are the same because it is just a magic(!) that is developers' choice of implementation:
listening on port 3000
GET/POST/PUt/PATCH
{
host: 'localhost:3000',
'user-agent': 'curl/7.78.0',
accept: '*/*',
authorization: 'Basic'
}
Basic
undefined
{ id: '123qwe' }
updating resource 123qwe to have a new date 1656495470330
done
Upvotes: 1
Reputation: 566
You are not required to pass a body in a request (Although the specification says so), PATCH will be your best option here since semantically it is updating an “part of existing resource” while PUT is meant for "updating the entire resource".
Upvotes: 0
Reputation: 1734
Depending on the mutability of the data it should either be POST(immutable) or PATCH(mutable). It doesn't depend on what You're sending or not sending.
If You really want to do it by the book then you should send a '{}'
when there are no fields to send. If any is added later you will just add it like '{"duration":"30"}'
Upvotes: 1