/** * Parses the specified HTTP status line into a {@link HttpResponseStatus}. The expected formats of the line are: * <ul> * <li>{@code statusCode} (e.g. 200)</li> * <li>{@code statusCode} {@code reasonPhrase} (e.g. 404 Not Found)</li> * </ul> * * @throws IllegalArgumentException if the specified status line is malformed */ public static HttpResponseStatus parseLine(AsciiString line) { try { int space = line.forEachByte(FIND_ASCII_SPACE); return space == -1 ? valueOf(line.parseInt()) : valueOf(line.parseInt(0, space), line.toString(space + 1)); } catch (Exception e) { throw new IllegalArgumentException("malformed status line: " + line, e); } }
/** * Returns an {@link AsciiString} containing the given string and retains/caches the input * string for later use in {@link #toString()}. * Used for the constants (which already stored in the JVM's string table) and in cases * where the guaranteed use of the {@link #toString()} method. */ public static AsciiString cached(String string) { AsciiString asciiString = new AsciiString(string); asciiString.string = string; return asciiString; }
@Override public boolean equals(CharSequence a, CharSequence b) { return AsciiString.contentEqualsIgnoreCase(a, b); } };
/** * Copies a range of characters into a new string. * @param start the offset of the first character (inclusive). * @return a new string containing the characters from start to the end of the string. * @throws IndexOutOfBoundsException if {@code start < 0} or {@code start > length()}. */ public AsciiString subSequence(int start) { return subSequence(start, length()); }
/** * Iterates over the readable bytes of this buffer with the specified {@code processor} in ascending order. * * @return {@code -1} if the processor iterated to or beyond the end of the readable bytes. * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}. */ public int forEachByte(ByteProcessor visitor) throws Exception { return forEachByte0(0, length(), visitor); }
/** * Converts this string to a byte array. */ public byte[] toByteArray() { return toByteArray(0, length()); }
@Override public void onResponse(HttpResponse httpResponse) { HttpResponseMessage response = HttpResponseMessage .from(request) .setStatusCode(httpResponse.status().code()) .setReasonPhrase(httpResponse.status().reasonPhrase()); for (Map.Entry<String, String> entry : httpResponse.headers()) { response.addHeader(entry.getKey(), entry.getValue()); } if (httpResponse instanceof FullHttpResponse) { ByteBuf content = ((FullHttpResponse) httpResponse).content(); if (content != null && content.readableBytes() > 0) { byte[] body = new byte[content.readableBytes()]; content.readBytes(body); response.body = body; response.addHeader(CONTENT_LENGTH.toString(), Integer.toString(response.body.length)); } } response.send(); Logs.HTTP.info("send proxy request success end request={}, response={}", request, response); }
if (!req.headers().containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE, true) || !HttpHeaderValues.WEBSOCKET.contentEqualsIgnoreCase(req.headers().get(HttpHeaderNames.UPGRADE))) { throw new WebSocketHandshakeException("not a WebSocket handshake request: missing upgrade"); boolean isHixie76 = req.headers().contains(HttpHeaderNames.SEC_WEBSOCKET_KEY1) && req.headers().contains(HttpHeaderNames.SEC_WEBSOCKET_KEY2); FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, new HttpResponseStatus(101, isHixie76 ? "WebSocket Protocol Handshake" : "Web Socket Protocol Handshake")); if (headers != null) { res.headers().add(headers); res.headers().add(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET); res.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE); int b = (int) (Long.parseLong(BEGINNING_DIGIT.matcher(key2).replaceAll("")) / BEGINNING_SPACE.matcher(key2).replaceAll("").length()); long c = req.content().readLong(); ByteBuf input = Unpooled.buffer(16); input.writeInt(a); input.writeInt(b); input.writeLong(c); res.content().writeBytes(WebSocketUtil.md5(input.array()));
List<String> contentTypes = headers.getAll(HttpHeaderNames.CONTENT_TYPE); List<String> transferEncoding = headers.getAll(HttpHeaderNames.TRANSFER_ENCODING); if (contentTypes != null) { headers.remove(HttpHeaderNames.CONTENT_TYPE); for (String contentType : contentTypes) { if (lowercased.startsWith(HttpHeaderValues.MULTIPART_FORM_DATA.toString()) || lowercased.startsWith(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED.toString())) { headers.remove(HttpHeaderNames.TRANSFER_ENCODING); for (CharSequence v : transferEncoding) { if (HttpHeaderValues.CHUNKED.contentEqualsIgnoreCase(v)) { ByteBuf chunkContent = chunk.content(); if (fullRequest.content() != chunkContent) { fullRequest.content().clear().writeBytes(chunkContent); chunkContent.release();
if (!response.status().equals(HttpResponseStatus.SWITCHING_PROTOCOLS)) { throw new WebSocketHandshakeException("Invalid handshake response getStatus: " + response.status()); HttpHeaders headers = response.headers(); CharSequence upgrade = headers.get(HttpHeaderNames.UPGRADE); if (!WEBSOCKET.contentEqualsIgnoreCase(upgrade)) { throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade); if (!headers.containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE, true)) { throw new WebSocketHandshakeException("Invalid handshake response connection: " + headers.get(HttpHeaderNames.CONNECTION)); ByteBuf challenge = response.content(); if (!challenge.equals(expectedChallengeResponseBytes)) { throw new WebSocketHandshakeException("Invalid challenge");
String headerName = header.getName().getValue(); if (!headerName.equalsIgnoreCase(CONTENT_LENGTH.toString()) && !headerName.equalsIgnoreCase(TRANSFER_ENCODING.toString()) && !headerName.equalsIgnoreCase(HOST.toString()) && !headerName.equalsIgnoreCase(ACCEPT_ENCODING.toString())) { if (!header.getValues().isEmpty()) { for (NottableString headerValue : header.getValues()) { request.headers().add(headerName, headerValue.getValue()); request.headers().add(headerName, ""); if (!Strings.isNullOrEmpty(httpRequest.getFirstHeader(HOST.toString()))) { request.headers().add(HOST, httpRequest.getFirstHeader(HOST.toString())); request.headers().set(ACCEPT_ENCODING, GZIP + "," + DEFLATE); request.headers().set(CONTENT_LENGTH, request.content().readableBytes()); if (isKeepAlive(request)) { request.headers().set(CONNECTION, KEEP_ALIVE);
/** * 转换为Netty所用Response<br> * 用于返回一般类型响应(文本) * * @return FullHttpResponse */ private FullHttpResponse toFullHttpResponse() { final ByteBuf byteBuf = (ByteBuf)content; final FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(httpVersion, status, byteBuf); // headers final HttpHeaders httpHeaders = fullHttpResponse.headers().add(headers); httpHeaders.set(HttpHeaderNames.CONTENT_TYPE.toString(), StrUtil.format("{};charset={}", contentType, charset)); httpHeaders.set(HttpHeaderNames.CONTENT_ENCODING.toString(), charset); httpHeaders.set(HttpHeaderNames.CONTENT_LENGTH.toString(), byteBuf.readableBytes()); // Cookies for (Cookie cookie : cookies) { httpHeaders.add(HttpHeaderNames.SET_COOKIE.toString(), ServerCookieEncoder.LAX.encode(cookie)); } return fullHttpResponse; } // -------------------------------------------------------------------------------------- build HttpResponse end
protected void verify(FullHttpResponse response) { final HttpResponseStatus status = HttpResponseStatus.SWITCHING_PROTOCOLS; final HttpHeaders headers = response.headers(); if (!response.status().equals(status)) { throw new WebSocketHandshakeException("Invalid handshake response getStatus: " + response.status()); CharSequence upgrade = headers.get(HttpHeaderNames.UPGRADE); if (!HttpHeaderValues.WEBSOCKET.contentEqualsIgnoreCase(upgrade)) { throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade); if (!headers.containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE, true)) { throw new WebSocketHandshakeException("Invalid handshake response connection: " + headers.get(HttpHeaderNames.CONNECTION));
/** * Copies the content of {@code src} to a {@link ByteBuf} using {@link ByteBuf#writeBytes(byte[], int, int)}. * * @param src the source string to copy * @param srcIdx the starting offset of characters to copy * @param dst the destination buffer * @param length the number of characters to copy */ public static void copy(AsciiString src, int srcIdx, ByteBuf dst, int length) { if (isOutOfBounds(srcIdx, length, src.length())) { throw new IndexOutOfBoundsException("expected: " + "0 <= srcIdx(" + srcIdx + ") <= srcIdx + length(" + length + ") <= srcLen(" + src.length() + ')'); } checkNotNull(dst, "dst").writeBytes(src.array(), srcIdx + src.arrayOffset(), length); }
@Override protected void decode(ChannelHandlerContext ctx, HttpObject msg, List<Object> out) throws Exception { if (msg instanceof HttpResponse && ((HttpResponse) msg).status().code() == 100) { cleanup(); final HttpMessage message = (HttpMessage) msg; final HttpHeaders headers = message.headers(); String contentEncoding = headers.get(HttpHeaderNames.CONTENT_ENCODING); if (contentEncoding != null) { contentEncoding = contentEncoding.trim(); if (headers.contains(HttpHeaderNames.CONTENT_LENGTH)) { headers.remove(HttpHeaderNames.CONTENT_LENGTH); headers.set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED); if (HttpHeaderValues.IDENTITY.contentEquals(targetContentEncoding)) { } else if (message instanceof HttpResponse) { copy = new DefaultHttpResponse(r.protocolVersion(), r.status()); } else { throw new CodecException("Object of class " + message.getClass().getName() + " is not a HttpRequest or HttpResponse"); copy.headers().set(message.headers()); copy.setDecoderResult(message.decoderResult()); out.add(copy);
private HttpClientResponseImpl beginResponse(HttpResponse resp) { HttpVersion version; if (resp.protocolVersion() == io.netty.handler.codec.http.HttpVersion.HTTP_1_0) { version = io.vertx.core.http.HttpVersion.HTTP_1_0; } else { version = io.vertx.core.http.HttpVersion.HTTP_1_1; response = new HttpClientResponseImpl(request, version, this, resp.status().code(), resp.status().reasonPhrase(), new HeadersAdaptor(resp.headers())); if (conn.metrics != null) { conn.metrics.responseBegin(request.metric(), response); if (resp.status().code() != 100 && request.method() != io.vertx.core.http.HttpMethod.CONNECT) { String responseConnectionHeader = resp.headers().get(HttpHeaderNames.CONNECTION); io.netty.handler.codec.http.HttpVersion protocolVersion = resp.protocolVersion(); String requestConnectionHeader = request.headers().get(HttpHeaderNames.CONNECTION); if (HttpHeaderValues.CLOSE.contentEqualsIgnoreCase(responseConnectionHeader) || HttpHeaderValues.CLOSE.contentEqualsIgnoreCase(requestConnectionHeader)) { } else if (protocolVersion == io.netty.handler.codec.http.HttpVersion.HTTP_1_0 && !HttpHeaderValues.KEEP_ALIVE.contentEqualsIgnoreCase(responseConnectionHeader)) { String keepAliveHeader = resp.headers().get(HttpHeaderNames.KEEP_ALIVE); if (keepAliveHeader != null) { int timeout = HttpUtils.parseKeepAliveHeaderTimeout(keepAliveHeader);
final FullHttpResponse response = (FullHttpResponse) msg; httpReceive.setStatusCode(response.status().code()) .setStatusText(response.status().codeAsText().toString()); HttpHeaders headers = response.headers(); if (httpSend.getNeedReceiveHeaders() && !headers.isEmpty()) { final Map<String, String> responseHeaderMap = Maps.newHashMapWithExpectedSize(headers.size()); headers.forEach(one -> { responseHeaderMap.put(one.getKey(), one.getValue()); }); final String responseBody = response.content().toString(httpSend.getCharset()); .setErrMsg(cause.getMessage()) .setThrowable(cause); } else if (response.status().code() != 200) { httpReceive.setHaveError(true) .setErrMsg("本次请求响应码不是200,是" + response.status().code());
if (!SWITCHING_PROTOCOLS.equals(rep.status())) { response = (FullHttpResponse) msg; response.retain(); out.add(response); } else { CharSequence upgradeHeader = response.headers().get(HttpHeaderNames.UPGRADE); if (upgradeHeader != null && !AsciiString.contentEqualsIgnoreCase(upgradeCodec.protocol(), upgradeHeader)) { throw new IllegalStateException( "Switching Protocols response with unexpected UPGRADE protocol: " + upgradeHeader); response.release(); out.clear(); removeThisHandler(ctx);
/** * Returns {@code true} if the specified message contains an expect header specifying an expectation that is not * supported. Note that this method returns {@code false} if the expect header is not valid for the message * (e.g., the message is a response, or the version on the message is HTTP/1.0). * * @param message the message * @return {@code true} if and only if an expectation is present that is not supported */ static boolean isUnsupportedExpectation(HttpMessage message) { if (!isExpectHeaderValid(message)) { return false; } final String expectValue = message.headers().get(HttpHeaderNames.EXPECT); return expectValue != null && !HttpHeaderValues.CONTINUE.toString().equalsIgnoreCase(expectValue); }
private CharSequence readStringLiteral(ByteBuf in, int length, boolean huffmanEncoded) throws Http2Exception { if (huffmanEncoded) { return hpackHuffmanDecoder.decode(in, length); } byte[] buf = new byte[length]; in.readBytes(buf); return new AsciiString(buf, false); }