Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1]
[0] https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope...
[1] https://aws.amazon.com/blogs/architecture/serving-content-us...
For the stated purpose, either function is fine:
With Lambda@Edge you'd use origin request if you were caching these paths, because your function would be called less often so your costs would be lower.
With CF Functions you can only do the pre-cache-lookup modification, so it will be called for every request, but the cost is much lower than Lambda@Edge so it may not matter, and maybe you were not caching these paths anyway in which case it's virtually identical.
Basically, using the Viewer Request trigger and modifying the URI there causes CloudFront to force a 301 to the user to the new URI, because it's for the viewer. Therefore, in the example of /api/users, if you modify the viewer to remove /api, CloudFront literally removes /api from your request URI, meaning the client accesses /api/users but the server instead sends you to /users (read: server returns 301 location: /users when you hit /api/users) because of your viewer rewrite. You end up hitting your frontend instead of your backend because in order for it to hit your backend, the viewer request has to have /api in it. Therefore you cannot strip it in the viewer request. You must do it in the origin request, which is not supported by CloudFront functions.