Skip to content

ImpostorKeanu/replace-response-placeholders

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This is a fork of Caddy's replace_response module that supports runtime placeholder values. It's significantly less efficient than the original.

Note

Replacement configurations that use runtime placeholders must have the placeholder field set to true. This allows us to maintain a semblance of the efficiency achieved by the original module.

Example with placeholder

This example replaces the string foo with the method of the current HTTP request.

{
  "handler": "replace_response_placeholder",
  "replacements": [
    {
      "search": "foo",
      "replace": "{http.request.method}",
      "placeholder": true
    }
  ]
}

Caddy replace_response handler module

This Caddy module performs substring and regular expression replacements on response bodies, hence the name replace_response.

By default, this module operates in "buffer" mode. This is not very memory-efficient, but it guarantees we can always set the correct Content-Length header because we can buffer the output to know the resulting length before writing the response. If you need higher efficiency, you can enable "streaming" mode. When performing replacements on a stream, the Content-Length header may be removed because it is not always possible to know the correct value, since the results are streamed directly to the client and headers must be written before the body.

Note: This handler cannot perform replacements on compressed content. If your response comes from a proxied backend that supports compression, you will either have to decompress it in a response handler chain before this handler runs, or disable from the backend. One easy way to ask the backend to not compress the response is to set the Accept-Encoding header to identity, for example: header_up Accept-Encoding identity (in your Caddyfile, in the reverse_proxy block).

This module supports the use of placeholders in the search and replace arguments (but not regexes).

Module name: http.handlers.replace_response

JSON examples

Substring substitution:

{
	"handler": "replace_response",
	"replacements": [
		{
			"search": "Foo",
			"replace": "Bar"
		}
	]
}

Regular expression replacement:

{
	"handler": "replace_response",
	"replacements": [
		{
			"search_regexp": "\\s+foo(bar|baz)\\s+",
			"replace": " foo $1 "
		}
	]
}

Same, but with streaming mode (we just set "stream": true in the handler):

{
	"handler": "replace_response",
	"replacements": [
		{
			"search_regexp": "\\s+foo(bar|baz)\\s+",
			"replace": " foo $1 "
		}
	],
	"stream": true
}

Caddyfile

This module has Caddyfile support. It registers the replace directive. Make sure to order the handler directive in the correct place in the middleware chain; usually this works well:

{
	order replace after encode
}

Syntax:

replace [stream | [re] <search> <replace>] {
	stream
	[re] <search> <replace>
}
  • re indicates a regular expression instead of substring.
  • stream enables streaming mode.

Simple substring substitution:

replace Foo Bar

Regex replacement:

replace re "\s+foo(bar|baz)\s+" " foo $1 "

Streaming mode:

replace stream {
	Foo Bar
}

Multiple replacements:

replace {
	Foo Bar
	re "\s+foo(bar|baz)\s+" " foo $1 "
	A B
}

Limitations:

  • Regex matches longer than 2kb will not be replaced.

  • Compressed responses (e.g. from an upstream proxy which gzipped the response body) will not be decoded before attempting to replace. To work around this, you may send the Accept-Encoding: identity request header to the upstream to tell it not to compress the response. For example:

    reverse_proxy localhost:8080 {
        header_up Accept-Encoding identity
    }
    

About

Caddy module that performs replacements in response bodies

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 100.0%