To make tidying of response bodies easier it would make sense to offer the option to externalize them from the tape file. For example the tape file itself would contain a body field with the file path of the data file with the body. The data file could then contain formatted data & use the correct file extension so it's easier to manually modify.
This may well help with memory problems as removing large response bodies from the YAML should make it significantly smaller to the point where it really shouldn't be a problem to read tape file into memory.
A couple of acceptance criteria for this:
I think to best implement this a reworking of some internals is required. This is an idea that's been in the back of my mind for some time but this requirement clarifies it a bit.
Currently implementations use a adapter pattern to make Netty / HttpClient request and response objects implement a common interface. A third implementation is the one used for storage on tape. This means there is a lot of copying going on, i.e. when playing back the stored response is copied to a real Netty / HttpClient response, when recording the wrapped Netty / HttpClient response is copied to a storable version.
What I'd like to have is a more layered approach. When recording the adapter class should be responsible for populating the recorded response. That would allow different strategies for response body storage and efficient writing of HTTP response content directly out to file rather than via an in-memory byte array as currently. It would be easy to support chunked responses by just appending to the file.
The current Request and Response interfaces are implemented by Netty and HttpClient adapters. The purpose of those interfaces needs to be clarified. Crucially Request is essentially read-only while Response is read-write. I don't think it makes sense for the tape representations (current RecordedRequest and RecordedResponse) to implement those interfaces – they're for the adapters to external models. It might make sense to separate a read model of response from a write model. The former is used to read a "real" response to create a recording and the latter for playing back an existing recording. Mixing those two functions up muddies the responsibilities of the adapter classes.
The play and record methods on Tape should be responsible for writing Betamax specific headers to the "real" response (at least the X-Betamax header, maybe not Via as that needs to go on requests as well which doesn't feel like the tape's responsibility). It should also handle content encoding and charsets which would remove some existing duplication from the code and ensure consistency across implementations. It's also a better separation of concerns – the response adapters shouldn't care whether the tape wants encoded or decoded content, that's up to the tape to handle.
#59 dumb proof of concept implementation
#59 write body to correct root directory
#59 writes the body out to tmpdir rather than tape root
#59 refactor loader<->tape relationship so tape doesn't need unreason…
…able amount of context
#59 almost working
now writes to correct directory. Need to make filenames unique (indexed?)
#59 better separation of responsibilities around where files are kept
#59 refactored so much out of StorableTape there's no need for it any…
#59 extract MIME->file extension code out to utility class
#59 clean up some unnecessary code
#59 write file path to YAML relative to tape root
#59 read files in as well
#59 failing test for remaining functionality
need a good strategy for consistently naming the body files
#59 place response body files in a sub-directory
Use interaction index in body file name
#59 zero pad filename index