argo-events icon indicating copy to clipboard operation
argo-events copied to clipboard

Enhance HTTP Method Handling to Integrate Query Parameters, Headers, and Body for Webhook Events

Open PieroValdebenito opened this issue 8 months ago • 1 comments

Is your feature request related to a problem? Please describe.

Currently, the GET method in the webhook event handling only supports capturing query parameters, and the POST method only sends the body of the request. This limitation reduces flexibility and functionality when interacting with the API, as it does not allow for the integrated sending or capturing of other important data like headers and both query parameters and body across all requests.

Describe the solution you'd like

I would like all HTTP methods (GET, POST, PUT, DELETE, etc.) to handle the data sent in query parameters, headers, and body in an integrated manner. Specifically, this would involve modifying the route handling functions to capture and send all this data regardless of the HTTP method used. This would allow for greater flexibility in handling requests and responding to webhook events.

Describe alternatives you've considered

Extend the current functionality of each method to optionally capture headers and other data through additional configurations in the route definition.

Additional context

Here is the relevant code that might need changes to implement this enhancement:

eventsources/sources/webhook/start.go#L167

func GetBody(writer *http.ResponseWriter, request *http.Request, route *webhook.Route, logger *zap.SugaredLogger) (*json.RawMessage, error) {
	switch request.Method {
	case http.MethodGet:

		// Currently only captures query parameters

		body, _ := json.Marshal(request.URL.Query())
		ret := json.RawMessage(body)
		return &ret, nil
	case http.MethodPost: 		// <--- Currently only captures body
		contentType := ""
		if len(request.Header["Content-Type"]) > 0 {
			contentType = request.Header["Content-Type"][0]
		}

		switch contentType {
		case "application/x-www-form-urlencoded":
			if err := request.ParseForm(); err != nil {
				logger.Errorw("failed to parse form data", zap.Error(err))
				common.SendInternalErrorResponse(*writer, err.Error())
				route.Metrics.EventProcessingFailed(route.EventSourceName, route.EventName)
				return nil, err
			}
			body, _ := json.Marshal(request.PostForm)
			ret := json.RawMessage(body)
			return &ret, nil
		default:
			request.Body = http.MaxBytesReader(*writer, request.Body, route.Context.GetMaxPayloadSize())
			body, err := getRequestBody(request)
			if err != nil {
				logger.Errorw("failed to read request body", zap.Error(err))
				common.SendErrorResponse(*writer, err.Error())
				route.Metrics.EventProcessingFailed(route.EventSourceName, route.EventName)
				return nil, err
			}
			ret := json.RawMessage(body)
			return &ret, nil
		}
	default:
		return nil, fmt.Errorf("unsupported method: %s", request.Method)
	}
}

Message from the maintainers:

If you wish to see this enhancement implemented please add a 👍 reaction to this issue! We often sort issues this way to know what to prioritize.

PieroValdebenito avatar Jun 21 '24 03:06 PieroValdebenito