View Javadoc
1   package com.guinetik.rr.request;
2   
3   import com.guinetik.rr.http.RocketHeaders;
4   
5   import java.util.HashMap;
6   import java.util.Map;
7   
8   /**
9    * Immutable specification of an HTTP request containing all parameters needed for execution.
10   *
11   * <p>A {@code RequestSpec} encapsulates the complete definition of an API request including
12   * the endpoint, HTTP method, query parameters, headers, request body, and expected response type.
13   * Instances are created using the {@link RequestBuilder} fluent API.
14   *
15   * <h2>Request Components</h2>
16   * <ul>
17   *   <li><b>Endpoint</b> - The API path (relative or absolute URL)</li>
18   *   <li><b>Method</b> - HTTP method (GET, POST, PUT, DELETE, etc.)</li>
19   *   <li><b>Query Parameters</b> - URL query string parameters</li>
20   *   <li><b>Headers</b> - HTTP request headers via {@link RocketHeaders}</li>
21   *   <li><b>Body</b> - Request payload (for POST, PUT, PATCH)</li>
22   *   <li><b>Response Type</b> - Expected Java class for response deserialization</li>
23   * </ul>
24   *
25   * <h2>Creating Request Specifications</h2>
26   * <pre class="language-java"><code>
27   * // Simple GET request
28   * RequestSpec&lt;Void, User&gt; getUser = RequestBuilder.&lt;Void, User&gt;get("/users/1")
29   *     .responseType(User.class)
30   *     .build();
31   *
32   * // POST request with body
33   * CreateUserRequest body = new CreateUserRequest("John", "john@example.com");
34   * RequestSpec&lt;CreateUserRequest, User&gt; createUser = RequestBuilder
35   *     .&lt;CreateUserRequest, User&gt;post("/users")
36   *     .body(body)
37   *     .responseType(User.class)
38   *     .build();
39   *
40   * // GET with query parameters
41   * Map&lt;String, String&gt; params = new HashMap&lt;&gt;();
42   * params.put("page", "1");
43   * params.put("limit", "20");
44   * RequestSpec&lt;Void, UserList&gt; listUsers = RequestBuilder.&lt;Void, UserList&gt;get("/users")
45   *     .queryParams(params)
46   *     .responseType(UserList.class)
47   *     .build();
48   * </code></pre>
49   *
50   * <h2>Executing Requests</h2>
51   * <pre class="language-java"><code>
52   * // With synchronous client
53   * User user = client.sync().execute(getUser);
54   *
55   * // With async client
56   * CompletableFuture&lt;User&gt; future = client.async().execute(getUser);
57   *
58   * // With fluent client
59   * Result&lt;User, ApiError&gt; result = client.fluent().execute(getUser);
60   * </code></pre>
61   *
62   * @param <Req> the type of the request body (use {@code Void} for requests without body)
63   * @param <Res> the type of the expected response
64   * @author guinetik &lt;guinetik@gmail.com&gt;
65   * @see RequestBuilder
66   * @see RocketHeaders
67   * @since 1.0.0
68   */
69  public class RequestSpec<Req, Res> {
70      private final String endpoint;
71      private final String method;
72      private final Map<String, String> queryParams;
73      private final RocketHeaders headers;
74      private final Req body;
75      private final Class<Res> responseType;
76  
77      public RequestSpec(String endpoint, String method, Map<String, String> queryParams,
78                         RocketHeaders headers, Req body, Class<Res> responseType) {
79          this.endpoint = endpoint;
80          this.method = method;
81          this.queryParams = queryParams != null ? queryParams : new HashMap<>();
82          this.headers = headers != null ? headers : RocketHeaders.defaultJson();
83          this.body = body;
84          this.responseType = responseType;
85      }
86  
87      public String getEndpoint() {
88          return endpoint;
89      }
90  
91      public String getMethod() {
92          return method;
93      }
94  
95      public Map<String, String> getQueryParams() {
96          return queryParams;
97      }
98  
99      public RocketHeaders getHeaders() {
100         return headers;
101     }
102 
103     public Req getBody() {
104         return body;
105     }
106 
107     public Class<Res> getResponseType() {
108         return responseType;
109     }
110 }