No URL found for key=6666
If I find an entry in my cache server, then the FF content is now filled in with my JSON string and I just need to route my FF to a HandleHttpResponse processor with a 200 HTTP code. This way, the user will see the JSON string with related information.
Let’s continue with the “shortlink” part of the flow. First of all I use a RouteOnAttribute processor to check that the URL provided at:
/shortlink?url=
is valid given a regular expression. If not I display an error message to the user with the combination of ReplaceText processor and HandleHttpResponse processor (as explained above).
If the URL is valid, I want to generate a key associated to this URL.
Note: for this part, I made the choice to keep it really simple and there are a lot of possible improvements/optimizations.
I make the decision that the key will be a 4-digits number and I create this number using time manipulation with the expression language. With an UpdateAttribute processor, I generate a ‘key’ attribute:
Once the key is generated I use a FetchDistributedMapCache processor to check if this key is already used or not.
If yes, my FF now contains the associated JSON string. I use an EvaluateJsonPath processor to extract the creation date information from the JSON string and then I use a RouteOnAttribute processor to check if this creation date if below the threshold of 24 hours. If yes, I route my FF back to the UpdateAttribute processor to generate a new random key, if no, it means the key can be overwritten and I route my FF to the next steps.
Once I have a generated key that is free to use, I use a ReplaceText processor to construct my JSON string:
Then I store this information in the cache using a PutDistributedMapCache processor:
Note the “replace if present” property in case we are overwriting an already existing key that is too old. Then I just route my FF to a HandleHttpResponse processor with a 200 HTTP code to display to the user the JSON string.
As I said, this part is simple, there are a lot of possible improvements such as (but not limited to):
Have a text-based key with the possibility for the user to customize it in order to expand the number of possible shortened URL stored.
Use the cache server to store a sequence ID for the generated key in order to avoid randomness and possible loops in the flow.
Add the possibility to reuse the same key for two identical URLs to shorten.
Finally, let’s complete our use case with the last part of the flow: when a HTTP request is received which is not shortlink/admin.
The accessed URL is obtained using the FF attributes, and I can directly use a FetchDistributedMapCache processor:
If I don’t find any entry in my cache, I route the FF to a combination of ReplaceText and HandleHttpResponse processors to display an error message to the user with a 404 HTTP error code.
If I find a match, I use an EvaluateJsonPath processor to extract the counter value and the long URL from the JSON string retrieved in the cache. Then I first route my FF to a HandleHttpResponse processor with a 307 HTTP code (temporary redirection) and I add a HTTP header property to redirect the user to the corresponding URL:
Note: I use the 307 HTTP code to avoid my browser to cache the redirection and to perform the request each time I access my shortened URL.
I also route my FF to a ReplaceText processor in order to increment the count value in my JSON string and I use a PutDistributedMapCache processor to update the data in the cache.
That’s it! We now have a running URL shortener service with Apache NiFi. The flow is available as a template here. As always, feel free to comment and/or ask questions about this post.