Skip to content

Commit

Permalink
Support custom response headers for RUM endpoints (#3820)
Browse files Browse the repository at this point in the history

Co-authored-by: Andrew Wilkins <axwalk@gmail.com>
  • Loading branch information
jalvz and axw committed May 27, 2020
1 parent 0237fa6 commit a93a1ef
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 7 deletions.
4 changes: 4 additions & 0 deletions _meta/beat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ apm-server:
# "Content-Encoding", and "Accept"
#allow_headers : []

# Custom HTTP headers to add to RUM responses, e.g. for security policy compliance.
#response_headers :
# X-My-Header: Contents of the header

# Regexp to be matched against a stacktrace frame's `file_name` and `abs_path` attributes.
# If the regexp matches, the stacktrace frame is considered to be a library frame.
#library_pattern: "node_modules|bower_components|~"
Expand Down
4 changes: 4 additions & 0 deletions apm-server.docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ apm-server:
# "Content-Encoding", and "Accept"
#allow_headers : []

# Custom HTTP headers to add to RUM responses, e.g. for security policy compliance.
#response_headers :
# X-My-Header: Contents of the header

# Regexp to be matched against a stacktrace frame's `file_name` and `abs_path` attributes.
# If the regexp matches, the stacktrace frame is considered to be a library frame.
#library_pattern: "node_modules|bower_components|~"
Expand Down
4 changes: 4 additions & 0 deletions apm-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ apm-server:
# "Content-Encoding", and "Accept"
#allow_headers : []

# Custom HTTP headers to add to RUM responses, e.g. for security policy compliance.
#response_headers :
# X-My-Header: Contents of the header

# Regexp to be matched against a stacktrace frame's `file_name` and `abs_path` attributes.
# If the regexp matches, the stacktrace frame is considered to be a library frame.
#library_pattern: "node_modules|bower_components|~"
Expand Down
1 change: 1 addition & 0 deletions beater/api/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ func rumMiddleware(cfg *config.Config, _ *authorization.Handler, m map[request.R
"Configure the `apm-server.rum` section in apm-server.yml to enable ingestion of RUM events. " +
"If you are not using the RUM agent, you can safely ignore this error."
rumMiddleware := append(apmMiddleware(m),
middleware.ResponseHeadersMiddleware(cfg.RumConfig.ResponseHeaders),
middleware.SetRumFlagMiddleware(),
middleware.SetIPRateLimitMiddleware(cfg.RumConfig.EventRate),
middleware.CORSMiddleware(cfg.RumConfig.AllowOrigins, cfg.RumConfig.AllowHeaders),
Expand Down
15 changes: 8 additions & 7 deletions beater/config/rum.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@ const (

// RumConfig holds config information related to the RUM endpoint
type RumConfig struct {
Enabled *bool `config:"enabled"`
EventRate *EventRate `config:"event_rate"`
AllowOrigins []string `config:"allow_origins"`
AllowHeaders []string `config:"allow_headers"`
LibraryPattern string `config:"library_pattern"`
ExcludeFromGrouping string `config:"exclude_from_grouping"`
SourceMapping *SourceMapping `config:"source_mapping"`
Enabled *bool `config:"enabled"`
EventRate *EventRate `config:"event_rate"`
AllowOrigins []string `config:"allow_origins"`
AllowHeaders []string `config:"allow_headers"`
ResponseHeaders map[string][]string `config:"response_headers"`
LibraryPattern string `config:"library_pattern"`
ExcludeFromGrouping string `config:"exclude_from_grouping"`
SourceMapping *SourceMapping `config:"source_mapping"`

BeatVersion string
}
Expand Down
36 changes: 36 additions & 0 deletions beater/middleware/response_headers_middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package middleware

import (
"github.com/elastic/apm-server/beater/request"
)

// ResponseHeadersMiddleware sets the configured headers in the response
func ResponseHeadersMiddleware(headers map[string][]string) Middleware {
return func(h request.Handler) (request.Handler, error) {
return func(c *request.Context) {
for k, v := range headers {
for _, s := range v {
c.Header().Add(k, s)
}
}
h(c)
}, nil
}
}
35 changes: 35 additions & 0 deletions beater/middleware/response_headers_middleware_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package middleware

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/elastic/apm-server/beater/beatertest"
)

func TestResponseHeadersMiddleware(t *testing.T) {
h := map[string][]string{
"X-Custom-Header": {"custom-header-value"},
}
c, _ := beatertest.DefaultContextWithResponseRecorder()
Apply(ResponseHeadersMiddleware(h), beatertest.HandlerIdle)(c)
assert.Equal(t, "custom-header-value", c.Header().Get("X-Custom-Header"))
}
1 change: 1 addition & 0 deletions changelogs/head.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ https://github.com/elastic/apm-server/compare/7.8\...master[View commits]

[float]
==== Added
* Support configurable response headers for the RUM endpoints {pull}3820[3820]

0 comments on commit a93a1ef

Please sign in to comment.