List of usage examples for io.netty.buffer Unpooled EMPTY_BUFFER
ByteBuf EMPTY_BUFFER
To view the source code for io.netty.buffer Unpooled EMPTY_BUFFER.
Click Source Link
From source file:com.linecorp.armeria.internal.Http1ObjectEncoder.java
License:Apache License
private HttpObject convertServerHeaders(int streamId, HttpHeaders headers, boolean endStream) throws Http2Exception { // Leading headers will always have :status, trailers will never have it. final HttpStatus status = headers.status(); if (status == null) { return convertTrailingHeaders(streamId, headers); }//from ww w . ja v a2s.c o m // Convert leading headers. final HttpResponse res; final boolean informational = status.codeClass() == HttpStatusClass.INFORMATIONAL; final HttpResponseStatus nettyStatus = HttpResponseStatus.valueOf(status.code()); if (endStream || informational) { res = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, nettyStatus, Unpooled.EMPTY_BUFFER, false); final io.netty.handler.codec.http.HttpHeaders outHeaders = res.headers(); convert(streamId, headers, outHeaders, false); if (informational) { // 1xx responses does not have the 'content-length' header. outHeaders.remove(HttpHeaderNames.CONTENT_LENGTH); } else if (!headers.contains(HttpHeaderNames.CONTENT_LENGTH)) { // NB: Set the 'content-length' only when not set rather than always setting to 0. // It's because a response to a HEAD request can have empty content while having // non-zero 'content-length' header. // However, this also opens the possibility of sending a non-zero 'content-length' // header even when it really has to be zero. e.g. a response to a non-HEAD request outHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0); } } else { res = new DefaultHttpResponse(HttpVersion.HTTP_1_1, nettyStatus, false); // Perform conversion. convert(streamId, headers, res.headers(), false); setTransferEncoding(res); } return res; }
From source file:com.linecorp.armeria.internal.Http1ObjectEncoder.java
License:Apache License
@Override protected ChannelFuture doWriteReset(ChannelHandlerContext ctx, int id, int streamId, Http2Error error) { // NB: this.minClosedId can be overwritten more than once when 3+ pipelined requests are received // and they are handled by different threads simultaneously. // e.g. when the 3rd request triggers a reset and then the 2nd one triggers another. minClosedId = Math.min(minClosedId, id); for (int i = minClosedId; i <= maxIdWithPendingWrites; i++) { final PendingWrites pendingWrites = pendingWritesMap.remove(i); for (;;) { final Entry<HttpObject, ChannelPromise> e = pendingWrites.poll(); if (e == null) { break; }//from w ww. j a v a 2 s. c o m e.getValue().tryFailure(ClosedSessionException.get()); } } final ChannelFuture f = ctx.write(Unpooled.EMPTY_BUFFER); if (currentId >= minClosedId) { f.addListener(ChannelFutureListener.CLOSE); } return f; }
From source file:com.linecorp.armeria.server.http.file.HttpFileServiceInvocationHandler.java
License:Apache License
@Override public void invoke(ServiceInvocationContext ctx, Executor blockingTaskExecutor, Promise<Object> promise) throws Exception { final HttpRequest req = ctx.originalRequest(); if (req.method() != HttpMethod.GET) { respond(ctx, promise, HttpResponseStatus.METHOD_NOT_ALLOWED, 0, ERROR_MIME_TYPE, Unpooled.wrappedBuffer(CONTENT_METHOD_NOT_ALLOWED)); return;/*from ww w .jav a2s.c o m*/ } final String path = normalizePath(ctx.mappedPath()); if (path == null) { respond(ctx, promise, HttpResponseStatus.NOT_FOUND, 0, ERROR_MIME_TYPE, Unpooled.wrappedBuffer(CONTENT_NOT_FOUND)); return; } Entry entry = getEntry(path); long lastModifiedMillis; if ((lastModifiedMillis = entry.lastModifiedMillis()) == 0) { boolean found = false; if (path.charAt(path.length() - 1) == '/') { // Try index.html if it was a directory access. entry = getEntry(path + "index.html"); if ((lastModifiedMillis = entry.lastModifiedMillis()) != 0) { found = true; } } if (!found) { respond(ctx, promise, HttpResponseStatus.NOT_FOUND, 0, ERROR_MIME_TYPE, Unpooled.wrappedBuffer(CONTENT_NOT_FOUND)); return; } } long ifModifiedSinceMillis = Long.MIN_VALUE; try { ifModifiedSinceMillis = req.headers().getTimeMillis(HttpHeaderNames.IF_MODIFIED_SINCE, Long.MIN_VALUE); } catch (Exception e) { // Ignore the ParseException, which is raised on malformed date. //noinspection ConstantConditions if (!(e instanceof ParseException)) { throw e; } } // HTTP-date does not have subsecond-precision; add 999ms to it. if (ifModifiedSinceMillis > Long.MAX_VALUE - 999) { ifModifiedSinceMillis = Long.MAX_VALUE; } else { ifModifiedSinceMillis += 999; } if (lastModifiedMillis < ifModifiedSinceMillis) { respond(ctx, promise, HttpResponseStatus.NOT_MODIFIED, lastModifiedMillis, entry.mimeType(), Unpooled.EMPTY_BUFFER); return; } respond(ctx, promise, HttpResponseStatus.OK, lastModifiedMillis, entry.mimeType(), entry.readContent(ctx.alloc())); }
From source file:com.linecorp.armeria.server.http.Http1RequestDecoder.java
License:Apache License
private void fail(ChannelHandlerContext ctx, HttpResponseStatus status) { discarding = true;/*w ww . j a va 2 s .co m*/ req = null; final ChannelFuture future; if (receivedRequests <= sentResponses) { // Just close the connection if sending an error response will make the number of the sent // responses exceed the number of the received requests, which doesn't make sense. future = ctx.writeAndFlush(Unpooled.EMPTY_BUFFER); } else { final ByteBuf content = Unpooled.copiedBuffer(status.toString(), StandardCharsets.UTF_8); final FullHttpResponse res = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, content); final HttpHeaders headers = res.headers(); headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE); headers.set(HttpHeaderNames.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8); headers.setInt(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); future = ctx.writeAndFlush(res); } future.addListener(ChannelFutureListener.CLOSE); }
From source file:com.linecorp.armeria.server.http.HttpServerHandler.java
License:Apache License
private void handleRequest(ChannelHandlerContext ctx, DecodedHttpRequest req) throws Exception { // Ignore the request received after the last request, // because we are going to close the connection after sending the last response. if (handledLastRequest) { return;//from w w w.j a v a 2 s .co m } // If we received the message with keep-alive disabled, // we should not accept a request anymore. if (!req.isKeepAlive()) { handledLastRequest = true; } final HttpHeaders headers = req.headers(); if (!ALLOWED_METHODS.contains(headers.method())) { respond(ctx, req, HttpStatus.METHOD_NOT_ALLOWED); return; } // Handle 'OPTIONS * HTTP/1.1'. final String originalPath = headers.path(); if (originalPath.isEmpty() || originalPath.charAt(0) != '/') { if (headers.method() == HttpMethod.OPTIONS && "*".equals(originalPath)) { handleOptions(ctx, req); } else { respond(ctx, req, HttpStatus.BAD_REQUEST); } return; } // Validate and split path and query. final String path = validatePathAndStripQuery(originalPath); if (path == null) { // Reject requests without a valid path. respond(ctx, req, HttpStatus.NOT_FOUND); return; } if (headers.authority() == null) { // HTTP/1.1 requests require a host header. respond(ctx, req, HttpStatus.BAD_REQUEST); return; } final String hostname = hostname(headers); final VirtualHost host = config.findVirtualHost(hostname); // Find the service that matches the path. final PathMapped<ServiceConfig> mapped = host.findServiceConfig(path); if (!mapped.isPresent()) { // No services matched the path. handleNonExistentMapping(ctx, req, host, path); return; } // Decode the request and create a new invocation context from it to perform an invocation. final String mappedPath = mapped.mappedPath(); final ServiceConfig serviceCfg = mapped.value(); final Service<Request, HttpResponse> service = serviceCfg.service(); final Channel channel = ctx.channel(); final ServiceRequestContext reqCtx = new DefaultServiceRequestContext(serviceCfg, channel, protocol, req.method().name(), path, mappedPath, LoggerFactory.getLogger(serviceCfg.loggerName()), req); final RequestLogBuilder reqLogBuilder = reqCtx.requestLogBuilder(); final HttpResponse res; try (PushHandle ignored = RequestContext.push(reqCtx)) { req.init(reqCtx); res = service.serve(reqCtx, req); } catch (Throwable cause) { reqLogBuilder.end(cause); if (cause instanceof ResourceNotFoundException) { respond(ctx, req, HttpStatus.NOT_FOUND); } else if (cause instanceof ServiceUnavailableException) { respond(ctx, req, HttpStatus.SERVICE_UNAVAILABLE); } else { logger.warn("{} Unexpected exception: {}, {}", reqCtx, service, req, cause); respond(ctx, req, HttpStatus.INTERNAL_SERVER_ERROR); } return; } final EventLoop eventLoop = channel.eventLoop(); // Keep track of the number of unfinished requests and // clean up the request stream when response stream ends. unfinishedRequests++; res.closeFuture().handle(voidFunction((ret, cause) -> { req.abort(); if (cause == null) { reqLogBuilder.end(); } else { reqLogBuilder.end(cause); } eventLoop.execute(() -> { if (--unfinishedRequests == 0 && handledLastRequest) { ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(CLOSE); } }); })).exceptionally(CompletionActions::log); res.subscribe(new HttpResponseSubscriber(ctx, responseEncoder, reqCtx, req), eventLoop); }
From source file:com.linecorp.armeria.server.http.ServiceCodecPromiseTest.java
License:Apache License
protected static void setupServer(ServerBuilder sb, GenericFutureListener<? extends Future<? super Object>> listener, ServiceInvocationHandler handler) { Service service = Service.of(new DecoratingServiceCodec(new HttpServiceCodec()) { @Override//w w w .j av a 2 s. c o m public DecodeResult decodeRequest(ServiceConfig cfg, Channel ch, SessionProtocol sessionProtocol, String hostname, String path, String mappedPath, ByteBuf in, Object originalRequest, Promise<Object> promise) throws Exception { promise.addListener(listener); return delegate().decodeRequest(cfg, ch, sessionProtocol, hostname, path, mappedPath, in, originalRequest, promise); } @Override public ByteBuf encodeResponse(ServiceInvocationContext ctx, Object response) throws Exception { return Unpooled.EMPTY_BUFFER; } }, handler); sb.serviceAt("/", service); }
From source file:com.linecorp.armeria.server.HttpServerHandler.java
License:Apache License
private void handleRequest(ChannelHandlerContext ctx, DecodedHttpRequest req) throws Exception { // Ignore the request received after the last request, // because we are going to close the connection after sending the last response. if (handledLastRequest) { return;/* w w w. j a v a 2s .c o m*/ } // If we received the message with keep-alive disabled, // we should not accept a request anymore. if (!req.isKeepAlive()) { handledLastRequest = true; } final HttpHeaders headers = req.headers(); if (!ALLOWED_METHODS.contains(headers.method())) { respond(ctx, req, HttpStatus.METHOD_NOT_ALLOWED, new IllegalArgumentException("Request method is not allowed: " + headers.method().name())); return; } // Handle 'OPTIONS * HTTP/1.1'. final String originalPath = headers.path(); if (originalPath == null) { respond(ctx, req, HttpStatus.BAD_REQUEST, new IllegalArgumentException("Request path is missing.")); return; } if (originalPath.isEmpty() || originalPath.charAt(0) != '/') { if (headers.method() == HttpMethod.OPTIONS && "*".equals(originalPath)) { handleOptions(ctx, req); } else { respond(ctx, req, HttpStatus.BAD_REQUEST, new IllegalArgumentException("Request path is invalid: " + originalPath)); } return; } // Validate and split path and query. final PathAndQuery pathAndQuery = PathAndQuery.parse(originalPath); if (pathAndQuery == null) { // Reject requests without a valid path. respond(ctx, req, HttpStatus.NOT_FOUND, new IllegalArgumentException("Request path is invalid: " + originalPath)); return; } final String hostname = hostname(ctx, headers); final VirtualHost host = config.findVirtualHost(hostname); final PathMappingContext mappingCtx = DefaultPathMappingContext.of(host, hostname, pathAndQuery.path(), pathAndQuery.query(), headers, host.producibleMediaTypes()); // Find the service that matches the path. final PathMapped<ServiceConfig> mapped; try { mapped = host.findServiceConfig(mappingCtx); } catch (HttpStatusException cause) { // We do not need to handle HttpResponseException here because we do not use it internally. respond(ctx, req, pathAndQuery, cause.httpStatus(), cause); return; } catch (Throwable cause) { logger.warn("{} Unexpected exception: {}", ctx.channel(), req, cause); respond(ctx, req, pathAndQuery, HttpStatus.INTERNAL_SERVER_ERROR, cause); return; } if (!mapped.isPresent()) { // No services matched the path. handleNonExistentMapping(ctx, req, host, pathAndQuery, mappingCtx); return; } // Decode the request and create a new invocation context from it to perform an invocation. final PathMappingResult mappingResult = mapped.mappingResult(); final ServiceConfig serviceCfg = mapped.value(); final Service<HttpRequest, HttpResponse> service = serviceCfg.service(); final Channel channel = ctx.channel(); final DefaultServiceRequestContext reqCtx = new DefaultServiceRequestContext(serviceCfg, channel, serviceCfg.server().meterRegistry(), protocol, mappingCtx, mappingResult, req, getSSLSession(channel), proxiedAddresses); try (SafeCloseable ignored = RequestContext.push(reqCtx)) { final RequestLogBuilder logBuilder = reqCtx.logBuilder(); HttpResponse serviceResponse; try { req.init(reqCtx); serviceResponse = service.serve(reqCtx, req); } catch (HttpResponseException cause) { serviceResponse = cause.httpResponse(); } catch (Throwable cause) { try { if (cause instanceof HttpStatusException) { respond(ctx, req, ((HttpStatusException) cause).httpStatus(), reqCtx, cause); } else { logger.warn("{} Unexpected exception: {}, {}", reqCtx, service, req, cause); respond(ctx, req, HttpStatus.INTERNAL_SERVER_ERROR, reqCtx, cause); } } finally { logBuilder.endRequest(cause); logBuilder.endResponse(cause); } return; } final HttpResponse res = serviceResponse; final EventLoop eventLoop = channel.eventLoop(); // Keep track of the number of unfinished requests and // clean up the request stream when response stream ends. gracefulShutdownSupport.inc(); unfinishedRequests++; unfinishedResponses.put(res, true); if (service.shouldCachePath(pathAndQuery.path(), pathAndQuery.query(), mapped.mapping())) { reqCtx.log().addListener(log -> { final HttpStatus status = log.responseHeaders().status(); if (status != null && status.code() >= 200 && status.code() < 400) { pathAndQuery.storeInCache(originalPath); } }, RequestLogAvailability.COMPLETE); } req.completionFuture().handle(voidFunction((ret, cause) -> { if (cause == null) { logBuilder.endRequest(); } else { logBuilder.endRequest(cause); // NB: logBuilder.endResponse(cause) will be called by HttpResponseSubscriber below } })).exceptionally(CompletionActions::log); res.completionFuture().handleAsync(voidFunction((ret, cause) -> { req.abort(); // NB: logBuilder.endResponse() is called by HttpResponseSubscriber below. gracefulShutdownSupport.dec(); unfinishedResponses.remove(res); if (--unfinishedRequests == 0 && handledLastRequest) { ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(CLOSE); } }), eventLoop).exceptionally(CompletionActions::log); assert responseEncoder != null; final HttpResponseSubscriber resSubscriber = new HttpResponseSubscriber(ctx, responseEncoder, reqCtx, req, accessLogWriter); reqCtx.setRequestTimeoutChangeListener(resSubscriber); res.subscribe(resSubscriber, eventLoop, true); } }
From source file:com.linecorp.armeria.server.metrics.MetricCollectingServiceCodecTest.java
License:Apache License
@SuppressWarnings("unchecked") protected static void setupServer(ServerBuilder sb, ServiceInvocationHandler handler, final MetricConsumer consumer) throws Exception { ServiceCodec codec = Mockito.mock(ServiceCodec.class); DecodeResult decodeResult = Mockito.mock(DecodeResult.class); DefaultAttributeMap defaultAttributeMap = new DefaultAttributeMap(); ServiceInvocationContext invocationContext = Mockito.mock(ServiceInvocationContext.class); when(decodeResult.type()).thenReturn(DecodeResultType.SUCCESS); when(decodeResult.invocationContext()).thenReturn(invocationContext); when(invocationContext.attr(any())).then(x -> defaultAttributeMap.attr(AttributeKey.valueOf("TEST"))); when(invocationContext.method()).thenReturn("someMethod"); when(codec.decodeRequest(any(), any(), any(), any(), any(), any(), any(), any(), any())) .thenReturn(decodeResult);/* w w w . j a va 2 s. c o m*/ when(codec.encodeResponse(any(), any())).thenReturn(Unpooled.EMPTY_BUFFER); when(codec.encodeFailureResponse(any(), any())).thenReturn(Unpooled.EMPTY_BUFFER); sb.serviceAt("/", Service.of(new MetricCollectingServiceCodec(codec, consumer), handler)); }
From source file:com.linecorp.armeria.unsafe.ByteBufHttpData.java
License:Apache License
/** * Constructs a new {@link ByteBufHttpData}. Ownership of {@code buf} is taken by this * {@link ByteBufHttpData}, which must not be mutated anymore. *//*from www. j av a2 s. c o m*/ public ByteBufHttpData(ByteBuf buf, boolean endOfStream) { length = requireNonNull(buf, "buf").readableBytes(); if (length != 0) { this.buf = buf; } else { buf.release(); this.buf = Unpooled.EMPTY_BUFFER; } this.endOfStream = endOfStream; }
From source file:com.linkedin.mitm.proxy.channel.ChannelMediator.java
License:Open Source License
private Future<Void> disconnect(final Channel channel) { if (channel == null) { return null; }//from w w w . ja va 2 s .com final Promise<Void> promise = channel.newPromise(); writeToChannel(channel, Unpooled.EMPTY_BUFFER).addListener(future -> closeChannel(promise, channel)); return promise; }