Search in sources :

Example 41 with BadRequestException

use of io.cdap.cdap.common.BadRequestException 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 42 with BadRequestException

use of io.cdap.cdap.common.BadRequestException in project cdap by caskdata.

the class RuntimeServiceRoutingHandler method openConnection.

/**
 * Opens a {@link HttpURLConnection} to the given service for the given program run.
 *
 * @throws BadRequestException if the request for service routing is not valid
 */
private HttpURLConnection openConnection(HttpRequest request, String namespace, String app, String version, String programType, String program, String run, String service) throws BadRequestException {
    ApplicationId appId = new NamespaceId(namespace).app(app, version);
    ProgramRunId programRunId = new ProgramRunId(appId, ProgramType.valueOfCategoryName(programType, BadRequestException::new), program, run);
    requestValidator.getProgramRunStatus(programRunId, request);
    Discoverable discoverable = endpointStrategyLoadingCache.getUnchecked(service).pick(2, TimeUnit.SECONDS);
    if (discoverable == null) {
        throw new ServiceUnavailableException(service);
    }
    String prefix = String.format("%s/runtime/namespaces/%s/apps/%s/versions/%s/%s/%s/runs/%s/services/%s", Constants.Gateway.INTERNAL_API_VERSION_3, namespace, app, version, programType, program, run, service);
    URI uri = URIScheme.createURI(discoverable, request.uri().substring(prefix.length()));
    try {
        URL url = uri.toURL();
        HttpURLConnection urlConn;
        try {
            urlConn = (HttpURLConnection) url.openConnection();
        } catch (IOException e) {
            // If fail to open the connection, treat it as service unavailable so that the client can retry
            throw new ServiceUnavailableException(service);
        }
        if (urlConn instanceof HttpsURLConnection) {
            new HttpsEnabler().setTrustAll(true).enable((HttpsURLConnection) urlConn);
        }
        for (Map.Entry<String, String> header : request.headers().entries()) {
            urlConn.setRequestProperty(header.getKey(), header.getValue());
        }
        urlConn.setRequestMethod(request.method().name());
        urlConn.setDoInput(true);
        return urlConn;
    } catch (MalformedURLException | ProtocolException e) {
        // This can only happen if the incoming request is bad
        throw new BadRequestException("Invalid request due to " + e.getMessage(), e);
    }
}
Also used : ProtocolException(java.net.ProtocolException) Discoverable(org.apache.twill.discovery.Discoverable) MalformedURLException(java.net.MalformedURLException) ServiceUnavailableException(io.cdap.cdap.common.ServiceUnavailableException) IOException(java.io.IOException) URI(java.net.URI) URL(java.net.URL) HttpURLConnection(java.net.HttpURLConnection) BadRequestException(io.cdap.cdap.common.BadRequestException) HttpsEnabler(io.cdap.cdap.common.security.HttpsEnabler) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) ApplicationId(io.cdap.cdap.proto.id.ApplicationId) Map(java.util.Map) HttpsURLConnection(javax.net.ssl.HttpsURLConnection)

Example 43 with BadRequestException

use of io.cdap.cdap.common.BadRequestException 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 44 with BadRequestException

use of io.cdap.cdap.common.BadRequestException in project cdap by caskdata.

the class RuntimeHandler method writeMessages.

/**
 * Handles call for writing to TMS from the program runtime for a given program run. The POST body is an
 * avro array of bytes.
 */
@Path("/topics/{topic}")
@POST
public BodyConsumer writeMessages(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("topic") String topic) throws Exception {
    if (!"avro/binary".equals(request.headers().get(HttpHeaderNames.CONTENT_TYPE))) {
        throw new BadRequestException("Only avro/binary content type is supported.");
    }
    ApplicationId appId = new NamespaceId(namespace).app(app, version);
    ProgramRunId programRunId = new ProgramRunId(appId, ProgramType.valueOfCategoryName(programType, BadRequestException::new), program, run);
    ProgramRunInfo programRunInfo = requestValidator.getProgramRunStatus(programRunId, request);
    if (!allowedTopics.contains(topic)) {
        throw new UnauthorizedException("Access denied for topic " + topic);
    }
    TopicId topicId = NamespaceId.SYSTEM.topic(topic);
    if (topic.startsWith(logsTopicPrefix)) {
        return new MessageBodyConsumer(topicId, logProcessor::process, programRunInfo);
    }
    return new MessageBodyConsumer(topicId, payloads -> {
        try {
            messagingContext.getDirectMessagePublisher().publish(topicId.getNamespace(), topicId.getTopic(), payloads);
        } catch (TopicNotFoundException e) {
            throw new BadRequestException(e);
        }
    }, programRunInfo);
}
Also used : TopicNotFoundException(io.cdap.cdap.api.messaging.TopicNotFoundException) UnauthorizedException(io.cdap.cdap.security.spi.authorization.UnauthorizedException) BadRequestException(io.cdap.cdap.common.BadRequestException) TopicId(io.cdap.cdap.proto.id.TopicId) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) ApplicationId(io.cdap.cdap.proto.id.ApplicationId) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST)

Example 45 with BadRequestException

use of io.cdap.cdap.common.BadRequestException in project cdap by caskdata.

the class StoreHandler method createStoreRequest.

/**
 * Creates a {@link StoreRequest} instance based on the given {@link HttpRequest}.
 */
private StoreRequest createStoreRequest(TopicId topicId, HttpRequest request, InputStream is) throws BadRequestException, IOException {
    // Currently only support avro
    if (!"avro/binary".equals(request.headers().get(HttpHeaderNames.CONTENT_TYPE))) {
        throw new BadRequestException("Only avro/binary content type is supported.");
    }
    Decoder decoder = DecoderFactory.get().directBinaryDecoder(is, null);
    DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(Schemas.V1.PublishRequest.SCHEMA);
    return new GenericRecordStoreRequest(topicId, datumReader.read(null, decoder));
}
Also used : GenericDatumReader(org.apache.avro.generic.GenericDatumReader) BadRequestException(io.cdap.cdap.common.BadRequestException) Decoder(org.apache.avro.io.Decoder) GenericRecord(org.apache.avro.generic.GenericRecord)

Aggregations

BadRequestException (io.cdap.cdap.common.BadRequestException)188 Path (javax.ws.rs.Path)68 NamespaceId (io.cdap.cdap.proto.id.NamespaceId)54 IOException (java.io.IOException)46 JsonSyntaxException (com.google.gson.JsonSyntaxException)44 NotFoundException (io.cdap.cdap.common.NotFoundException)42 ApplicationId (io.cdap.cdap.proto.id.ApplicationId)42 POST (javax.ws.rs.POST)42 HttpResponse (io.cdap.common.http.HttpResponse)36 ByteBufInputStream (io.netty.buffer.ByteBufInputStream)34 URL (java.net.URL)34 ProgramType (io.cdap.cdap.proto.ProgramType)30 InputStreamReader (java.io.InputStreamReader)28 Reader (java.io.Reader)28 ArrayList (java.util.ArrayList)28 AuditPolicy (io.cdap.cdap.common.security.AuditPolicy)26 ProgramId (io.cdap.cdap.proto.id.ProgramId)26 ServiceUnavailableException (io.cdap.cdap.common.ServiceUnavailableException)24 GET (javax.ws.rs.GET)24 ProgramRunId (io.cdap.cdap.proto.id.ProgramRunId)22