use of co.cask.http.NettyHttpService in project cdap by caskdata.
the class WebappProgramRunner method run.
@Override
public ProgramController run(Program program, ProgramOptions options) {
try {
ProgramType processorType = program.getType();
Preconditions.checkNotNull(processorType, "Missing processor type");
Preconditions.checkArgument(processorType == ProgramType.WEBAPP, "Only WEBAPP process type is supported");
LOG.info("Initializing Webapp for app {} with jar {}", program.getApplicationId(), program.getJarLocation().getName());
String serviceName = getServiceName(program.getId());
Preconditions.checkNotNull(serviceName, "Cannot determine service name for program %s", program.getName());
LOG.info("Got service name {}", serviceName);
// Start netty server
// TODO: add metrics reporting
JarHttpHandler jarHttpHandler = webappHttpHandlerFactory.createHandler(program.getJarLocation());
NettyHttpService.Builder builder = new CommonNettyHttpServiceBuilder(cConf, program.getId().toString());
builder.addHttpHandlers(ImmutableSet.of(jarHttpHandler));
builder.setUrlRewriter(new WebappURLRewriter(jarHttpHandler));
builder.setHost(hostname.getCanonicalHostName());
NettyHttpService httpService = builder.build();
httpService.startAndWait();
final InetSocketAddress address = httpService.getBindAddress();
RunId runId = ProgramRunners.getRunId(options);
// Register service, and the serving host names.
final List<Cancellable> cancellables = Lists.newArrayList();
LOG.info("Webapp {} running on address {} registering as {}", program.getApplicationId(), address, serviceName);
cancellables.add(serviceAnnouncer.announce(serviceName, address.getPort()));
for (String hname : getServingHostNames(Locations.newInputSupplier(program.getJarLocation()))) {
final String sname = ProgramType.WEBAPP.name().toLowerCase() + "/" + hname;
LOG.info("Webapp {} running on address {} registering as {}", program.getApplicationId(), address, sname);
cancellables.add(discoveryService.register(ResolvingDiscoverable.of(new Discoverable(sname, address))));
}
return new WebappProgramController(program.getId(), runId, httpService, new Cancellable() {
@Override
public void cancel() {
for (Cancellable cancellable : cancellables) {
cancellable.cancel();
}
}
});
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
use of co.cask.http.NettyHttpService in project cdap by caskdata.
the class HttpHandlerGeneratorTest method testHttpHeaders.
@Test
public void testHttpHeaders() throws Exception {
MetricsContext noOpsMetricsContext = new NoOpMetricsCollectionService().getContext(new HashMap<String, String>());
HttpHandlerFactory factory = new HttpHandlerFactory("/prefix", noOpsMetricsContext);
HttpHandler httpHandler = factory.createHttpHandler(TypeToken.of(MyHttpHandler.class), new AbstractDelegatorContext<MyHttpHandler>() {
@Override
protected MyHttpHandler createHandler() {
return new MyHttpHandler();
}
});
NettyHttpService service = NettyHttpService.builder().addHttpHandlers(ImmutableList.of(httpHandler)).build();
service.startAndWait();
try {
InetSocketAddress bindAddress = service.getBindAddress();
// Make a request with headers that the response should carry first value for each header name
HttpURLConnection urlConn = (HttpURLConnection) new URL(String.format("http://%s:%d/prefix/p2/echo/firstHeaders", bindAddress.getHostName(), bindAddress.getPort())).openConnection();
urlConn.addRequestProperty("k1", "v1");
urlConn.addRequestProperty("k1", "v2");
urlConn.addRequestProperty("k2", "v2");
Assert.assertEquals(200, urlConn.getResponseCode());
Map<String, List<String>> headers = urlConn.getHeaderFields();
Assert.assertEquals(ImmutableList.of("v1"), headers.get("k1"));
Assert.assertEquals(ImmutableList.of("v2"), headers.get("k2"));
// Make a request with headers that the response should carry all values for each header name
urlConn = (HttpURLConnection) new URL(String.format("http://%s:%d/prefix/p2/echo/allHeaders", bindAddress.getHostName(), bindAddress.getPort())).openConnection();
urlConn.addRequestProperty("k1", "v1");
urlConn.addRequestProperty("k1", "v2");
urlConn.addRequestProperty("k1", "v3");
urlConn.addRequestProperty("k2", "v2");
Assert.assertEquals(200, urlConn.getResponseCode());
headers = urlConn.getHeaderFields();
// URLConnection always reverse the ordering of the header values.
Assert.assertEquals(ImmutableList.of("v3", "v2", "v1"), headers.get("k1"));
Assert.assertEquals(ImmutableList.of("v2"), headers.get("k2"));
} finally {
service.stopAndWait();
}
}
use of co.cask.http.NettyHttpService in project cdap by caskdata.
the class ServiceHttpServer method createNettyHttpService.
/**
* Creates a {@link NettyHttpService} from the given host, and list of {@link HandlerDelegatorContext}s
*
* @param program Program that contains the handler
* @param host the host which the service will run on
* @param delegatorContexts the list {@link HandlerDelegatorContext}
* @param metricsContext a {@link MetricsContext} for metrics collection
*
* @return a NettyHttpService which delegates to the {@link HttpServiceHandler}s to handle the HTTP requests
*/
private NettyHttpService createNettyHttpService(Program program, String host, Iterable<HandlerDelegatorContext> delegatorContexts, MetricsContext metricsContext) {
// The service URI is always prefixed for routing purpose
String pathPrefix = String.format("%s/namespaces/%s/apps/%s/services/%s/methods", Constants.Gateway.API_VERSION_3, program.getNamespaceId(), program.getApplicationId(), program.getName());
String versionId = program.getId().getVersion();
String versionedPathPrefix = String.format("%s/namespaces/%s/apps/%s/versions/%s/services/%s/methods", Constants.Gateway.API_VERSION_3, program.getNamespaceId(), program.getApplicationId(), versionId, program.getName());
// Create HttpHandlers which delegate to the HttpServiceHandlers
HttpHandlerFactory factory = new HttpHandlerFactory(pathPrefix, metricsContext);
HttpHandlerFactory versionedFactory = new HttpHandlerFactory(versionedPathPrefix, metricsContext);
List<HttpHandler> nettyHttpHandlers = Lists.newArrayList();
// get the runtime args from the twill context
for (HandlerDelegatorContext context : delegatorContexts) {
nettyHttpHandlers.add(factory.createHttpHandler(context.getHandlerType(), context));
nettyHttpHandlers.add(versionedFactory.createHttpHandler(context.getHandlerType(), context));
}
NettyHttpService.Builder builder = NettyHttpService.builder(program.getName() + "-http").setHost(host).setPort(0).addHttpHandlers(nettyHttpHandlers);
// These properties are for unit-test only. Currently they are not controllable by the user program
String threadPoolSize = System.getProperty(THREAD_POOL_SIZE);
if (threadPoolSize != null) {
builder.setExecThreadPoolSize(Integer.parseInt(threadPoolSize));
}
String threadAliveSec = System.getProperty(THREAD_KEEP_ALIVE_SECONDS);
if (threadAliveSec != null) {
builder.setExecThreadKeepAliveSeconds(Long.parseLong(threadAliveSec));
}
return builder.build();
}
use of co.cask.http.NettyHttpService in project cdap by caskdata.
the class UGIProviderTest method testRemoteUGIProvider.
@Test
public void testRemoteUGIProvider() throws Exception {
// Starts a mock server to handle remote UGI requests
final NettyHttpService httpService = NettyHttpService.builder("remoteUGITest").addHttpHandlers(Collections.singleton(new UGIProviderTestHandler())).build();
httpService.startAndWait();
setKeytabDir(localKeytabDirPath.getAbsolutePath());
OwnerAdmin ownerAdmin = getOwnerAdmin();
// add an owner for stream
ownerAdmin.add(aliceEntity, aliceKerberosPrincipalId);
try {
InMemoryDiscoveryService discoveryService = new InMemoryDiscoveryService();
discoveryService.register(new Discoverable(Constants.Service.APP_FABRIC_HTTP, httpService.getBindAddress()));
RemoteUGIProvider ugiProvider = new RemoteUGIProvider(cConf, discoveryService, locationFactory);
ImpersonationRequest aliceImpRequest = new ImpersonationRequest(aliceEntity, ImpersonatedOpType.OTHER);
UGIWithPrincipal aliceUGIWithPrincipal = ugiProvider.getConfiguredUGI(aliceImpRequest);
// Shouldn't be a kerberos UGI
Assert.assertFalse(aliceUGIWithPrincipal.getUGI().hasKerberosCredentials());
// Validate the credentials
Token<? extends TokenIdentifier> token = aliceUGIWithPrincipal.getUGI().getCredentials().getToken(new Text("entity"));
Assert.assertArrayEquals(aliceEntity.toString().getBytes(StandardCharsets.UTF_8), token.getIdentifier());
Assert.assertArrayEquals(aliceEntity.toString().getBytes(StandardCharsets.UTF_8), token.getPassword());
Assert.assertEquals(new Text("entity"), token.getKind());
Assert.assertEquals(new Text("service"), token.getService());
token = aliceUGIWithPrincipal.getUGI().getCredentials().getToken(new Text("opType"));
Assert.assertArrayEquals(aliceImpRequest.getImpersonatedOpType().toString().getBytes(StandardCharsets.UTF_8), token.getIdentifier());
Assert.assertArrayEquals(aliceImpRequest.getImpersonatedOpType().toString().getBytes(StandardCharsets.UTF_8), token.getPassword());
Assert.assertEquals(new Text("opType"), token.getKind());
Assert.assertEquals(new Text("service"), token.getService());
// Fetch it again, it should return the same UGI due to caching
Assert.assertSame(aliceUGIWithPrincipal, ugiProvider.getConfiguredUGI(aliceImpRequest));
// Invalid the cache and fetch it again. A different UGI should be returned
ugiProvider.invalidCache();
Assert.assertNotSame(aliceUGIWithPrincipal, ugiProvider.getConfiguredUGI(aliceImpRequest));
} finally {
httpService.stopAndWait();
}
// cleanup
ownerAdmin.delete(aliceEntity);
}
use of co.cask.http.NettyHttpService in project cdap by caskdata.
the class HttpHandlerGeneratorTest method testContentProducer.
@Test
public void testContentProducer() throws Exception {
MetricsContext noOpsMetricsContext = new NoOpMetricsCollectionService().getContext(new HashMap<String, String>());
HttpHandlerFactory factory = new HttpHandlerFactory("/content", noOpsMetricsContext);
// Create the file upload handler and starts a netty server with it
final File outputDir = TEMP_FOLDER.newFolder();
HttpHandler httpHandler = factory.createHttpHandler(TypeToken.of(FileHandler.class), new AbstractDelegatorContext<FileHandler>() {
@Override
protected FileHandler createHandler() {
return new FileHandler(outputDir);
}
});
NettyHttpService service = NettyHttpService.builder().addHttpHandlers(ImmutableList.of(httpHandler)).build();
service.startAndWait();
try {
// Generate a 100K file
File file = TEMP_FOLDER.newFile();
Files.write(Strings.repeat("0123456789", 10240).getBytes(Charsets.UTF_8), file);
InetSocketAddress bindAddress = service.getBindAddress();
// Upload the generated file
URL uploadURL = new URL(String.format("http://%s:%d/content/upload/test.txt", bindAddress.getHostName(), bindAddress.getPort()));
HttpURLConnection urlConn = (HttpURLConnection) uploadURL.openConnection();
try {
urlConn.setDoOutput(true);
urlConn.setRequestMethod("PUT");
Files.copy(file, urlConn.getOutputStream());
Assert.assertEquals(200, urlConn.getResponseCode());
} finally {
urlConn.disconnect();
}
// Download the file
File downloadFile = TEMP_FOLDER.newFile();
urlConn = (HttpURLConnection) new URL(String.format("http://%s:%d/content/download/test.txt", bindAddress.getHostName(), bindAddress.getPort())).openConnection();
try {
ByteStreams.copy(urlConn.getInputStream(), Files.newOutputStreamSupplier(downloadFile));
} finally {
urlConn.disconnect();
}
// Compare if the file content are the same
Assert.assertTrue(Files.equal(file, downloadFile));
// Download a file that doesn't exist
urlConn = (HttpURLConnection) new URL(String.format("http://%s:%d/content/download/test2.txt", bindAddress.getHostName(), bindAddress.getPort())).openConnection();
try {
Assert.assertEquals(500, urlConn.getResponseCode());
} finally {
urlConn.disconnect();
}
// Upload the file to the POST endpoint. The endpoint should response with the same file content
downloadFile = TEMP_FOLDER.newFile();
urlConn = (HttpURLConnection) uploadURL.openConnection();
try {
urlConn.setDoOutput(true);
urlConn.setRequestMethod("POST");
Files.copy(file, urlConn.getOutputStream());
ByteStreams.copy(urlConn.getInputStream(), Files.newOutputStreamSupplier(downloadFile));
Assert.assertEquals(200, urlConn.getResponseCode());
Assert.assertTrue(Files.equal(file, downloadFile));
} finally {
urlConn.disconnect();
}
} finally {
service.stopAndWait();
}
}
Aggregations