@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) throws Exception { if (event.getMessage() instanceof MappingHttpRequest) { MappingHttpRequest httpRequest = (MappingHttpRequest) event.getMessage(); if (httpRequest.getMessage() instanceof ObjectStorageDataRequestType) { if (httpRequest.isChunked()) { // Chunked request, and beginning, setup map etc. initializeNewPut(ctx, (ObjectStorageDataRequestType) httpRequest.getMessage()); } } } else if (event.getMessage() instanceof HttpChunk) { // Add the chunk to the current streams channel buffer. HttpChunk chunk = (HttpChunk) event.getMessage(); appendChunk(chunk.getContent(), ctx.getChannel()); if (chunk.isLast()) { // Remove from the map Logs.extreme() .debug( "Removing data map due to last chunk processed event for channel: " + ctx.getChannel().getId()); dataMap.remove(ctx.getChannel()); } } // Always pass it on ctx.sendUpstream(event); }
@Override protected void encodeInitialLine(final ChannelBuffer buf, final HttpMessage message) throws Exception { final MappingHttpRequest request = (MappingHttpRequest) message; buf.writeBytes(request.getMethod().toString().getBytes("ASCII")); buf.writeByte(HttpUtils.SP); buf.writeBytes(request.getServicePath().getBytes("ASCII")); buf.writeByte(HttpUtils.SP); buf.writeBytes(request.getProtocolVersion().toString().getBytes("ASCII")); buf.writeBytes(HttpUtils.CRLF); }
static void sendRedirect( final ChannelHandlerContext ctx, final ChannelEvent e, final Class<? extends ComponentId> compClass, final MappingHttpRequest request) { e.getFuture().cancel(); String redirectUri = null; if (Topology.isEnabled(compClass)) { // have an enabled service, lets use that final URI serviceUri = ServiceUris.remote(Topology.lookup(compClass)); redirectUri = serviceUri.toASCIIString() + request.getServicePath().replace(serviceUri.getPath(), ""); } else if (Topology.isEnabled( Eucalyptus.class)) { // can't find service info, redirect via clc master final URI serviceUri = ServiceUris.remote(Topology.lookup(Eucalyptus.class)); redirectUri = serviceUri.toASCIIString().replace(Eucalyptus.INSTANCE.getServicePath(), "") + request.getServicePath().replace(serviceUri.getPath(), ""); } HttpResponse response = null; if (redirectUri == null || isRedirectLoop(request, redirectUri)) { response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.SERVICE_UNAVAILABLE); if (Logs.isDebug()) { String errorMessage = "Failed to lookup service for " + Components.lookup(compClass).getName() + " for path " + request.getServicePath() + ".\nCurrent state: \n\t" + Joiner.on("\n\t").join(Topology.enabledServices()); byte[] errorBytes = Exceptions.string(new ServiceStateException(errorMessage)).getBytes(); response.setContent(ChannelBuffers.wrappedBuffer(errorBytes)); } } else { response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.TEMPORARY_REDIRECT); if (request.getQuery() != null) { redirectUri += "?" + request.getQuery(); } response.setHeader(HttpHeaders.Names.LOCATION, redirectUri); } response.setHeader(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE); if (ctx.getChannel().isConnected()) { ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE); } }
private final String extractOperationName(final MappingHttpRequest httpRequest) { if (httpRequest.getParameters().containsKey(this.operationParam.toString())) { return httpRequest.getParameters().get(this.operationParam.toString()); } else { for (final T param : this.altOperationParams) { if (httpRequest.getParameters().containsKey(param.toString())) { return httpRequest.getParameters().get(this.operationParam.toString()); } } } LOG.error( "Failed to find operation parameter an " + Lists.asList(this.operationParam, this.altOperationParams.toArray()).toString() + " in HTTP request: " + httpRequest); return null; }
@Override public void incomingMessage(ChannelHandlerContext ctx, MessageEvent event) throws Exception { if (event.getMessage() instanceof MappingHttpRequest) { MappingHttpRequest httpRequest = (MappingHttpRequest) event.getMessage(); if (httpRequest.getMessage() instanceof WalrusRequestType) { WalrusRequestType request = (WalrusRequestType) httpRequest.getMessage(); BucketLogData logData = request.getLogData(); if (logData != null) { long currentTime = System.currentTimeMillis(); logData.setTotalTime(currentTime); logData.setTurnAroundTime(currentTime); logData.setUri(httpRequest.getUri()); String referrer = httpRequest.getHeader(HttpHeaders.Names.REFERER); if (referrer != null) logData.setReferrer(referrer); String userAgent = httpRequest.getHeader(HttpHeaders.Names.USER_AGENT); if (userAgent != null) logData.setUserAgent(userAgent); logData.setTimestamp( String.format("[%1$td/%1$tb/%1$tY:%1$tH:%1$tM:%1$tS %1$tz]", Calendar.getInstance())); User user = Contexts.lookup(httpRequest.getCorrelationId()).getUser(); if (user != null) logData.setAccessorId(user.getUserId()); if (request.getBucket() != null) logData.setBucketName(request.getBucket()); if (request.getKey() != null) logData.setKey(request.getKey()); if (ctx.getChannel().getRemoteAddress() instanceof InetSocketAddress) { InetSocketAddress sockAddress = (InetSocketAddress) ctx.getChannel().getRemoteAddress(); logData.setSourceAddress(sockAddress.getAddress().getHostAddress()); } } } } }
@Override public void incomingMessage(ChannelHandlerContext ctx, MessageEvent event) throws Exception { if (event.getMessage() instanceof MappingHttpRequest) { MappingHttpRequest httpRequest = (MappingHttpRequest) event.getMessage(); if (httpRequest.getContent().readableBytes() == 0) { waitForNext = true; processedFirstChunk = false; this.httpRequest = httpRequest; } } else if (event.getMessage() instanceof DefaultHttpChunk) { if (!processedFirstChunk) { DefaultHttpChunk httpChunk = (DefaultHttpChunk) event.getMessage(); httpRequest.setContent(httpChunk.getContent()); processedFirstChunk = true; UpstreamMessageEvent newEvent = new UpstreamMessageEvent(ctx.getChannel(), httpRequest, null); ctx.sendUpstream(newEvent); } } }
@Override public boolean checkAccepts(final HttpRequest message) { if (message instanceof MappingHttpRequest) { final MappingHttpRequest httpRequest = (MappingHttpRequest) message; final boolean usesServicePath = Iterables.any(servicePathPrefixes, Strings.isPrefixOf(message.getUri())); final boolean noPath = message.getUri().isEmpty() || message.getUri().equals("/") || message.getUri().startsWith("/?"); if (!usesServicePath && !(noPath && resolvesByHost(message.getHeader(HttpHeaders.Names.HOST)))) { return false; } if (httpRequest.getMethod().equals(HttpMethod.POST) && !message.getHeaderNames().contains("SOAPAction")) { Map<String, String> parameters = new HashMap<String, String>(httpRequest.getParameters()); Set<String> nonQueryParameters = Sets.newHashSet(); final String query = httpRequest.getContentAsString(); for (String p : query.split("&")) { String[] splitParam = p.split("=", 2); String lhs = splitParam[0]; String rhs = splitParam.length == 2 ? splitParam[1] : null; try { if (lhs != null) lhs = new URLCodec().decode(lhs); } catch (DecoderException e) { } try { if (rhs != null) rhs = new URLCodec().decode(rhs); } catch (DecoderException e) { } parameters.put(lhs, rhs); nonQueryParameters.add(lhs); } for (RequiredQueryParams p : requiredQueryParams) { if (!parameters.containsKey(p.toString())) { return false; } } httpRequest.getParameters().putAll(parameters); httpRequest.addNonQueryParameterKeys(nonQueryParameters); } else { for (RequiredQueryParams p : requiredQueryParams) { if (!httpRequest.getParameters().containsKey(p.toString())) { return false; } } } return true; } return false; }
@Override public boolean checkAccepts(final HttpRequest message) { if (message instanceof MappingHttpRequest) { final MappingHttpRequest httpRequest = (MappingHttpRequest) message; if (httpRequest.getMethod().equals(HttpMethod.POST)) { final Map<String, String> parameters = new HashMap<String, String>(httpRequest.getParameters()); final ChannelBuffer buffer = httpRequest.getContent(); buffer.markReaderIndex(); final byte[] read = new byte[buffer.readableBytes()]; buffer.readBytes(read); final String query = new String(read); buffer.resetReaderIndex(); for (final String p : query.split("&")) { final String[] splitParam = p.split("="); String lhs = splitParam[0]; String rhs = splitParam.length == 2 ? splitParam[1] : null; try { if (lhs != null) lhs = new URLCodec().decode(lhs); } catch (final DecoderException e) { } try { if (rhs != null) rhs = new URLCodec().decode(rhs); } catch (final DecoderException e) { } parameters.put(lhs, rhs); } for (final RequiredQueryParams p : RequiredQueryParams.values()) { if (!parameters.containsKey(p.toString())) { return false; } } httpRequest.getParameters().putAll(parameters); } else { for (final RequiredQueryParams p : RequiredQueryParams.values()) { if (!httpRequest.getParameters().containsKey(p.toString())) { return false; } } } return (message.getUri().startsWith(this.servicePath) || message.getUri().startsWith(this.internalServicePath)); } return false; }
private static boolean isRedirectLoop(final MappingHttpRequest request, final String uri) { final String requestHost = request.getHeader(HttpHeaders.Names.HOST); final String requestPath = request.getServicePath(); return requestHost != null && requestPath != null && uri.contains(requestHost + requestPath); }
@Override public Object bind(final MappingHttpRequest httpRequest) throws BindingException { final String operationName = this.extractOperationName(httpRequest); final String operationNameType = operationName + "Type"; for (final T op : this.possibleParams) httpRequest.getParameters().remove(op.name()); final Map<String, String> params = httpRequest.getParameters(); BaseMessage eucaMsg = null; Map<String, String> fieldMap = null; Class<?> targetType = null; Binding currentBinding = null; try { if (this.getBinding().hasElementClass(operationName)) { currentBinding = this.getBinding(); targetType = currentBinding.getElementClass(operationName); } else if (this.getBinding().hasElementClass(operationNameType)) { currentBinding = this.getBinding(); targetType = currentBinding.getElementClass(operationNameType); } else if (this.getDefaultBinding().hasElementClass(operationName)) { currentBinding = this.getDefaultBinding(); targetType = currentBinding.getElementClass(operationName); } else if (this.getDefaultBinding().hasElementClass(operationNameType)) { currentBinding = this.getDefaultBinding(); targetType = currentBinding.getElementClass(operationNameType); } else if (BindingManager.getDefaultBinding().hasElementClass(operationName)) { currentBinding = BindingManager.getDefaultBinding(); targetType = currentBinding.getElementClass(operationName); } else if (BindingManager.getDefaultBinding().hasElementClass(operationNameType)) { currentBinding = BindingManager.getDefaultBinding(); targetType = currentBinding.getElementClass(operationNameType); } else { // this will necessarily fault. try { targetType = this.getBinding().getElementClass(operationName); } catch (final BindingException ex) { LOG.error(ex, ex); throw ex; } } fieldMap = this.buildFieldMap(targetType); eucaMsg = (BaseMessage) targetType.newInstance(); } catch (final BindingException e) { LOG.debug("Failed to construct message of type: " + operationName, e); LOG.error(e, e); throw e; } catch (final Exception e) { throw new BindingException("Failed to construct message of type " + operationName, e); } final List<String> failedMappings = this.populateObject((GroovyObject) eucaMsg, fieldMap, params); if (!failedMappings.isEmpty() || !params.isEmpty()) { final StringBuilder errMsg = new StringBuilder("Failed to bind the following fields:\n"); for (final String f : failedMappings) errMsg.append(f).append('\n'); for (final Map.Entry<String, String> f : params.entrySet()) errMsg.append(f.getKey()).append(" = ").append(f.getValue()).append('\n'); throw new BindingException(errMsg.toString()); } try { currentBinding.toOM(eucaMsg, this.getNamespace()); } catch (final RuntimeException e) { LOG.error( "Falling back to default (unvalidated) binding for: " + operationName + " with params=" + params); LOG.error("Failed to build a valid message: " + e.getMessage(), e); try { BindingManager.getDefaultBinding().toOM(eucaMsg, BindingManager.defaultBindingNamespace()); } catch (final RuntimeException ex) { throw new BindingException( "Default binding failed to build a valid message: " + ex.getMessage(), ex); } } return eucaMsg; }