-
Notifications
You must be signed in to change notification settings - Fork 236
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
How access portions of the request. #1209
Comments
Hi @marvfinsy , Thanks for reaching out with your feature request for the GoFr framework. We’d like to understand your needs better: URL Path Access: Since the URL path is directly mapped to the handler, could you explain why a separate method is necessary? Request Headers: We currently have methods to access authentication-related headers. Could you please provide more details on the type of headers you need to access and the specific use case? Understanding your specific needs will help us provide the best solution. Looking forward to your response. |
Yes i could set a variable = to the mapped path... But my original idea was to map every URL path to the same handler. That handler can get the URL path from the http.Request.Url object. 80% to 90% of business logic seems to be the same. There will be a "list" of acceptable headers. This common handler would also need to read those headers from the request. |
@marvfinsy Thank you for sharing your feedback regarding header access. While we understand your idea of mapping every URL path to the same handler and reading headers from the request, we would love to learn more about your specific use case to ensure that our implementation aligns with your requirements. Could you please provide an example or scenario where this functionality would be particularly useful? For instance, how would you envision using the list of acceptable headers, and what kind of business logic would depend on this header-based processing? Your insights will help us evaluate and prioritize this feature to best serve your needs. Looking forward to hearing from you! |
@Umang01-hash an example application would be a Zoom "Recording Complete" webhook that requires validation of a specific timestamp from the header and then returning a specific payload as described here: https://developers.zoom.us/docs/api/rest/webhook-reference/#validate-your-webhook-endpoint with a Javascript implementation here: https://github.com/zoom/webhook-sample/blob/master/index.js#L24-L49 As far as I can tell, this would not be simple to accomplish with existing functionality. |
However, this PR #1227 looks like it would make it easy to extract that header value that Zoom sends and then run the required calculations to return the validated expected value.. |
@devorbitus Thank you for highlighting this use case! While the proposed PR (#1227) simplifies header access, webhook validation for Zoom can be effectively handled at the middleware level. Middleware has full access to headers, including By performing the signature verification in middleware, we can ensure that only validated requests proceed to the handler, streamlining the process. |
@Umang01-hash The flow in the javascript code looks at the payload and when a specific validation property is detected it responds back a specific way instead of responding back with usual payload, how would a middleware implementation accomplish this? |
In my case i'm redirecting to a vendor site. The vendor has a unique set of rules regarding authentication etc... Some information required for authentication i've saved in a badger key-value store. I also need an http client for vendor calls. Once authenticated i can redirect based on the current endpoint path. I could write a handler for each endpoint that calls a "common handler" and pass the endpoint path as a string to the "common handler". But it would be easier to have the one "common handler" accessing the http.Request.URL.Path for the information.
|
@devorbitus Here is my attempt to provide you with some implementation regarding how can we achieve our use-case using a middleware: package main
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"gofr.dev/pkg/gofr"
gofrHTTP "gofr.dev/pkg/gofr/http"
)
func main() {
// Create a new application
a := gofr.New()
// Register the middleware for validating Zoom webhooks
a.UseMiddleware(zoomWebhookValidationMiddleware("webhook-secret"))
// Register the POST handler for the Zoom webhook
a.POST("/zoom-webhook", handler)
// Run the application
a.Run()
}
// handler processes the validated webhook request
func handler(c *gofr.Context) (interface{}, error) {
// Check if the request was validated by the middleware
validated, ok := c.Value("zoomValidated").(bool)
if !ok || !validated {
return nil, fmt.Errorf("invalid signature")
}
// Parse the request body as per user-defined structure
var requestBody map[string]interface{} // Generic map for flexibility
if err := c.Bind(&requestBody); err != nil {
return nil, fmt.Errorf("invalid request body: %w", err)
}
// Return the validated request body as a response
return map[string]interface{}{
"validated": validated,
"body": requestBody,
}, nil
}
// zoomWebhookValidationMiddleware validates Zoom webhook requests
func zoomWebhookValidationMiddleware(secret string) gofrHTTP.Middleware {
return func(inner http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Extract required headers for validation
timestamp := r.Header.Get("x-zm-request-timestamp")
signature := r.Header.Get("x-zm-signature")
// Validate that the necessary headers are present
if timestamp == "" || signature == "" {
http.Error(w, "Missing required headers", http.StatusBadRequest)
return
}
// Read and reset the request body
bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request body", http.StatusInternalServerError)
return
}
r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
// Perform the signature validation
if !validateZoomSignature(secret, timestamp, bodyBytes, signature) {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}
// Mark the request as validated and pass it to the next handler
ctx := context.WithValue(r.Context(), "zoomValidated", true)
inner.ServeHTTP(w, r.WithContext(ctx))
})
}
} I have used Please let me know if we can provide any further assistance with respect to your use-case. Thankyou. |
@marvfinsy addressing your concerns: GoFr supports adding data to the context within middleware, which can be accessed in handlers: Also it's not generally suggested to use an HTTP client or database in middleware, we should perform essential tasks like authentication and pass results through the context. |
thx... Appears i can use middleware to get path from request.URL then save and read it from context... That works! Will give a "try" this weekend! thx for help... |
From the context I see u have a method to get Host. Query parameters etc.
How do i access other parts of the request like:
I need to get the path of the request without the scheme and host parts. Was going to create custom middleware to do this. It would add a custom header to the request with that information. Once in my route i'd access the header i added. yuk!
Of course If i can't read the generated header in my route he above is useless. Really hate the idea of altering original request adding self-generated headers.
Do i really need to do all the above to read request path information or to read headers?
thx ~Marvin
marvinfoster@finsync.com
mmarvb7@gmail.com
The text was updated successfully, but these errors were encountered: