Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable OPTIONS and CloudEvent Webhook headers #5542

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/broker/filter/filter_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ func (h *Handler) Start(ctx context.Context) error {
// 5. send event to trigger's subscriber
// 6. write the response
func (h *Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
writer.Header().Set("Allow", "POST")

if request.Method != http.MethodPost {
writer.WriteHeader(http.StatusMethodNotAllowed)
Expand Down
7 changes: 7 additions & 0 deletions pkg/broker/ingress/ingress_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,14 @@ func (h *Handler) Start(ctx context.Context) error {
}

func (h *Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
writer.Header().Set("Allow", "POST, OPTIONS")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http://github.com/knative/specs/pull/25, data-plane.md, line 88.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I started working ahead of that commit landing)

// validate request method
if request.Method == http.MethodOptions {
writer.Header().Set("WebHook-Allowed-Origin", "*") // Accept from any Origin:
writer.Header().Set("WebHook-Allowed-Rate", "*") // Unlimited requests/minute
writer.WriteHeader(http.StatusOK)
return
}
if request.Method != http.MethodPost {
h.Logger.Warn("unexpected request method", zap.String("method", request.Method))
writer.WriteHeader(http.StatusMethodNotAllowed)
Expand Down
27 changes: 18 additions & 9 deletions pkg/broker/ingress/ingress_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,20 +104,29 @@ func TestHandler_ServeHTTP(t *testing.T) {
defaulter: broker.TTLDefaulter(logger, 100),
},
{
name: "invalid method OPTIONS",
method: nethttp.MethodOptions,
uri: "/ns/name",
body: getValidEvent(),
statusCode: nethttp.StatusMethodNotAllowed,
name: "valid method OPTIONS",
method: nethttp.MethodOptions,
uri: "/ns/name",
body: strings.NewReader(""),
expectedHeaders: nethttp.Header{
"Allow": []string{"PUT, OPTIONS"},
"WebHook-Allowed-Origin": []string{"*"},
"WebHook-Allowed-Rate": []string{"*"},
"Content-Length": []string{"0"},
},
statusCode: nethttp.StatusOK,
handler: handler(),
reporter: &mockReporter{},
defaulter: broker.TTLDefaulter(logger, 100),
},
{
name: "valid (happy path)",
method: nethttp.MethodPost,
uri: "/ns/name",
body: getValidEvent(),
name: "valid (happy path POST)",
method: nethttp.MethodPost,
uri: "/ns/name",
body: getValidEvent(),
expectedHeaders: nethttp.Header{
"Allow": []string{"PUT, OPTIONS"},
},
statusCode: senderResponseStatusCode,
handler: handler(),
reporter: &mockReporter{StatusCode: senderResponseStatusCode, EventDispatchTimeReported: true},
Expand Down
7 changes: 7 additions & 0 deletions pkg/channel/message_receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ func (r *MessageReceiver) Start(ctx context.Context) error {
}

func (r *MessageReceiver) ServeHTTP(response nethttp.ResponseWriter, request *nethttp.Request) {
response.Header().Set("Allow", "POST, OPTIONS")
if request.Method == nethttp.MethodOptions {
response.Header().Set("WebHook-Allowed-Origin", "*") // Accept from any Origin:
response.Header().Set("WebHook-Allowed-Rate", "*") // Unlimited requests/minute
response.WriteHeader(nethttp.StatusOK)
return
}
if request.Method != nethttp.MethodPost {
response.WriteHeader(nethttp.StatusMethodNotAllowed)
return
Expand Down
22 changes: 22 additions & 0 deletions pkg/channel/message_receiver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func TestMessageReceiver_ServeHTTP(t *testing.T) {
additionalHeaders nethttp.Header
expected int
receiverFunc UnbufferedMessageReceiverFunc
responseValidator func(r httptest.ResponseRecorder) error
}{
"non '/' path": {
path: "/something",
Expand Down Expand Up @@ -121,6 +122,22 @@ func TestMessageReceiver_ServeHTTP(t *testing.T) {
},
expected: nethttp.StatusAccepted,
},
"OPTIONS okay": {
method: nethttp.MethodOptions,
host: "test-name.test-namespace.svc." + network.GetClusterDomainName(),
expected: nethttp.StatusOK,
responseValidator: func(res httptest.ResponseRecorder) error {
expectedHeaders := nethttp.Header{
"Allow": []string{"POST, OPTIONS"},
"Webhook-Allowed-Origin": []string{"*"},
"Webhook-Allowed-Rate": []string{"*"},
}
if diff := cmp.Diff(expectedHeaders, res.Header()); diff != "" {
return fmt.Errorf("test receiver func -- bad OPTION headers (-want, +got): %s", diff)
}
return nil
},
},
}
reporter := NewStatsReporter("testcontainer", "testpod")
for n, tc := range testCases {
Expand Down Expand Up @@ -172,6 +189,11 @@ func TestMessageReceiver_ServeHTTP(t *testing.T) {
if res.Code != tc.expected {
t.Fatalf("Unexpected status code. Expected %v. Actual %v", tc.expected, res.Code)
}
if tc.responseValidator != nil {
if err := tc.responseValidator(res); err != nil {
t.Errorf("Incorrect response: %v", err)
}
}
})
}
}
Expand Down
18 changes: 17 additions & 1 deletion test/conformance/helpers/broker_data_plane_test_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func BrokerDataPlaneNamespaceSetupOption(ctx context.Context, namespace string)
//Supports structured or Binary mode
//Respond with 2xx on good CE
//Respond with 400 on bad CE
//Reject non-POST requests to publish URI
//Reject non-POST, non-OPTIONS requests to publish URI (beyond spec?!)
func BrokerIngressDataPlaneTestHelper(
ctx context.Context,
t *testing.T,
Expand All @@ -108,6 +108,22 @@ func BrokerIngressDataPlaneTestHelper(
resources.WithSubscriberServiceRefForTrigger(loggerName),
)

st.Run("Ingress supports OPTIONS", func(t *testing.T) {
// TODO(evana): check "Allow" header and other options.
// This may be simpler if the setup requires a local HTTP proxy which can reach into the cluster.
method := sender.WithMethod("OPTIONS")
responseSink := "http://" + client.GetServiceHost(loggerName)
responseForward := sender.WithResponseSink(responseSink)
senderName := "options-test-sender"
client.SendRequestToAddressable(ctx, senderName, broker.Name, testlib.BrokerTypeMeta, map[string]string{}, "", method, responseForward)
client.WaitForResourceReadyOrFail(senderName, &podMeta)
eventTracker.AssertAtLeast(1, recordevents.MatchEvent(cetest.AllOf(
cetest.AnyOf(
sender.MatchStatusCode(200), sender.MatchStatusCode(405)),
cetest.HasSource("https://knative.dev/eventing/test/event-sender"),
)))
})

client.WaitForResourceReadyOrFail(trigger.Name, testlib.TriggerTypeMeta)
st.Run("Ingress Supports CE0.3", func(t *testing.T) {
eventID := "CE0.3"
Expand Down