Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

There is no any changes on public interfaces. We just add define a new configuration property "response.http.headers"prefix "filter.name.<name>.", then followed by a set of properties which define rules for header. The following section has detailed description on this new propertydescription.

Proposed Changes

Adding New PropertyProperties

We will add a new property "response.http.headers" set of new properties in org.apache.kafka.connect.runtime.WorkerConfig class. It will allow REST server administrator to configure headers based on their security policies. We borrow and take advantage of Jetty HeaderFilter class and use same format of headerConfig, includedPaths, excludedPaths, includedMimeTypes, excludedMimeTypes, includedHttpMethods, excludedHttpMethods init parameters.

Description of Properties

header.config

init param. The format for response.http.headers will be "[[action] [header]:[header value],..." which is a list of [action] [header]:[value] separated by comma ",". So it is a CSV of actions to perform on headers with the following syntax:
[action] [header name]: [header value],
[action] can be one of "set, add, setDate, or addDate" which specify an action will perform on header. 

...

[header name] specify name of header.
[header value] specify value for the header. We need put double quotes around the value if the value contains commas due to we use comma as separator for different headers. 

Example:

header.config=set X-Frame-Options: DENY, "add Cache-Control: no-cache, no-store, must-revalidate", setDate Expires: 31540000000, addDate Last-Modified: 0

header.includedpaths

It is optional. it is comma separated values of included path specs applied to headers.config. See path spec rules section.

Example:

header.includedpaths=^/test/0$

header.excludedaths

It is optional. it is comma separated values of excluded path specs applied to headers.config. See path spec rules section.

Example:

header.excludedpaths=^/test/0$

header.includedmimetypes

It is optional. it is comma separated values of included mime types applied to headers.config.

Example:

header.includedmimetypes=application/json

header.excludedmimetypes

It is optional. it is comma separated values of excluded mime types applied to headers.config.

Example:

header.excludedmimetypes=application/xml

header.includedhttpmethods

It is optional. it is comma separated values of included http methods applied to headers.config.

Example:

header.includedhttpmethods=POST,PUT

header.excludedhttpmethods

It is optional. it is comma separated values of excluded http methods applied to headers.config.

Example:

header.excludedhttpmethods=GET

Path Spec Rules:

  • If the spec starts with ^, the spec is assumed to be a regex based path spec and will match with normal Java regex rules.
  • If the spec starts with /, the spec is assumed to be a Servlet url-pattern rules path spec for either an exact match or prefix based match.
  • If the spec starts with *., the spec is assumed to be a Servlet url-pattern rules path spec for a suffix based match.
  • All other syntaxes are unsupported.


Multiple Headers Configuration

We use Jetty HeaderFilter to implement HTTP response header configuration. We need support multiple rules applied to multiple different response headers.

We define a prefix filter.name.<name>. to allow multiple configurations, so that different paths have different headers.

Example:

filter.name.header1.header.config of configuration for response.http.headersresponse.http.headers=set X-Frame-Options: DENY, "add Cache-Control: no-cache, no-store, must-revalidate", setDate Expires: 31540000000, addDate Last-Modified: 0

filter.name.header1.header.includedpaths=^/test/0$

filter.name.header1.header.excludedpaths=^/test1/0$     

filter.name.header1.header.includedmimetypes=application/jsonheader

filter.name.header1.header.excludedmimetypes=application/xml

filter.name.header1.header.includedhttpmethods=POST,PUT

filter.name.header1.header.excludedhttpmethods=GET


Implementation

Implementation will use Jetty HeaderFilter class. We need update org.apache.kafka.connect.runtime.rest.RestServer class. During initializing process Connect REST server will read all header configuration configurations from the property responsewith prefix filter.httpname.headers, then create a list of FilterHoder with HeaderFilter class and add the list of filter holder holders to Servlet context handler based on name of filter. Implementation is similar as we handle header access.control.allow.origin in Connect REST server.

...

ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
Map<String, String> headerFilterConfigs = extractHeaderFilterConfig(workerConfig);
for (String name : headerFilterConfigs.getkeySet()) {
String filterName = extract
String responseHeaders = config.getString("response.http.headers");
FilterHolder headersFilterHolder = new FilterHolder(HeaderFilter.class);
headersFilterHolder.setName("headerConfig");
headersFilterHolder.setInitParameter("headerConfig", responseHeaders);
context.addFilter(headersFilterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));

References

...