We have a REST API with an endpoint accepting JSON data from the client. One of the JSON fields is a URL that will be rendrered to other users as a hyperlink to a website page associated to the resource. Somewhere in the pipeline we needed to ensure the URL is valid (starts with
http(s)://, contains a domain from a whitelist, etc.).
So we designed the API such that it would accept only valid URLS, and return an error (400) when the URL is considered invalid. On the UI side, the user has to correct the URL until it is valid, the error message adapting to the error case (missing value, invalid domain, invalid format...).
Our product owner tested our implementation before going live, and had trouble with this simple approach. He typed in "facebook.com/foobar" and was expecting the URL to be valid. The error message was something along the lines of "Please enter a valid URL like https://www.example.com/xxxx". He was expecting (quite rightly) that the input field would accept anything a browser address bar would accept. The error message could have been clearer ("the URL should start with http(s)://"), but we agreed he was right and that in this case, user input should be fixed by our application before being saved.
Here we had 2 ideas:
- Either let the API correct the URL (prepend a default protocol) upon saving ;
- Or prepend the protocol on the client side, and don't touch the API validation.
I have a strong preference for the client-side method, because I believe a REST API should never alter user input silently (you never know what kind of client will consume your API, and silently modifying user input could have unexpected side-effects). The problem is I couldn't find any real-life example to back up my point of view.
On the contrary, one of my teammates (the one responsible for the fix) couldn't find any good reason to prefer one method over the other, and went for the API fix (mainly because it's much faster to implement, and you don't have to implement this behavior for each client using your API).
What do you think?