/** * Copyright 2007-2015, Kaazing Corporation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kaazing.specification.http.rfc7230; import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.rules.RuleChain.outerRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.DisableOnDebug; import org.junit.rules.TestRule; import org.junit.rules.Timeout; import org.kaazing.k3po.junit.annotation.Specification; import org.kaazing.k3po.junit.rules.K3poRule; /** * Test to validate behavior as specified in <a href="https://tools.ietf.org/html/rfc7230#section-6">RFC 7230 section 6: * Connection Management</a>. */ public class ConnectionManagementIT { private final K3poRule k3po = new K3poRule().setScriptRoot("org/kaazing/specification/http/rfc7230/connection.management"); private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); @Rule public final TestRule chain = outerRule(k3po).around(timeout); /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.1">RFC 7230 section 6.1: Connection</a>. * * In order to avoid confusing downstream recipients, a proxy or gateway MUST remove or replace any received * connection options before forwarding the message. * * @throws Exception when K3PO is not started */ @Test @Specification({ "intermediary.must.remove.connection.header.on.forward.request/client", "intermediary.must.remove.connection.header.on.forward.request/intermediary", "intermediary.must.remove.connection.header.on.forward.request/backend" }) public void intermediaryMustRemoveConnectionHeaderOnForwardRequest() throws Exception { k3po.finish(); } @Test @Specification({ "reverse.proxy.connection.established/client", "reverse.proxy.connection.established/proxy", "reverse.proxy.connection.established/server" }) public void reverseProxyConnectionEstablished() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.1">RFC 7230 section 6.1: Connection</a>. * * The "close" connection option is defined for a sender to signal that this connection will be closed after * completion of the response. For example, * * Connection: close * * in either the request or the response header fields indicates that the sender is going to close the connection * after the current request/response is complete (Section 6.6). * * @throws Exception when K3PO is not started */ @Test @Specification({ "client.must.close.connection.after.request.with.connection.close/request", "client.must.close.connection.after.request.with.connection.close/response" }) public void clientMustCloseConnectionAfterRequestWithConnectionClose() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.1">RFC 7230 section 6.1: Connection</a>. * * The "close" connection option is defined for a sender to signal that this connection will be closed after * completion of the response. For example, * * Connection: close * * in either the request or the response header fields indicates that the sender is going to close the connection * after the current request/response is complete (Section 6.6). * * @throws Exception when K3PO is not started */ @Test @Specification({ "server.must.close.connection.after.response.with.connection.close/request", "server.must.close.connection.after.response.with.connection.close/response" }) public void serverMustCloseConnectionAfterResponseWithConnectionClose() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.3">RFC 7230 section 6.3: Persistence</a>. * * HTTP implementations SHOULD support persistent connections. * * @throws Exception when K3PO is not started */ @Test @Specification({ "connections.should.persist.by.default/client", "connections.should.persist.by.default/backend" }) public void connectionsShouldPersistByDefault() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.3.1">RFC 7230 section 6.3.1: Retrying Requests</a>. * * A proxy MUST NOT automatically retry non-idempotent requests. * * @throws Exception when K3PO is not started */ @Test @Specification({ "proxy.must.not.retry.non.idempotent.requests/client", "proxy.must.not.retry.non.idempotent.requests/proxy", "proxy.must.not.retry.non.idempotent.requests/server" }) public void proxyMustNotRetryNonIdempotentRequests() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.3.2">RFC 7230 section 6.3.2: Pipelining</a>. * <p> * A client can send multiple requests with out getting a response, but a server must send responses back it order * </p> * @throws Exception when K3PO is not started */ @Test @Specification({ "server.should.accept.http.pipelining/request", "server.should.accept.http.pipelining/response" }) public void serverShouldAcceptHttpPipelining() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.3.2">RFC 7230 section 6.3.2: Pipelining</a>. * <p> * If client is pipelining requests and the connection closes from underneath the client should retry requests, and * the first retry must not be pipelined with other requests * </p> * * @throws Exception when K3PO is not started */ @Test @Specification({ "client.with.pipelining.must.not.retry.pipelining.immediately.after.failure/request", "client.with.pipelining.must.not.retry.pipelining.immediately.after.failure/response" }) public void clientWithPipeliningMustNotRetryPipeliningImmediatelyAfterFailure() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.6">RFC 7230 section 6.6: Tear-down</a>. <blockquote> A * server that receives a "close" connection option MUST initiate a close of the connection (see below) after it * sends the final response to the request that contained "close". The server SHOULD send a "close" connection * option in its final response on that connection. The server MUST NOT process any further requests received on * that connection. </blockquote> * * @throws Exception when K3PO is not started */ @Test @Specification({ "server.must.close.its.half.of.connection.after.sending.response.if.it.receives.a.close/request", "server.must.close.its.half.of.connection.after.sending.response.if.it.receives.a.close/response" }) public void serverMustCloseItsHalfOfConnectionAfterSendingResponseIfItReceivesAClose() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.6">RFC 7230 section 6.6: Tear-down</a>. <blockquote> A * client that receives a "close" connection option MUST cease sending requests on that connection and close the * connection after reading the response message containing the "close"; if additional pipelined requests had been * sent on the connection, the client SHOULD NOT assume that they will be processed by the server. </blockquote> * * @throws Exception when K3PO is not started */ @Test @Specification({ "client.must.not.reuse.tcp.connection.when.receives.connection.close/request", "client.must.not.reuse.tcp.connection.when.receives.connection.close/response" }) public void clientMustNotReuseTcpConnectionWhenReceivesConnectionClose() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.7">RFC 7230 section 6.7: Upgrade</a>. <blockquote> A * server that sends a 101 (Switching Protocols) response MUST send an Upgrade header field to indicate the new * protocol(s) to which the connection is being switched; if multiple protocol layers are being switched, the sender * MUST list the protocols in layer-ascending order. </blockquote> * * @throws Exception when K3PO is not started */ @Test @Specification({ "server.getting.upgrade.request.must.respond.with.upgrade.header/request", "server.getting.upgrade.request.must.respond.with.upgrade.header/response" }) public void serverGettingUpgradeRequestMustRespondWithUpgradeHeader() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.7">RFC 7230 section 6.7: Upgrade</a>. <blockquote> A * server that sends a 426 (Upgrade Required) response MUST send an Upgrade header field to indicate the acceptable * protocols, in order of descending preference. </blockquote> * * @throws Exception when K3PO is not started */ @Test @Specification({ "server.that.sends.upgrade.required.must.include.upgrade.header/request", "server.that.sends.upgrade.required.must.include.upgrade.header/response" }) public void serverThatSendsUpgradeRequiredMustIncludeUpgradeHeader() throws Exception { k3po.finish(); } /** * See <a href="https://tools.ietf.org/html/rfc7230#section-6.7">RFC 7230 section 6.7: Upgrade</a>. * * <blockquote> if the Upgrade header field is received in a GET request and the server decides to switch protocols, * it first responds with a 101 (Switching Protocols) message in HTTP/1.1 and then immediately follows that with the * new protocol's equivalent of a response to a GET on the target resource. </blockquote> * * @throws Exception when K3PO is not started */ @Test @Specification({ "server.that.is.upgrading.must.send.a.101.response/request", "server.that.is.upgrading.must.send.a.101.response/response" }) public void serverThatIsUpgradingMustSendA100Response() throws Exception { k3po.finish(); } }