use of org.jboss.netty.handler.codec.http.DefaultHttpResponse in project voldemort by voldemort.
the class GetAllResponseSender method sendResponse.
/**
* Sends nested multipart response. Outer multipart wraps all the keys
* requested. Each key has a separate multipart for the versioned values.
*/
@Override
public void sendResponse(StoreStats performanceStats, boolean isFromLocalZone, long startTimeInMs) throws Exception {
/*
* Pay attention to the code below. Note that in this method we wrap a multiPart object with a mimeMessage.
* However when writing to the outputStream we only send the multiPart object and not the entire
* mimeMessage. This is intentional.
*
* In the earlier version of this code we used to create a multiPart object and just send that multiPart
* across the wire.
*
* However, we later discovered that upon setting the content of a MimeBodyPart, JavaMail internally creates
* a DataHandler object wrapping the object you passed in. The part's Content-Type header is not updated
* immediately. In order to get the headers updated, one needs to to call MimeMessage.saveChanges() on the
* enclosing message, which cascades down the MIME structure into a call to MimeBodyPart.updateHeaders()
* on the body part. It's this updateHeaders call that transfers the content type from the
* DataHandler to the part's MIME Content-Type header.
*
* To make sure that the Content-Type headers are being updated (without changing too much code), we decided
* to wrap the multiPart in a mimeMessage, call mimeMessage.saveChanges() and then just send the multiPart.
* This is to make sure multiPart's headers are updated accurately.
*/
MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
// multiPartKeys is the outer multipart
MimeMultipart multiPartKeys = new MimeMultipart();
ByteArrayOutputStream keysOutputStream = new ByteArrayOutputStream();
for (Entry<ByteArray, List<Versioned<byte[]>>> entry : versionedResponses.entrySet()) {
ByteArray key = entry.getKey();
String base64Key = RestUtils.encodeVoldemortKey(key.get());
String contentLocationKey = "/" + this.storeName + "/" + base64Key;
// Create the individual body part - for each key requested
MimeBodyPart keyBody = new MimeBodyPart();
try {
// Add the right headers
keyBody.addHeader(CONTENT_TYPE, "application/octet-stream");
keyBody.addHeader(CONTENT_TRANSFER_ENCODING, "binary");
keyBody.addHeader(CONTENT_LOCATION, contentLocationKey);
} catch (MessagingException me) {
logger.error("Exception while constructing key body headers", me);
keysOutputStream.close();
throw me;
}
// multiPartValues is the inner multipart
MimeMultipart multiPartValues = new MimeMultipart();
for (Versioned<byte[]> versionedValue : entry.getValue()) {
byte[] responseValue = versionedValue.getValue();
VectorClock vectorClock = (VectorClock) versionedValue.getVersion();
String eTag = RestUtils.getSerializedVectorClock(vectorClock);
numVectorClockEntries += vectorClock.getVersionMap().size();
// Create the individual body part - for each versioned value of
// a key
MimeBodyPart valueBody = new MimeBodyPart();
try {
// Add the right headers
valueBody.addHeader(CONTENT_TYPE, "application/octet-stream");
valueBody.addHeader(CONTENT_TRANSFER_ENCODING, "binary");
valueBody.addHeader(RestMessageHeaders.X_VOLD_VECTOR_CLOCK, eTag);
valueBody.setContent(responseValue, "application/octet-stream");
valueBody.addHeader(RestMessageHeaders.CONTENT_LENGTH, Integer.toString(responseValue.length));
multiPartValues.addBodyPart(valueBody);
} catch (MessagingException me) {
logger.error("Exception while constructing value body part", me);
keysOutputStream.close();
throw me;
}
}
try {
// Add the inner multipart as the content of the outer body part
keyBody.setContent(multiPartValues);
multiPartKeys.addBodyPart(keyBody);
} catch (MessagingException me) {
logger.error("Exception while constructing key body part", me);
keysOutputStream.close();
throw me;
}
}
message.setContent(multiPartKeys);
message.saveChanges();
try {
multiPartKeys.writeTo(keysOutputStream);
} catch (Exception e) {
logger.error("Exception while writing mutipart to output stream", e);
throw e;
}
ChannelBuffer responseContent = ChannelBuffers.dynamicBuffer();
responseContent.writeBytes(keysOutputStream.toByteArray());
// Create the Response object
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
// Set the right headers
response.setHeader(CONTENT_TYPE, "multipart/binary");
response.setHeader(CONTENT_TRANSFER_ENCODING, "binary");
// Copy the data into the payload
response.setContent(responseContent);
response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes());
// Write the response to the Netty Channel
if (logger.isDebugEnabled()) {
String keyStr = getKeysHexString(this.versionedResponses.keySet());
debugLog("GET_ALL", this.storeName, keyStr, startTimeInMs, System.currentTimeMillis(), numVectorClockEntries);
}
this.messageEvent.getChannel().write(response);
if (performanceStats != null && isFromLocalZone) {
recordStats(performanceStats, startTimeInMs, Tracked.GET_ALL);
}
keysOutputStream.close();
}
use of org.jboss.netty.handler.codec.http.DefaultHttpResponse in project voldemort by voldemort.
the class GetMetadataResponseSender method sendResponse.
/**
* Sends a normal HTTP response containing the serialization information in
* a XML format
*/
@Override
public void sendResponse(StoreStats performanceStats, boolean isFromLocalZone, long startTimeInMs) throws Exception {
ChannelBuffer responseContent = ChannelBuffers.dynamicBuffer(this.responseValue.length);
responseContent.writeBytes(responseValue);
// 1. Create the Response object
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
// 2. Set the right headers
response.setHeader(CONTENT_TYPE, "binary");
response.setHeader(CONTENT_TRANSFER_ENCODING, "binary");
// 3. Copy the data into the payload
response.setContent(responseContent);
response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes());
if (logger.isDebugEnabled()) {
logger.debug("Response = " + response);
}
// Write the response to the Netty Channel
this.messageEvent.getChannel().write(response);
if (performanceStats != null && isFromLocalZone) {
recordStats(performanceStats, startTimeInMs, Tracked.GET);
}
}
use of org.jboss.netty.handler.codec.http.DefaultHttpResponse in project voldemort by voldemort.
the class RestErrorHandler method writeErrorResponse.
/**
* Writes all error responses to the client.
*
* TODO REST-Server 1. collect error stats
*
* @param messageEvent - for retrieving the channel details
* @param status - error code
* @param message - error message
*/
public static void writeErrorResponse(MessageEvent messageEvent, HttpResponseStatus status, String message) {
// Create the Response object
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
response.setContent(ChannelBuffers.copiedBuffer("Failure: " + status.toString() + ". " + message + "\r\n", CharsetUtil.UTF_8));
response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes());
// Write the response to the Netty Channel
messageEvent.getChannel().write(response);
}
use of org.jboss.netty.handler.codec.http.DefaultHttpResponse in project voldemort by voldemort.
the class CoordinatorAdminRequestHandler method sendResponse.
public HttpResponse sendResponse(HttpResponseStatus responseCode, String responseBody) {
String actualResponseBody = responseBody + "\n";
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, responseCode);
response.setHeader(CONTENT_LENGTH, actualResponseBody.length());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
outputStream.write(actualResponseBody.getBytes());
} catch (IOException e) {
logger.error("IOException while trying to write the outputStream for an admin response", e);
throw new RuntimeException(e);
}
ChannelBuffer responseContent = ChannelBuffers.dynamicBuffer();
responseContent.writeBytes(outputStream.toByteArray());
response.setContent(responseContent);
if (logger.isDebugEnabled()) {
logger.debug("Sent " + response);
}
return response;
}
use of org.jboss.netty.handler.codec.http.DefaultHttpResponse in project cdap by caskdata.
the class SecurityAuthenticationHttpHandler method validateSecuredInterception.
/**
* Intercepts the HttpMessage for getting the access token in authorization header
*
* @param ctx channel handler context delegated from MessageReceived callback
* @param msg intercepted HTTP message
* @param inboundChannel
* @return {@code true} if the HTTP message has valid Access token
* @throws Exception
*/
private boolean validateSecuredInterception(ChannelHandlerContext ctx, HttpRequest msg, Channel inboundChannel, AuditLogEntry logEntry) throws Exception {
String auth = msg.getHeader(HttpHeaders.Names.AUTHORIZATION);
String accessToken = null;
/*
* Parse the access token from authorization header. The header will be in the form:
* Authorization: Bearer ACCESSTOKEN
*
* where ACCESSTOKEN is the base64 encoded serialized AccessToken instance.
*/
if (auth != null) {
int spIndex = auth.trim().indexOf(' ');
if (spIndex != -1) {
accessToken = auth.substring(spIndex + 1).trim();
}
}
HttpMethod httpMethod = msg.getMethod();
String uri = msg.getUri();
logEntry.setClientIP(((InetSocketAddress) ctx.getChannel().getRemoteAddress()).getAddress());
logEntry.setRequestLine(httpMethod, uri, msg.getProtocolVersion());
TokenState tokenState = tokenValidator.validate(accessToken);
if (!tokenState.isValid()) {
HttpResponse httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.UNAUTHORIZED);
logEntry.setResponseCode(HttpResponseStatus.UNAUTHORIZED.getCode());
JsonObject jsonObject = new JsonObject();
if (tokenState == TokenState.MISSING) {
httpResponse.addHeader(HttpHeaders.Names.WWW_AUTHENTICATE, String.format("Bearer realm=\"%s\"", realm));
LOG.debug("Authentication failed due to missing token");
} else {
httpResponse.addHeader(HttpHeaders.Names.WWW_AUTHENTICATE, String.format("Bearer realm=\"%s\" error=\"invalid_token\"" + " error_description=\"%s\"", realm, tokenState.getMsg()));
jsonObject.addProperty("error", "invalid_token");
jsonObject.addProperty("error_description", tokenState.getMsg());
LOG.debug("Authentication failed due to invalid token, reason={};", tokenState);
}
JsonArray externalAuthenticationURIs = new JsonArray();
// Waiting for service to get discovered
stopWatchWait(externalAuthenticationURIs);
jsonObject.add("auth_uri", externalAuthenticationURIs);
ChannelBuffer content = ChannelBuffers.wrappedBuffer(jsonObject.toString().getBytes(Charsets.UTF_8));
httpResponse.setContent(content);
int contentLength = content.readableBytes();
httpResponse.setHeader(HttpHeaders.Names.CONTENT_LENGTH, contentLength);
httpResponse.setHeader(HttpHeaders.Names.CONTENT_TYPE, "application/json;charset=UTF-8");
logEntry.setResponseContentLength(new Long(contentLength));
ChannelFuture writeFuture = Channels.future(inboundChannel);
Channels.write(ctx, writeFuture, httpResponse);
writeFuture.addListener(ChannelFutureListener.CLOSE);
return false;
} else {
AccessTokenTransformer.AccessTokenIdentifierPair accessTokenIdentifierPair = accessTokenTransformer.transform(accessToken);
AuditLogContent auditLogContent = AUDIT_LOG_LOOKUP_METHOD.contains(httpMethod) ? AUDIT_LOOK_UP.getAuditLogContent(msg.getUri(), httpMethod) : null;
if (auditLogContent != null) {
List<String> headerNames = auditLogContent.getHeaderNames();
if (!headerNames.isEmpty()) {
Map<String, String> headers = new HashMap<>();
for (String headerName : headerNames) {
headers.put(headerName, msg.getHeader(headerName));
}
logEntry.setHeaders(headers);
}
if (auditLogContent.isLogRequestBody()) {
ChannelBuffer body = msg.getContent();
if (body.readable()) {
logEntry.setRequestBody(body.toString(Charsets.UTF_8));
}
}
logEntry.setLogResponseBody(auditLogContent.isLogResponsebody());
}
logEntry.setUserName(accessTokenIdentifierPair.getAccessTokenIdentifierObj().getUsername());
msg.setHeader(HttpHeaders.Names.AUTHORIZATION, "CDAP-verified " + accessTokenIdentifierPair.getAccessTokenIdentifierStr());
msg.setHeader(Constants.Security.Headers.USER_ID, accessTokenIdentifierPair.getAccessTokenIdentifierObj().getUsername());
msg.setHeader(Constants.Security.Headers.USER_IP, ((InetSocketAddress) ctx.getChannel().getRemoteAddress()).getAddress().getHostAddress());
return true;
}
}
Aggregations