DTP is the Deterministic Test Protocol. DTP works as an HTTP web server that can generate HTTP responses based on parameters provided in the request.
DTP is enabled by specifying an endpoint in the fakeOrigin configuration with a type of testing. The testing capabilities will then be available at an endpoint named after the id specified in the configuration of that endpoint. For example:
"endpoints": [
{
"id": "testing_endpoint",
"type": "testing"
}
]
can then be reached at http://host:port/testing_endpoint/. Where you can then add any additional parameters to be tested as specified below.
Desired behavior is requested via url string, with the following format:
http://endpoint/~p.<type>/~<key0>.<val0>/~<key1>.<val1> ....
Options also passable via custom request header:
X-Dtp: ~<key0>.<val0>,~<key1>.<val1>
Or via query string:
http://endpoint/~p.<type>/&~<key0>.<val0>/~<key1>.<val1> ....
A special header, becomes Cache-Control
X-Dtp-Cc: public, max-age=200
This header explicitly tells DTP what Cache-Control headers to set for the response.
Currently implemented handler (has priority) (~h.):
Initial modifier:
Data types (~p.):
Modifiers (applies to Data types):
Forwarders (requires ~p.) (~f.):
Cache control:
Size: ~s - size value (int64)
~s.100 ~s.10M ~s.((1,30000r)25w,(100000,1000000r)45w,(1M)30w)
Random Seed: ~rnd - seed value (int64)
~rnd.42
Remove specified headers before processing: ~rmhdrs - List of headers
~rmhdrs.Range
Status Code: ~sc - any valid http status code value
~sc.502
HTTP Payload: ~payload - any simple string
~payload.Hello-World
Base 64 Mime Encoded Payload: ~payload64 - a base64 mime encoded payload string
~payload64.SGVsbG8sIFdvcmxkCg== (Hello, World\n)
Specifying byte position for event (very useful for range requests, EvalNumber): ~posevt:
~f.posevt.1200000.close ~f.posevt.1048577.sc.416 ~f.posevt.1000001.etags.foo.bar
Delay: ~delay- golang parseable delay applied to each block Read request, NOT the First block
~f.delay.250ms
Add Headers (can be combined):
~hdr - dot separated pairs
~hdr.Foo.Bar ~hdr.Foo.Faz.Bar.Baz
~hdr64 - dot separated pairs, with contents base64 mime encoded
~hdr64.Cache-Control.bWF4LWFnZT00Mg== (max-age=42)
Max Age (Seconds): ~ui - Last-Modified: (UTC / ui) * ui
~ui.2000
~lm - Last-Modified in UTC seconds. This either needs ~hdr.Cache-Control, ~hdr64.CacheControl or X-Dtp-Cc: header
~lm.1586266180
~etag - Add an etag header, autogen if blank/empty or as specified
~etag.foo ~etag
~cksum_req - Standalone option which will md5sum the request header as X-Request-Header-Cksum
500 MB plain text response:
curl "http://endpoint/~p.txt/~s.500M/"
Cacheable url that cycles every aligned 2000s (Last Modifed, Max-Age, etc):
curl "http://endpoint/~p.bin/~s.1G/&~ui.2000/"
Sample range call given (transfer 6 bytes then fail):
curl "http://endpoint/~p.txt/~f.posevt/~s.2M/&~posevt.1000005.close/" -r 999999-1049100
Slice sample call given slice block 1000000 (1 byte then 416 server response):
curl "http://endpoint/~p.txt/~f.posevt/~s.2M/&~posevt.1049076.sc.416/" -r 999999-1049100
Slice sample call given slice block 1000000 (transfer 6 bytes then change etag):
curl "http://endpoint/~p.txt/~s.2M/a&~f.posevt.1000005.etags.foo.bar/" -r 999999-1049100
Sample per 32k block delay parameter, not the first block:
curl "http://endpoint/~p.txt/~s.2M/&~f.delay.100ms/" -r 999999-1049100
Sample last modified header:
curl "http://endpoint/~p.txt/~s.1024/~hdr.foo.bar.Next-Modified.RnJpLCAwNyBGZWIgMjAyMCAxNTowNjo0MCBHTVQ=" results in return headers: Foo: bar Next-Modified: RnJpLCAwNyBGZWIgMjAyMCAxNTowNjo0MCBHTVQ=
curl "http://endpoint/~p.txt/~s.1024/~hdr64.Next-Modified.RnJpLCAwNyBGZWIgMjAyMCAxNTowNjo0MCBHTVQ=" results in return header: Next-Modified: Fri, 07 Feb 2020 15:06:40 GMT
DTP may be profiled if so desired. If profiling is enabled, then DTP endpoints become available under:
http://endpoint/debug/pprof/cmdline
http://endpoint/debug/pprof/profile
http://endpoint/debug/pprof/symbol
http://endpoint/debug/pprof/trace
Current DTP configuration may be dumped via endpoint:
Header logging can be flipped on or off with the following:
http://endpoint/config?request_headers=true
http://endpoint/config?response_headers=false
http://endpoint/config?all_headers=true
The “type” identifies which “plugin” to use for handling a response. This allows developers to drop in their own custom plugins. A developer needs to include a per connection function with signature:
func(http.ResponseWriter, *http.Request, map[string]string)
the file needs to register the function as:
func init() {
GlobalHandlerFuncs[`type`] = TypeFunc
}
A simple example is in “type_hijack.go” An example curl might be:
curl -v "http://endpoint/~h.hijack/&~payload.HelloWorld"
or
curl -v "http://endpoint/~h.hijack/&~payload64.SGVsbG8gV29ybGQK" (Hello World with a \n at the the end)
With debug turned on you should see the message “Connection hijacked” displayed.
Another example is type_gen3s.go