use of io.servicetalk.http.api.HttpRequestMethod in project servicetalk by apple.
the class HttpRequestDecoder method decodeHttpMethod.
private static HttpRequestMethod decodeHttpMethod(final ByteBuf buffer, final int start, final int length) {
final String methodName = buffer.toString(start, length, US_ASCII);
final HttpRequestMethod method = HttpRequestMethod.of(methodName);
if (method != null) {
return method;
}
try {
return HttpRequestMethod.of(methodName, NONE);
} catch (IllegalArgumentException cause) {
throw new StacklessDecoderException("Invalid start-line: HTTP request method must follow a valid token format", cause);
}
}
use of io.servicetalk.http.api.HttpRequestMethod in project servicetalk by apple.
the class H2ToStH1ServerDuplexHandler method channelRead.
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof Http2HeadersFrame) {
Http2HeadersFrame headersFrame = (Http2HeadersFrame) msg;
Http2Headers h2Headers = headersFrame.headers();
final HttpRequestMethod httpMethod;
final String path;
if (!readHeaders) {
closeHandler.protocolPayloadBeginInbound(ctx);
CharSequence method = h2Headers.getAndRemove(METHOD.value());
CharSequence pathSequence = h2Headers.getAndRemove(PATH.value());
if (pathSequence == null || method == null) {
throw new IllegalArgumentException("a request must have " + METHOD + " and " + PATH + " headers");
}
path = pathSequence.toString();
httpMethod = sequenceToHttpRequestMethod(method);
readHeaders = true;
} else {
httpMethod = null;
path = null;
}
if (headersFrame.isEndStream()) {
if (httpMethod != null) {
fireFullRequest(ctx, h2Headers, httpMethod, path);
} else {
ctx.fireChannelRead(h2TrailersToH1TrailersServer(h2Headers));
}
closeHandler.protocolPayloadEndInbound(ctx);
} else if (httpMethod == null) {
throw new IllegalArgumentException("a request must have " + METHOD + " and " + PATH + " headers");
} else {
ctx.fireChannelRead(newRequestMetaData(HTTP_2_0, httpMethod, path, h2HeadersToH1HeadersServer(h2Headers, httpMethod, false)));
}
} else if (msg instanceof Http2DataFrame) {
readDataFrame(ctx, msg);
} else {
ctx.fireChannelRead(msg);
}
}
use of io.servicetalk.http.api.HttpRequestMethod in project servicetalk by apple.
the class H2ToStH1ServerDuplexHandler method sequenceToHttpRequestMethod.
private static HttpRequestMethod sequenceToHttpRequestMethod(CharSequence sequence) {
String strMethod = sequence.toString();
HttpRequestMethod reqMethod = HttpRequestMethod.of(strMethod);
return reqMethod != null ? reqMethod : HttpRequestMethod.of(strMethod, NONE);
}
use of io.servicetalk.http.api.HttpRequestMethod in project servicetalk by apple.
the class HttpResponseEncoder method isContentAlwaysEmpty.
@Override
protected boolean isContentAlwaysEmpty(HttpResponseMetaData msg) {
// Peek from the queue here as sanitizeHeadersBeforeEncode is responsible for poll.
final HttpRequestMethod method = methodQueue.peek();
if (HEAD.equals(method)) {
return true;
}
// Correctly handle special cases as stated in:
// https://tools.ietf.org/html/rfc7230#section-3.3.3
final HttpResponseStatus status = msg.status();
if (status.statusClass() == INFORMATIONAL_1XX) {
if (status.code() == SWITCHING_PROTOCOLS.code()) {
// See https://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-1.2
return msg.headers().contains(SEC_WEBSOCKET_VERSION);
}
return true;
}
return status.code() == NO_CONTENT.code() || status.code() == NOT_MODIFIED.code();
}
use of io.servicetalk.http.api.HttpRequestMethod in project servicetalk by apple.
the class HttpResponseEncoder method sanitizeHeadersBeforeEncode.
@Override
protected void sanitizeHeadersBeforeEncode(HttpResponseMetaData msg, boolean isAlwaysEmpty) {
// This method has side effects on the methodQueue for the following reasons:
// - createMessage will not necessarily fire a message up the pipeline.
// - the trigger points on the queue are currently symmetric for the request/response decoder and
// request/response encoder. We may use header information on the response decoder side, and the queue
// interaction is conditional (1xx responses don't touch the queue).
// - unit tests exist which verify these side effects occur, so if behavior of the internal classes changes the
// unit test should catch it.
// - this is the rough equivalent of what is done in Netty in terms of sequencing. Instead of trying to
// iterate a decoded list it makes some assumptions about the base class ordering of events.
HttpRequestMethod method = methodQueue.poll();
HttpHeaders headers = msg.headers();
if (isAlwaysEmpty) {
final HttpResponseStatus status = msg.status();
if (status.statusClass() == INFORMATIONAL_1XX || status.code() == NO_CONTENT.code()) {
// Stripping Content-Length:
// See https://tools.ietf.org/html/rfc7230#section-3.3.2
headers.remove(CONTENT_LENGTH);
// Stripping Transfer-Encoding:
// See https://tools.ietf.org/html/rfc7230#section-3.3.1
headers.remove(TRANSFER_ENCODING);
}
} else if (CONNECT.equals(method) && msg.status().statusClass() == SUCCESSFUL_2XX) {
// Stripping Content-Length:
// See https://tools.ietf.org/html/rfc7230#section-3.3.2
headers.remove(CONTENT_LENGTH);
// Stripping Transfer-Encoding:
// See https://tools.ietf.org/html/rfc7230#section-3.3.1
headers.remove(TRANSFER_ENCODING);
}
}
Aggregations