0
# HTTP Utilities
1
2
HTTP service building and request/response handling components for creating Netty-based HTTP services with authentication, body handling, and configuration management.
3
4
## Capabilities
5
6
### HTTP Service Building
7
8
Components for building and configuring Netty-based HTTP services.
9
10
```java { .api }
11
/**
12
* Builder for creating common Netty HTTP services
13
*/
14
public class CommonNettyHttpServiceBuilder {
15
public CommonNettyHttpServiceBuilder();
16
17
/**
18
* Set the host to bind to
19
*/
20
public CommonNettyHttpServiceBuilder setHost(String host);
21
22
/**
23
* Set the port to bind to
24
*/
25
public CommonNettyHttpServiceBuilder setPort(int port);
26
27
/**
28
* Set the number of boss threads
29
*/
30
public CommonNettyHttpServiceBuilder setBossThreadPoolSize(int bossThreads);
31
32
/**
33
* Set the number of worker threads
34
*/
35
public CommonNettyHttpServiceBuilder setWorkerThreadPoolSize(int workerThreads);
36
37
/**
38
* Set connection backlog size
39
*/
40
public CommonNettyHttpServiceBuilder setConnectionBacklog(int backlog);
41
42
/**
43
* Enable/disable HTTP compression
44
*/
45
public CommonNettyHttpServiceBuilder enableCompression(boolean compress);
46
47
/**
48
* Set maximum content length
49
*/
50
public CommonNettyHttpServiceBuilder setMaxContentLength(int maxContentLength);
51
52
/**
53
* Add HTTP handlers
54
*/
55
public CommonNettyHttpServiceBuilder addHttpHandlers(Iterable<? extends HttpHandler> handlers);
56
57
/**
58
* Build the HTTP service
59
*/
60
public NettyHttpService build();
61
}
62
63
/**
64
* Factory for creating HTTP services
65
*/
66
public class CommonNettyHttpServiceFactory {
67
/**
68
* Create a new HTTP service builder
69
*/
70
public static CommonNettyHttpServiceBuilder builder();
71
72
/**
73
* Create HTTP service with default configuration
74
*/
75
public static NettyHttpService create(String host, int port,
76
Iterable<? extends HttpHandler> handlers);
77
}
78
```
79
80
**Usage Examples:**
81
82
```java
83
import io.cdap.cdap.common.http.*;
84
import co.cask.http.HttpHandler;
85
import co.cask.http.NettyHttpService;
86
87
// Build HTTP service with custom configuration
88
NettyHttpService httpService = CommonNettyHttpServiceFactory.builder()
89
.setHost("0.0.0.0")
90
.setPort(8080)
91
.setBossThreadPoolSize(1)
92
.setWorkerThreadPoolSize(10)
93
.setConnectionBacklog(1000)
94
.enableCompression(true)
95
.setMaxContentLength(10 * 1024 * 1024) // 10MB
96
.addHttpHandlers(Arrays.asList(new MyHttpHandler()))
97
.build();
98
99
// Start the service
100
httpService.startAsync().awaitRunning();
101
System.out.println("HTTP service started on port: " + httpService.getBindAddress().getPort());
102
103
// Stop the service
104
httpService.stopAsync().awaitTerminated();
105
106
// Simple service creation
107
NettyHttpService simpleService = CommonNettyHttpServiceFactory.create(
108
"localhost", 9090, Arrays.asList(new PingHandler())
109
);
110
```
111
112
### Request and Response Handling
113
114
Components for handling HTTP request/response bodies and content processing.
115
116
```java { .api }
117
/**
118
* Abstract base class for consuming HTTP request bodies
119
*/
120
public abstract class AbstractBodyConsumer extends BodyConsumer {
121
protected AbstractBodyConsumer();
122
123
/**
124
* Handle incoming chunk of data
125
*/
126
@Override
127
public void chunk(ChannelBuffer content, HttpResponder responder);
128
129
/**
130
* Handle end of request body
131
*/
132
@Override
133
public void finished(HttpResponder responder);
134
135
/**
136
* Handle error during body consumption
137
*/
138
@Override
139
public void handleError(Throwable cause);
140
}
141
142
/**
143
* Body consumer that can spill to disk when memory limits are exceeded
144
*/
145
public class SpillableBodyConsumer extends AbstractBodyConsumer {
146
public SpillableBodyConsumer(File spillDir, long memoryLimit);
147
148
/**
149
* Get the consumed content as input stream
150
*/
151
public InputStream getInputStream() throws IOException;
152
153
/**
154
* Get the total content length
155
*/
156
public long getContentLength();
157
158
/**
159
* Clean up resources
160
*/
161
public void close() throws IOException;
162
}
163
164
/**
165
* Body producer that reads from a location (file system, etc.)
166
*/
167
public class LocationBodyProducer extends BodyProducer {
168
public LocationBodyProducer(Location location);
169
170
@Override
171
public ByteBuf nextChunk() throws Exception;
172
173
@Override
174
public void finished() throws Exception;
175
176
@Override
177
public void handleError(Throwable cause);
178
}
179
```
180
181
### HTTP Configuration
182
183
Configuration classes for HTTP services and client requests.
184
185
```java { .api }
186
/**
187
* Default HTTP request configuration
188
*/
189
public class DefaultHttpRequestConfig implements HttpRequestConfig {
190
public DefaultHttpRequestConfig();
191
public DefaultHttpRequestConfig(int connectTimeout, int readTimeout);
192
193
@Override
194
public int getConnectTimeout();
195
196
@Override
197
public int getReadTimeout();
198
199
@Override
200
public boolean isVerifySSLCert();
201
202
@Override
203
public KeyStore getKeyStore();
204
205
@Override
206
public String getKeyStorePassword();
207
208
@Override
209
public KeyStore getTrustStore();
210
211
@Override
212
public String getTrustStorePassword();
213
}
214
215
/**
216
* HTTP status code utilities
217
*/
218
public class HttpCodes {
219
public static final int OK = 200;
220
public static final int CREATED = 201;
221
public static final int ACCEPTED = 202;
222
public static final int NO_CONTENT = 204;
223
public static final int BAD_REQUEST = 400;
224
public static final int UNAUTHORIZED = 401;
225
public static final int FORBIDDEN = 403;
226
public static final int NOT_FOUND = 404;
227
public static final int CONFLICT = 409;
228
public static final int INTERNAL_SERVER_ERROR = 500;
229
230
/**
231
* Check if status code indicates success (2xx)
232
*/
233
public static boolean isSuccess(int statusCode);
234
235
/**
236
* Check if status code indicates client error (4xx)
237
*/
238
public static boolean isClientError(int statusCode);
239
240
/**
241
* Check if status code indicates server error (5xx)
242
*/
243
public static boolean isServerError(int statusCode);
244
}
245
```
246
247
### Authentication Handling
248
249
HTTP authentication and security components.
250
251
```java { .api }
252
/**
253
* Channel handler for HTTP authentication
254
*/
255
public class AuthenticationChannelHandler extends SimpleChannelInboundHandler<HttpRequest> {
256
public AuthenticationChannelHandler(AuthenticationContext authContext);
257
258
@Override
259
protected void channelRead0(ChannelHandlerContext ctx, HttpRequest request) throws Exception;
260
261
/**
262
* Authenticate the HTTP request
263
*/
264
protected boolean authenticate(HttpRequest request, ChannelHandlerContext ctx);
265
266
/**
267
* Handle authentication failure
268
*/
269
protected void handleAuthFailure(ChannelHandlerContext ctx, String reason);
270
}
271
```
272
273
**Advanced Usage Examples:**
274
275
```java
276
import io.cdap.cdap.common.http.*;
277
import co.cask.http.HttpHandler;
278
279
// Custom HTTP handler with body processing
280
@Path("/api/v1")
281
public class DataUploadHandler extends AbstractHttpHandler {
282
283
@POST
284
@Path("/upload")
285
public void uploadData(HttpRequest request, HttpResponder responder) throws Exception {
286
// Use spillable body consumer for large uploads
287
SpillableBodyConsumer bodyConsumer = new SpillableBodyConsumer(
288
new File("/tmp/uploads"),
289
5 * 1024 * 1024 // 5MB memory limit
290
);
291
292
request.getContent().readBytes(bodyConsumer);
293
294
try (InputStream inputStream = bodyConsumer.getInputStream()) {
295
// Process the uploaded data
296
processUploadedData(inputStream);
297
responder.sendStatus(HttpCodes.ACCEPTED);
298
} finally {
299
bodyConsumer.close();
300
}
301
}
302
303
@GET
304
@Path("/download/{fileId}")
305
public void downloadFile(@PathParam("fileId") String fileId,
306
HttpRequest request, HttpResponder responder) throws Exception {
307
308
Location fileLocation = fileStore.getLocation(fileId);
309
if (fileLocation == null || !fileLocation.exists()) {
310
responder.sendStatus(HttpCodes.NOT_FOUND);
311
return;
312
}
313
314
// Use location body producer for file downloads
315
LocationBodyProducer bodyProducer = new LocationBodyProducer(fileLocation);
316
317
responder.sendContent(HttpCodes.OK, bodyProducer,
318
ImmutableMultimap.of("Content-Type", "application/octet-stream"));
319
}
320
}
321
322
// HTTP client with custom configuration
323
public class ApiClient {
324
private final HttpRequestConfig requestConfig;
325
326
public ApiClient(int connectTimeoutMs, int readTimeoutMs) {
327
this.requestConfig = new DefaultHttpRequestConfig(connectTimeoutMs, readTimeoutMs);
328
}
329
330
public String makeRequest(String url) throws IOException {
331
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
332
connection.setConnectTimeout(requestConfig.getConnectTimeout());
333
connection.setReadTimeout(requestConfig.getReadTimeout());
334
335
int responseCode = connection.getResponseCode();
336
337
if (HttpCodes.isSuccess(responseCode)) {
338
try (InputStream inputStream = connection.getInputStream()) {
339
return IOUtils.toString(inputStream, StandardCharsets.UTF_8);
340
}
341
} else if (HttpCodes.isClientError(responseCode)) {
342
throw new IOException("Client error: " + responseCode);
343
} else if (HttpCodes.isServerError(responseCode)) {
344
throw new IOException("Server error: " + responseCode);
345
}
346
347
throw new IOException("Unexpected response code: " + responseCode);
348
}
349
}
350
351
// Authenticated HTTP service
352
@Path("/secure")
353
public class SecureHandler extends AbstractHttpHandler {
354
355
@GET
356
@Path("/data")
357
public void getSecureData(HttpRequest request, HttpResponder responder,
358
@Context AuthenticationContext authContext) throws Exception {
359
360
if (authContext.getPrincipal() == null) {
361
responder.sendStatus(HttpCodes.UNAUTHORIZED);
362
return;
363
}
364
365
// Process authenticated request
366
String userData = fetchUserData(authContext.getPrincipal().getName());
367
responder.sendJson(HttpCodes.OK, userData);
368
}
369
}
370
371
// Service with authentication
372
public class AuthenticatedService {
373
public NettyHttpService createService(AuthenticationContext authContext) {
374
AuthenticationChannelHandler authHandler =
375
new AuthenticationChannelHandler(authContext);
376
377
return CommonNettyHttpServiceFactory.builder()
378
.setHost("0.0.0.0")
379
.setPort(8443)
380
.addChannelHandler(authHandler)
381
.addHttpHandlers(Arrays.asList(new SecureHandler()))
382
.build();
383
}
384
}
385
```