I have code that checks if the scanned qr code exist in the database and if it exist it will insert data into another table but I did it in the HTTP GET request, is this alright to do it this way or there are other ways to do it correctly?
In genereal it's not a good idea. There are exceptions however. An access log can be implemented with a database, GET being a safe http method should never change the resource, but access log is not the resource so that is ok.
If you need to integrate with some system that doesn't understand the semantics of http (PLCs i'm looking at you) you can be forced to do it, but it's not ideal.
You need to be aware there can be issues if not using the methods correctly. E.g. webbrowsers+crawlers will call these methods as part of preload or scraping because they know they are safe. Example of what can happen if you don't use the correct method
Side effects aside, for example, an exponential increase of entries in the DB due to bots, web crawlers or a (un)intended miss usage of the API, I can think in one that would worry me.
GET is supposed to be cacheable. Caching unsafe operations (those with side-effects) is something you will rarely see and it's for good reason. Makes the system hard or impossible to predict (depending on the eviction strategy) and harder to track too.
Unless you disable the cache between the server and the client, in such a case you end up realising that using
POST you achieve the same result without much less overhead.
Another issue is if your API is convenient for me. If your
GETis unsafe, I need to know. If your
GET complicates my developments then I might look for another API.
To me, the main problem with ignoring the semantics is not how we wrap our head around that idea, is how the rest of the world do it. For 99% of us (including browsers and HTTP clients developers), GET is safe, idempotent and cacheable, so that 99% feels comfortable calling GET as many times as necessary with no fear of breaking anything.1.
But it matters only if it matters. You have to find out if the issues mentioned here are feasible in your system. Even if they are a problem at all.
1: It might happen due to evil intentions, due to load tests or due to bugs in the client-side which cause your API to be bombed with countless
The most obvious problems are:
- The database could run out of space and cause downstream failures
- A failed attempt to insert into the database could cause the attempt to get the resource to fail (a more specific variation of the above)
- The response to another GET for the same resource could fail incorrectly due to the database change (for instance, you give one response to the first 100 requests and a different response to those after. And then you incorrectly update the database as having 100 requests on the first request).
There is nothing inherently wrong with doing an insertion a GET, but it can cause problems of both scale and logic, and it’s an obvious target for a misconception because others may assume that asking for that resource won’t change anything.
There are a couple of questions you need to ask yourself which weren't 100% clear when I read what you had written.
1. Non-existent QR codes: If a GET request is received for a QR code which is not in the database, does anything happen in the database? I think you are saying "No", which is safe. If you did do something (such as synthesise a new record for the new code), then that is unsafe because, as other answers have pointed out, you might get 10,000 random requests from a mad robot.
(In principle the same problem also exists with POST, but robots do not usually use POST unless they are specifically designed with malicious intent).
2. Repeated requests: The first time a GET request is received for a QR code in your database, you insert something into a separate table. What is inserted the second, third, fourth, fifth, sixth time? If the answer is "nothing", then you are safe. If the answer is "six records get inserted into the table", then you are at risk.
To amplify this point: I can imagine, for example, that you might have some physical products that have unique QR codes, and that those codes are sent to your server as part of a registration process. In that case you would probably only want to have one "registration details" entry per QR code. You could decide to accept the first GET for a given code and ignore the others, or you could decide that the most recent GET supersedes all the previous ones. Either of those approaches is safe, because either of them leads to a table which has at most one record per valid QR code.
Looking at it from a greater distance - with browser caches and so on - you are safe if, when a subsequent GET request is submitted to the same browser, it doesn't matter whether (a) the browser sends the request to the server and receives a response to it or (b) the browser sends nothing to the server and just uses the last remembered response.