There is a way to initialize an Arduino String with a given memory length: see reserve() method. It will generally greatly reduce or entirely eliminate memory fragmentation, if you can afford reserving a sufficient amount of memory in advance.
Just keep in mind that this is a "soft" boundary: once your string gets longer than the reserved amount, String will quietly resume reallocating memory with all those typical consequences.
It is just not clear what you plan to do if the pre-reserved amount of memory proves to be insufficient. Fall back to "memory fragmentation"? Anything more elaborate than that will be pretty much as complex as performing manual management of a char[] array.
All the functionalities you requested are present for char[] arrays as well, might just require a few more lines of code. And it is not clear why one might "need" comparisons to be == specifically.
This might also be an XY problem. Why are you trying to concatenate all these requests in memory? What are you planning to do with them once you are done "concatenating"?