Search in sources :

Example 1 with BodyConsumer

use of io.cdap.http.BodyConsumer in project cdap by caskdata.

the class RuntimeServiceRoutingHandler method routeServiceWithBody.

/**
 * Handles PUT and POST calls from program runtime to access CDAP services.
 * It simply verify the request and forward the call to internal CDAP services.
 */
@Path("/services/{service}/**")
@PUT
@POST
public BodyConsumer routeServiceWithBody(HttpRequest request, HttpResponder responder, @PathParam("namespace") String namespace, @PathParam("app") String app, @PathParam("version") String version, @PathParam("program-type") String programType, @PathParam("program") String program, @PathParam("run") String run, @PathParam("service") String service) throws Exception {
    HttpURLConnection urlConn = openConnection(request, namespace, app, version, programType, program, run, service);
    urlConn.setDoOutput(true);
    OutputStream output;
    try {
        output = urlConn.getOutputStream();
    } catch (UnknownServiceException e) {
        throw new BadRequestException(e.getMessage(), e);
    } catch (IOException e) {
        // If fails to get output stream, treat it as service unavailable so that the client can retry
        throw new ServiceUnavailableException(service, e);
    }
    return new BodyConsumer() {

        @Override
        public void chunk(ByteBuf byteBuf, HttpResponder httpResponder) {
            try {
                byteBuf.readBytes(output, byteBuf.readableBytes());
            } catch (IOException e) {
                throw new ServiceUnavailableException(service, e);
            }
        }

        @Override
        public void finished(HttpResponder httpResponder) {
            try {
                output.close();
            } catch (IOException e) {
                throw new ServiceUnavailableException(service, e);
            }
            try {
                ResponseInfo responseInfo = new ResponseInfo(service, urlConn);
                responder.sendContent(HttpResponseStatus.valueOf(responseInfo.getResponseCode()), new RelayBodyProducer(urlConn.getURL(), responseInfo), responseInfo.getHeaders());
            } catch (BadRequestException e) {
                throw new ServiceException(e, HttpResponseStatus.BAD_REQUEST);
            }
        }

        @Override
        public void handleError(Throwable throwable) {
            LOG.warn("Exception raised for call to {}", urlConn.getURL(), throwable);
        }
    };
}
Also used : HttpResponder(io.cdap.http.HttpResponder) UnknownServiceException(java.net.UnknownServiceException) OutputStream(java.io.OutputStream) IOException(java.io.IOException) ServiceUnavailableException(io.cdap.cdap.common.ServiceUnavailableException) ByteBuf(io.netty.buffer.ByteBuf) HttpURLConnection(java.net.HttpURLConnection) UnknownServiceException(java.net.UnknownServiceException) ServiceException(io.cdap.cdap.common.ServiceException) BadRequestException(io.cdap.cdap.common.BadRequestException) BodyConsumer(io.cdap.http.BodyConsumer) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) PUT(javax.ws.rs.PUT)

Example 2 with BodyConsumer

use of io.cdap.http.BodyConsumer in project cdap by caskdata.

the class RuntimeHandler method writeSparkEventLogs.

/**
 * Handles call for Spark event logs upload.
 */
@Path("/spark-event-logs/{id}")
@POST
public BodyConsumer writeSparkEventLogs(HttpRequest request, HttpResponder responder, @PathParam("namespace") String namespace, @PathParam("app") String app, @PathParam("version") String version, @PathParam("program-type") String programType, @PathParam("program") String program, @PathParam("run") String run, @PathParam("id") String id) throws Exception {
    if (!eventLogsEnabled) {
        throw new UnsupportedOperationException("Spark event logs collection is not enabled");
    }
    if (!MediaType.APPLICATION_OCTET_STREAM.equals(request.headers().get(HttpHeaderNames.CONTENT_TYPE))) {
        throw new BadRequestException("Only application/octet-stream content type is supported.");
    }
    ApplicationId appId = new NamespaceId(namespace).app(app, version);
    ProgramRunId programRunId = new ProgramRunId(appId, ProgramType.valueOfCategoryName(programType, BadRequestException::new), program, run);
    requestValidator.getProgramRunStatus(programRunId, request);
    Location location = eventLogsBaseLocation.append(String.format("%s-%s-%s-%s-%s", namespace, app, program, run, id));
    if (location.exists()) {
        LOG.debug("Deleting event logs location {} for program run {}", location, programRunId);
        location.delete(true);
    }
    OutputStream os = location.getOutputStream();
    return new BodyConsumer() {

        @Override
        public void chunk(ByteBuf request, HttpResponder responder) {
            try {
                request.readBytes(os, request.readableBytes());
            } catch (IOException e) {
                throw new RuntimeException("Failed to write spark event logs to " + location, e);
            }
        }

        @Override
        public void finished(HttpResponder responder) {
            try {
                os.close();
                responder.sendStatus(HttpResponseStatus.OK);
            } catch (IOException e) {
                throw new RuntimeException("Failed to close spark event logs output stream for " + location, e);
            }
        }

        @Override
        public void handleError(Throwable cause) {
            LOG.error("Failed to write spark event logs for {}", programRunId, cause);
            Closeables.closeQuietly(os);
            try {
                location.delete();
            } catch (IOException e) {
                LOG.error("Failed to delete obsolete event logs location {}", location, e);
            }
        }
    };
}
Also used : HttpResponder(io.cdap.http.HttpResponder) OutputStream(java.io.OutputStream) IOException(java.io.IOException) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) ByteBuf(io.netty.buffer.ByteBuf) BadRequestException(io.cdap.cdap.common.BadRequestException) BodyConsumer(io.cdap.http.BodyConsumer) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) ApplicationId(io.cdap.cdap.proto.id.ApplicationId) Location(org.apache.twill.filesystem.Location) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST)

Example 3 with BodyConsumer

use of io.cdap.http.BodyConsumer in project cdap by caskdata.

the class AbstractHttpHandlerDelegator method wrapContentConsumer.

/**
 * Returns a new instance of {@link BodyConsumer} that wraps around the given {@link HttpContentConsumer}
 * and {@link DelayedHttpServiceResponder}.
 *
 * IMPORTANT: This method will also capture the context associated with the current thread, hence after
 * this method is called, no other methods on this class should be called from the current thread.
 *
 * This method is called from handler class generated by {@link HttpHandlerGenerator}.
 */
@SuppressWarnings("unused")
protected final BodyConsumer wrapContentConsumer(HttpContentConsumer consumer, DelayedHttpServiceResponder responder, TransactionControl defaultTxControl) {
    Preconditions.checkState(!responder.hasBufferedResponse(), "HttpContentConsumer may not be used after a response has already been sent.");
    // Close the provided responder since a new one will be created for the BodyConsumerAdapter to use.
    responder.close();
    ServiceTaskExecutor taskExecutor = context.getServiceTaskExecutor();
    Cancellable contextReleaser = context.capture();
    return new BodyConsumerAdapter(new DelayedHttpServiceResponder(responder, (contentProducer, txServiceContext) -> new BodyProducerAdapter(contentProducer, txServiceContext, contextReleaser, defaultTxControl)), consumer, taskExecutor, contextReleaser, defaultTxControl);
}
Also used : HttpRequest(io.netty.handler.codec.http.HttpRequest) BodyConsumer(io.cdap.http.BodyConsumer) HttpResponder(io.cdap.http.HttpResponder) HttpContentConsumer(io.cdap.cdap.api.service.http.HttpContentConsumer) HandlerContext(io.cdap.http.HandlerContext) HttpHandler(io.cdap.http.HttpHandler) MetricsContext(io.cdap.cdap.api.metrics.MetricsContext) HttpContentProducer(io.cdap.cdap.api.service.http.HttpContentProducer) BodyProducer(io.cdap.http.BodyProducer) TransactionControl(io.cdap.cdap.api.annotation.TransactionControl) HttpServiceRequest(io.cdap.cdap.api.service.http.HttpServiceRequest) ThrowingRunnable(io.cdap.cdap.internal.app.runtime.ThrowingRunnable) Preconditions(com.google.common.base.Preconditions) Cancellable(org.apache.twill.common.Cancellable) CombineClassLoader(io.cdap.cdap.common.lang.CombineClassLoader) Cancellable(org.apache.twill.common.Cancellable)

Example 4 with BodyConsumer

use of io.cdap.http.BodyConsumer in project cdap by caskdata.

the class AppFabricClient method deployApplication.

public void deployApplication(ApplicationId appId, AppRequest appRequest) throws Exception {
    HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, String.format("%s/apps/%s/versions/%s/create", getNamespacePath(appId.getNamespace()), appId.getApplication(), appId.getVersion()));
    request.headers().set(Constants.Gateway.API_KEY, "api-key-example");
    HttpUtil.setTransferEncodingChunked(request, true);
    MockResponder mockResponder = new MockResponder();
    BodyConsumer bodyConsumer = appLifecycleHttpHandler.createAppVersion(request, mockResponder, appId.getNamespace(), appId.getApplication(), appId.getVersion());
    Preconditions.checkNotNull(bodyConsumer, "BodyConsumer from deploy call should not be null");
    bodyConsumer.chunk(Unpooled.copiedBuffer(GSON.toJson(appRequest), StandardCharsets.UTF_8), mockResponder);
    bodyConsumer.finished(mockResponder);
    verifyResponse(HttpResponseStatus.OK, mockResponder.getStatus(), "Failed to deploy app (" + mockResponder.getResponseContentAsString() + ")");
}
Also used : DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) DefaultHttpRequest(io.netty.handler.codec.http.DefaultHttpRequest) HttpRequest(io.netty.handler.codec.http.HttpRequest) FullHttpRequest(io.netty.handler.codec.http.FullHttpRequest) DefaultHttpRequest(io.netty.handler.codec.http.DefaultHttpRequest) BodyConsumer(io.cdap.http.BodyConsumer)

Example 5 with BodyConsumer

use of io.cdap.http.BodyConsumer in project cdap by caskdata.

the class AppFabricClient method deployApplication.

public Location deployApplication(Id.Namespace namespace, Class<?> applicationClz, String config, @Nullable KerberosPrincipalId ownerPrincipal, File... bundleEmbeddedJars) throws Exception {
    Preconditions.checkNotNull(applicationClz, "Application cannot be null.");
    Location deployedJar = AppJarHelper.createDeploymentJar(locationFactory, applicationClz, bundleEmbeddedJars);
    LOG.info("Created deployedJar at {}", deployedJar);
    String archiveName = String.format("%s-1.0.%d.jar", applicationClz.getSimpleName(), System.currentTimeMillis());
    FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, String.format("/v3/namespaces/%s/apps", namespace.getId()));
    request.headers().set(Constants.Gateway.API_KEY, "api-key-example");
    request.headers().set(AbstractAppFabricHttpHandler.ARCHIVE_NAME_HEADER, archiveName);
    if (config != null) {
        request.headers().set(AbstractAppFabricHttpHandler.APP_CONFIG_HEADER, config);
    }
    String owner = null;
    if (ownerPrincipal != null) {
        owner = GSON.toJson(ownerPrincipal, KerberosPrincipalId.class);
        request.headers().set(AbstractAppFabricHttpHandler.PRINCIPAL_HEADER, owner);
    }
    MockResponder mockResponder = new MockResponder();
    BodyConsumer bodyConsumer = appLifecycleHttpHandler.deploy(request, mockResponder, namespace.getId(), archiveName, config, owner, true);
    Preconditions.checkNotNull(bodyConsumer, "BodyConsumer from deploy call should not be null");
    try (BufferFileInputStream is = new BufferFileInputStream(deployedJar.getInputStream(), 100 * 1024)) {
        byte[] chunk = is.read();
        while (chunk.length > 0) {
            mockResponder = new MockResponder();
            bodyConsumer.chunk(Unpooled.wrappedBuffer(chunk), mockResponder);
            Preconditions.checkState(mockResponder.getStatus() == null, "failed to deploy app");
            chunk = is.read();
        }
        mockResponder = new MockResponder();
        bodyConsumer.finished(mockResponder);
        verifyResponse(HttpResponseStatus.OK, mockResponder.getStatus(), "Failed to deploy app (" + mockResponder.getResponseContentAsString() + ")");
    }
    return deployedJar;
}
Also used : DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) FullHttpRequest(io.netty.handler.codec.http.FullHttpRequest) DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) BodyConsumer(io.cdap.http.BodyConsumer) KerberosPrincipalId(io.cdap.cdap.proto.id.KerberosPrincipalId) BufferFileInputStream(io.cdap.cdap.internal.app.BufferFileInputStream) Location(org.apache.twill.filesystem.Location)

Aggregations

BodyConsumer (io.cdap.http.BodyConsumer)5 HttpResponder (io.cdap.http.HttpResponder)3 BadRequestException (io.cdap.cdap.common.BadRequestException)2 ByteBuf (io.netty.buffer.ByteBuf)2 DefaultFullHttpRequest (io.netty.handler.codec.http.DefaultFullHttpRequest)2 FullHttpRequest (io.netty.handler.codec.http.FullHttpRequest)2 HttpRequest (io.netty.handler.codec.http.HttpRequest)2 IOException (java.io.IOException)2 OutputStream (java.io.OutputStream)2 POST (javax.ws.rs.POST)2 Path (javax.ws.rs.Path)2 Location (org.apache.twill.filesystem.Location)2 Preconditions (com.google.common.base.Preconditions)1 TransactionControl (io.cdap.cdap.api.annotation.TransactionControl)1 MetricsContext (io.cdap.cdap.api.metrics.MetricsContext)1 HttpContentConsumer (io.cdap.cdap.api.service.http.HttpContentConsumer)1 HttpContentProducer (io.cdap.cdap.api.service.http.HttpContentProducer)1 HttpServiceRequest (io.cdap.cdap.api.service.http.HttpServiceRequest)1 ServiceException (io.cdap.cdap.common.ServiceException)1 ServiceUnavailableException (io.cdap.cdap.common.ServiceUnavailableException)1