private static Http2Headers http1HeadersToHttp2Headers(FullHttpRequest request) { CharSequence host = request.headers().get(HttpHeaderNames.HOST); Http2Headers http2Headers = new DefaultHttp2Headers() .method(HttpMethod.GET.asciiName()) .path(request.uri()) .scheme(HttpScheme.HTTP.name()); if (host != null) { http2Headers.authority(host); } return http2Headers; }
@Override public void writeHead(HttpMethod method, String rawMethod, String uri, MultiMap headers, String hostHeader, boolean chunked, ByteBuf content, boolean end, StreamPriority priority) { Http2Headers h = new DefaultHttp2Headers(); h.method(method != HttpMethod.OTHER ? method.name() : rawMethod); if (method == HttpMethod.CONNECT) { if (hostHeader == null) { throw new IllegalArgumentException("Missing :authority / host header"); h.authority(hostHeader); } else { h.path(uri); h.scheme(conn.isSSL() ? "https" : "http"); if (hostHeader != null) { h.authority(hostHeader); h.add(Http2HeadersAdaptor.toLowerCase(header.getKey()), header.getValue()); if (conn.client.getOptions().isTryUseCompression() && h.get(HttpHeaderNames.ACCEPT_ENCODING) == null) { h.set(HttpHeaderNames.ACCEPT_ENCODING, DEFLATE_GZIP); writeBuffer(content, end); } else { handlerContext.flush();
private boolean checkSendHeaders(boolean end) { if (!headWritten) { if (headersEndHandler != null) { headersEndHandler.handle(null); } sanitizeHeaders(); if (Metrics.METRICS_ENABLED && metric != null) { conn.metrics().responseBegin(metric, this); } headWritten = true; headers.status(Integer.toString(status.code())); // Could be optimized for usual case ? stream.writeHeaders(headers, end); if (end) { ctx.flush(); } return true; } else { return false; } }
private void sanitizeHeaders() { if (head || status == HttpResponseStatus.NOT_MODIFIED) { headers.remove(HttpHeaders.TRANSFER_ENCODING); } else if (status == HttpResponseStatus.RESET_CONTENT) { headers.remove(HttpHeaders.TRANSFER_ENCODING); headers.set(HttpHeaders.CONTENT_LENGTH, "0"); } else if (status.codeClass() == HttpStatusClass.INFORMATIONAL || status == HttpResponseStatus.NO_CONTENT) { headers.remove(HttpHeaders.TRANSFER_ENCODING); headers.remove(HttpHeaders.CONTENT_LENGTH); } }
public Http2HeadersAdaptor(Http2Headers headers) { List<CharSequence> cookies = headers.getAll(HttpHeaderNames.COOKIE); if (cookies != null && cookies.size() > 1) { // combine the cookie values into 1 header entry. // https://tools.ietf.org/html/rfc7540#section-8.1.2.5 String value = cookies.stream().collect(Collectors.joining("; ")); headers.set(HttpHeaderNames.COOKIE, value); } this.headers = headers; }
ctx.write(msg, promise); return; streamRequest.getEntityStream().setReader(reader); LOG.debug("Sent HTTP/2 HEADERS frame, stream={}, end={}, headers={}, padding={}bytes", new Object[] { streamId, NOT_END_STREAM, http2Headers.size(), NO_PADDING}); headersFuture = encoder.writeHeaders(ctx, streamId, http2Headers, NO_PADDING, NOT_END_STREAM, promise); headersFuture.addListener(future -> { if (future.isSuccess()) final Http2Headers headers = NettyRequestAdapter.toHttp2Headers(restRequest); LOG.debug("Sent HTTP/2 HEADERS frame, stream={}, end={}, headers={}, padding={}bytes", new Object[] { streamId, NOT_END_STREAM, headers.size(), NO_PADDING}); headersFuture = encoder.writeHeaders(ctx, streamId, headers, NO_PADDING, NOT_END_STREAM, promise); headersFuture.addListener(future -> { if (future.isSuccess()) LOG.debug("Sent HTTP/2 DATA frame, stream={}, end={}, data={}bytes, padding={}bytes", new Object[]{streamId, END_STREAM, data.readableBytes(), NO_PADDING}); encoder.writeData(ctx, streamId, data, NO_PADDING, END_STREAM, ctx.newPromise()); ctx.channel().flush();
@Override public void push(final String method, final String path, final Map<String, Object> headers) { ctx.channel().eventLoop().execute(() -> { AsciiString streamIdHeader = HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(); Http2Connection connection = encoder.connection(); int nextStreamId = connection.local().incrementAndGetNextStreamId(); Http2Headers h2headers = new DefaultHttp2Headers() .path(path) .method(method) .authority(authority) .scheme(scheme); headers.forEach((n, v) -> h2headers.add(n, v.toString())); encoder.writePushPromise(ctx, streamId, nextStreamId, h2headers, 0, ctx.newPromise()); // TODO: Is there another way of handling a push promise? DefaultFullHttpRequest pushRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(method.toUpperCase()), path, Unpooled.EMPTY_BUFFER, new DefaultHttpHeaders(false).set(streamIdHeader, nextStreamId), EmptyHttpHeaders.INSTANCE); ctx.pipeline().fireChannelRead(pushRequest); ctx.pipeline().fireChannelReadComplete(); }); }
String path = http2Headers.headers().path().toString(); baseUri, requestUri, http2Headers.headers().method().toString(), getSecurityContext(), new PropertiesDelegate() { ctx.channel().closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() { @Override public void operationComplete(Future<? super Void> future) throws Exception { for (CharSequence name : http2Headers.headers().names()) { requestContext.headers(name.toString(), mapToString(http2Headers.headers().getAll(name)));
protected void sendHttp2Response(ChannelHandlerContext ctx, int streamId, HttpResponseStatus status, String result) { // Send a frame for the response status Http2Headers headers = new DefaultHttp2Headers().status(status.codeAsText()); if (!HttpResponseStatus.OK.equals(status)) { headers.set(RemotingConstants.HEAD_RESPONSE_ERROR, "true"); } if (StringUtils.isNotBlank(result)) { ByteBuf data = ctx.alloc().buffer(); data.writeBytes(result.getBytes(RpcConstants.DEFAULT_CHARSET)); encoder().writeHeaders(ctx, streamId, headers, 0, false, ctx.newPromise()); encoder().writeData(ctx, streamId, data, 0, true, ctx.newPromise()); } else { encoder().writeHeaders(ctx, streamId, headers, 0, true, ctx.newPromise()); } }
if (headers.get(HttpHeaderNames.CONTENT_LENGTH) == null) { putHeader(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(contentLength)); if (headers.get(HttpHeaderNames.CONTENT_TYPE) == null) { String contentType = MimeMapping.getMimeTypeForFilename(filename); if (contentType != null) { ctx.channel() .eventLoop() .register(fileChannel)
? HttpResponseStatus.valueOf(statusCode) : new HttpResponseStatus(statusCode, reasonPhrase); DefaultHttp2Headers response = new DefaultHttp2Headers(); response.status(Integer.toString(responseContext.getStatus())); response.add(e.getKey().toLowerCase(), e.getValue()); response.set(HttpHeaderNames.CONTENT_LENGTH, Long.toString(contentLength)); ctx.writeAndFlush(new DefaultHttp2HeadersFrame(response)); if (!headersFrame.headers().method().equals(HttpMethod.HEAD.asciiName()) && (contentLength > 0 || contentLength == -1)) { ctx.writeAndFlush(new DefaultHttp2DataFrame(true)); return null;
private static void setHttp2Scheme(HttpHeaders in, URI uri, Http2Headers out) { String value = uri.getScheme(); if (value != null) { out.scheme(new AsciiString(value)); return; } // Consume the Scheme extension header if present CharSequence cValue = in.get(ExtensionHeaderNames.SCHEME.text()); if (cValue != null) { out.scheme(AsciiString.of(cValue)); return; } if (uri.getPort() == HTTPS.port()) { out.scheme(HTTPS.name()); } else if (uri.getPort() == HTTP.port()) { out.scheme(HTTP.name()); } else { throw new IllegalArgumentException(":scheme must be specified. " + "see https://tools.ietf.org/html/rfc7540#section-8.1.2.3"); } }
int id = stream == null ? 0 : stream.id(); final CharSequence status = headers.status(); if (null != status && HttpResponseStatus.CONTINUE.codeAsText().contentEquals(status)) { final FullHttpMessage fullMsg = newFullMessage(id, headers, ctx.alloc()); out.add(fullMsg); return; if (headers.method() == null && status == null) { LastHttpContent last = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER, validateHeaders); HttpConversionUtil.addHttp2ToHttpHeaders(id, headers, last.trailingHeaders(), out.add(last); } else { FullHttpMessage full = newFullMessage(id, headers, ctx.alloc()); out.add(full); HttpMessage req = newMessage(id, headers); if (!HttpUtil.isContentLengthSet(req)) { req.headers().add(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
final AcceptNotificationResponse acceptNotificationResponse = (AcceptNotificationResponse) message; final Http2Headers headers = new DefaultHttp2Headers() .status(HttpResponseStatus.OK.codeAsText()) .add(APNS_ID_HEADER, FastUUID.toString(acceptNotificationResponse.getApnsId())); this.encoder().writeHeaders(context, acceptNotificationResponse.getStreamId(), headers, 0, true, writePromise); final RejectNotificationResponse rejectNotificationResponse = (RejectNotificationResponse) message; final Http2Headers headers = new DefaultHttp2Headers() .status(rejectNotificationResponse.getErrorReason().getHttpResponseStatus().codeAsText()) .add(HttpHeaderNames.CONTENT_TYPE, "application/json") .add(APNS_ID_HEADER, FastUUID.toString(rejectNotificationResponse.getApnsId())); final ChannelPromise headersPromise = context.newPromise(); this.encoder().writeHeaders(context, rejectNotificationResponse.getStreamId(), headers, 0, false, headersPromise); final ChannelPromise dataPromise = context.newPromise(); this.encoder().writeData(context, rejectNotificationResponse.getStreamId(), Unpooled.wrappedBuffer(payloadBytes), 0, true, dataPromise); context.write(message, writePromise);
if (expect) { if (postRequestDecoder == null) { CharSequence contentType = headers.get(HttpHeaderNames.CONTENT_TYPE); if (contentType != null) { io.netty.handler.codec.http.HttpMethod method = io.netty.handler.codec.http.HttpMethod.valueOf(headers.method().toString()); String lowerCaseContentType = contentType.toString().toLowerCase(); boolean isURLEncoded = lowerCaseContentType.startsWith(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED.toString()); if ((lowerCaseContentType.startsWith(HttpHeaderValues.MULTIPART_FORM_DATA.toString()) || isURLEncoded) && (method == io.netty.handler.codec.http.HttpMethod.POST || method == io.netty.handler.codec.http.HttpMethod.PUT || io.netty.handler.codec.http.HttpVersion.HTTP_1_1, method, headers.path().toString()); req.headers().add(HttpHeaderNames.CONTENT_TYPE, contentType); postRequestDecoder = new HttpPostRequestDecoder(new NettyFileUploadDataFactory(context, this, () -> uploadHandler), req);
private void writeErrorResponse(ChannelHandlerContext ctx, int streamId, HttpResponseStatus status) throws Http2Exception { final byte[] content = status.toString().getBytes(StandardCharsets.UTF_8); writer.writeHeaders( ctx, streamId, new DefaultHttp2Headers(false) .status(status.codeAsText()) .set(HttpHeaderNames.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8.toString()) .setInt(HttpHeaderNames.CONTENT_LENGTH, content.length), 0, false, ctx.voidPromise()); writer.writeData(ctx, streamId, Unpooled.wrappedBuffer(content), 0, true, ctx.voidPromise()); final Http2Stream stream = writer.connection().stream(streamId); if (stream != null && writer.flowController().hasFlowControlled(stream)) { // Ensure to flush the error response if it's flow-controlled so that it is sent // before an RST_STREAM frame. writer.flowController().writePendingBytes(); } }
new Object[]{streamId, endOfStream, headers.size(), padding}); if (headers.status() != null) builder.setStatus(Integer.parseInt(headers.status().toString())); if (headers.authority() != null) builder.addHeaderValue(HttpHeaderNames.HOST.toString(), headers.authority().toString()); if (callback != null) ctx.fireChannelRead(new ResponseWithCallback<Response, TransportCallback<?>>(response, callback));
private void sendHttp2Response0(HttpResponseStatus status, boolean error, ByteBuf data) { Http2Headers headers = new DefaultHttp2Headers().status(status.codeAsText()); if (request.getSerializeType() > 0) { String serialization = SerializerFactory.getAliasByCode(request.getSerializeType()); headers.set(RemotingConstants.HEAD_SERIALIZE_TYPE, serialization); } else { headers.set(CONTENT_TYPE, "text/plain; charset=" + RpcConstants.DEFAULT_CHARSET.displayName()); } if (error) { headers.set(RemotingConstants.HEAD_RESPONSE_ERROR, "true"); } if (data != null) { encoder.writeHeaders(ctx, streamId, headers, 0, false, ctx.newPromise()); encoder.writeData(ctx, streamId, data, 0, true, ctx.newPromise()); } else { encoder.writeHeaders(ctx, streamId, headers, 0, true, ctx.newPromise()); } } }
String statusMessage; try { status = Integer.parseInt(headers.status().toString()); statusMessage = HttpResponseStatus.valueOf(status).reasonPhrase(); } catch (Exception e) { handleException(e);