Hone logo
Hone
Problems

Implementing Request Interceptors in Go

Interceptors are a powerful mechanism for modifying requests before they are sent and responses after they are received. This challenge asks you to implement a system of request interceptors in Go, allowing you to add functionality like logging, authentication, or request transformation without modifying the core request-sending logic. This is a common pattern in distributed systems and microservices architectures.

Problem Description

You are tasked with creating a simple HTTP client with interceptor support. The client should be able to send HTTP requests to a given URL and allow multiple interceptors to be chained together. Each interceptor should have the opportunity to modify the request before it's sent and the response after it's received.

What needs to be achieved:

  1. Interceptor Interface: Define an Interceptor interface with two methods: InterceptRequest and InterceptResponse. InterceptRequest takes the request as input and can modify it. InterceptResponse takes the response as input and can modify it. Both methods return the modified request/response.
  2. Client with Interceptor Chain: Create an HTTPClient struct that accepts a slice of Interceptor implementations in its constructor. The client should have a Do method that sends an HTTP request, applying each interceptor in the chain sequentially.
  3. Request and Response Structs: Define simple Request and Response structs to represent the HTTP request and response. These structs should contain at least a URL field for the request and a Body field for the response.

Key Requirements:

  • The interceptors should be applied in the order they are provided to the client.
  • The Do method should handle sending the HTTP request and receiving the response. For simplicity, you can use the standard net/http package for this.
  • Each interceptor should receive the modified request/response from the previous interceptor in the chain.
  • The client should return an error if the HTTP request fails.

Expected Behavior:

The Do method should:

  1. Start with the original request.
  2. Pass the request to the first interceptor.
  3. Pass the modified request to the second interceptor, and so on.
  4. Send the final modified request using net/http.
  5. Receive the response.
  6. Pass the response to the last interceptor.
  7. Pass the modified response to the second-to-last interceptor, and so on.
  8. Return the final modified response.

Edge Cases to Consider:

  • Empty interceptor chain (no interceptors provided).
  • Interceptors that return errors. The client should propagate these errors.
  • Invalid URLs.
  • Network errors during the HTTP request.

Examples

Example 1:

Input: Client with two interceptors:
    Interceptor 1: Adds a header to the request.
    Interceptor 2: Logs the request URL.
Request: GET /api/data
Output: Response with the added header and logged URL.
Explanation: Interceptor 1 modifies the request by adding a header. Interceptor 2 logs the URL of the modified request before it's sent. The client then sends the modified request and returns the response.

Example 2:

Input: Client with no interceptors.
Request: GET /api/data
Output: Response from the server.
Explanation: The request is sent directly to the server without any modifications.

Example 3: (Edge Case)

Input: Client with one interceptor that returns an error.
Request: GET /api/data
Output: Error message indicating the interceptor failed.
Explanation: The client should catch the error returned by the interceptor and return it to the caller.

Constraints

  • The Request struct must have a URL field (string).
  • The Response struct must have a Body field (string).
  • The interceptors should be applied sequentially.
  • The Do method should use the net/http package for sending requests.
  • Error handling is crucial. Propagate errors appropriately.
  • Assume the URL is always valid for the purpose of this challenge.

Notes

  • Consider using interfaces to decouple the client from specific interceptor implementations.
  • Think about how to handle errors returned by interceptors.
  • This challenge focuses on the core logic of interceptors. You don't need to implement a full-fledged HTTP client with all the features.
  • The InterceptRequest and InterceptResponse methods should return the modified request/response. If no modification is needed, return the original request/response.
Loading editor...
go