Merge pull request #3247 from eclipse-vertx/http-method-interface

HttpMethod is an interface
This commit is contained in:
Paulo Lopes
2020-01-10 16:17:52 +01:00
committed by GitHub
21 changed files with 346 additions and 191 deletions

View File

@@ -87,30 +87,6 @@ ID 14, bad timestamp
+++
|===
[[HttpMethod]]
== HttpMethod
++++
Represents an HTTP method
++++
'''
[cols=">25%,75%"]
[frame="topbot"]
|===
^|Name | Description
|[[OPTIONS]]`OPTIONS`|-
|[[GET]]`GET`|-
|[[HEAD]]`HEAD`|-
|[[POST]]`POST`|-
|[[PUT]]`PUT`|-
|[[DELETE]]`DELETE`|-
|[[TRACE]]`TRACE`|-
|[[CONNECT]]`CONNECT`|-
|[[PATCH]]`PATCH`|-
|[[OTHER]]`OTHER`|-
|===
[[HttpVersion]]
== HttpVersion

View File

@@ -382,11 +382,6 @@ this will get called every time a custom frame arrives. Here's an example:
HTTP/2 frames are not subject to flow control - the frame handler will be called immediatly when a
custom frame is received whether the request is paused or is not
==== Non standard HTTP methods
The {@link io.vertx.core.http.HttpMethod#OTHER} HTTP method is used for non standard methods, in this case
{@link io.vertx.core.http.HttpServerRequest#rawMethod()} returns the HTTP method as sent by the client.
=== Sending back responses
The server response object is an instance of {@link io.vertx.core.http.HttpServerResponse} and is obtained from the
@@ -887,12 +882,6 @@ You can also write headers using {@link io.vertx.core.http.HttpClientRequest#put
If you wish to write headers to the request you must do so before any part of the request body is written.
==== Non standard HTTP methods
The {@link io.vertx.core.http.HttpMethod#OTHER} HTTP method is used for non standard methods, when this method
is used, {@link io.vertx.core.http.HttpClientRequest#setRawMethod(java.lang.String)} must be used to
set the raw method to send to the server.
==== Ending HTTP requests
Once you have finished with the HTTP request you must end it with one of the {@link io.vertx.core.http.HttpClientRequest#end}

View File

@@ -99,20 +99,6 @@ public interface HttpClientRequest extends WriteStream<Buffer>, Future<HttpClien
*/
HttpMethod method();
/**
* @return the raw value of the method this request sends
*/
String getRawMethod();
/**
* Set the value the method to send when the method {@link HttpMethod#OTHER} is used.
*
* @param method the raw method
* @return a reference to this, so the API can be used fluently
*/
@Fluent
HttpClientRequest setRawMethod(String method);
/**
* @return the absolute URI corresponding to the the HTTP request
*/

View File

@@ -12,13 +12,109 @@
package io.vertx.core.http;
import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.http.impl.HttpMethodImpl;
import java.util.Objects;
/**
* Represents an HTTP method
* Represents an HTTP method.
*
* @author <a href="http://tfox.org">Tim Fox</a>
*/
@VertxGen
public enum HttpMethod {
OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, PATCH, OTHER
public interface HttpMethod {
/**
* The {@code OPTIONS} method, this instance is interned and uniquely used.
*/
HttpMethod OPTIONS = new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.OPTIONS);
/**
* The {@code GET} method, this instance is interned and uniquely used.
*/
HttpMethod GET = new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.GET);
/**
* The {@code HEAD} method, this instance is interned and uniquely used.
*/
HttpMethod HEAD = new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.HEAD);
/**
* The {@code POST} method, this instance is interned and uniquely used.
*/
HttpMethod POST = new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.POST);
/**
* The {@code PUT} method, this instance is interned and uniquely used.
*/
HttpMethod PUT = new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.PUT);
/**
* The {@code DELETE} method, this instance is interned and uniquely used.
*/
HttpMethod DELETE = new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.DELETE);
/**
* The {@code TRACE} method, this instance is interned and uniquely used.
*/
HttpMethod TRACE = new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.TRACE);
/**
* The {@code CONNECT} method, this instance is interned and uniquely used.
*/
HttpMethod CONNECT = new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.CONNECT);
/**
* The {@code PATCH} method, this instance is interned and uniquely used.
*/
HttpMethod PATCH = new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.PATCH);
/**
* @return the method name
*/
String name();
/**
* @return the same value than {@link #name()}
*/
String toString();
/**
* Lookup the {@code HttpMethod} value for the specified {@code value}.
* <br/>
* The predefined method constants {@link #GET}, {@link #POST}, {@link #PUT}, {@link #HEAD}, {@link #OPTIONS},
* {@link #DELETE}, {@link #TRACE}, {@link #CONNECT} and {@link #PATCH} are interned and will be returned
* when case sensitively matching their string value (i.e {@code "GET"}, etc...)
* <br/>
* Otherwise a new instance is returned.
*
* @param value the value
* @return the {@code HttpMethod} instance for the specified string {@code value}
* @throws IllegalArgumentException when the value is incorrect, the value is empty or contains an invalid char
*/
static HttpMethod valueOf(String value) {
Objects.requireNonNull(value, "value");
switch (value) {
case "OPTIONS":
return OPTIONS;
case "GET":
return GET;
case "HEAD":
return HEAD;
case "POST":
return POST;
case "PUT":
return PUT;
case "DELETE":
return DELETE;
case "TRACE":
return TRACE;
case "CONNECT":
return CONNECT;
case "PATCH":
return PATCH;
default:
return new HttpMethodImpl(io.netty.handler.codec.http.HttpMethod.valueOf(value));
}
}
}

View File

@@ -72,11 +72,6 @@ public interface HttpServerRequest extends ReadStream<Buffer> {
*/
HttpMethod method();
/**
* @return the HTTP method as sent by the client
*/
String rawMethod();
/**
* @return true if this {@link io.vertx.core.net.NetSocket} is encrypted via SSL/TLS
*/

View File

@@ -117,12 +117,11 @@ class Http1xClientConnection extends Http1xConnectionBase<WebSocketImpl> impleme
private HttpRequest createRequest(
HttpMethod method,
String rawMethod,
String uri,
MultiMap headerMap,
String hostHeader,
boolean chunked) {
DefaultHttpRequest request = new DefaultHttpRequest(HttpUtils.toNettyHttpVersion(version), HttpUtils.toNettyHttpMethod(method, rawMethod), uri, false);
DefaultHttpRequest request = new DefaultHttpRequest(HttpUtils.toNettyHttpVersion(version), HttpMethodImpl.toNetty(method), uri, false);
HttpHeaders headers = request.headers();
if (headerMap != null) {
for (Map.Entry<String, String> header : headerMap) {
@@ -313,8 +312,8 @@ class Http1xClientConnection extends Http1xConnectionBase<WebSocketImpl> impleme
}
@Override
public void writeHead(HttpMethod method, String rawMethod, String uri, MultiMap headers, String hostHeader, boolean chunked, ByteBuf buf, boolean end, StreamPriority priority, Handler<AsyncResult<Void>> handler) {
HttpRequest request = conn.createRequest(method, rawMethod, uri, headers, hostHeader, chunked);
public void writeHead(HttpMethod method, String uri, MultiMap headers, String hostHeader, boolean chunked, ByteBuf buf, boolean end, StreamPriority priority, Handler<AsyncResult<Void>> handler) {
HttpRequest request = conn.createRequest(method, uri, headers, hostHeader, chunked);
if (end) {
if (buf != null) {
request = new AssembledFullHttpRequest(request, buf);

View File

@@ -65,7 +65,6 @@ public class Http1xServerRequest implements HttpServerRequest {
private HttpRequest request;
private io.vertx.core.http.HttpVersion version;
private io.vertx.core.http.HttpMethod method;
private String rawMethod;
private String uri;
private String path;
private String query;
@@ -208,24 +207,11 @@ public class Http1xServerRequest implements HttpServerRequest {
@Override
public io.vertx.core.http.HttpMethod method() {
if (method == null) {
String sMethod = request.method().toString();
try {
method = io.vertx.core.http.HttpMethod.valueOf(sMethod);
} catch (IllegalArgumentException e) {
method = io.vertx.core.http.HttpMethod.OTHER;
}
method = io.vertx.core.http.impl.HttpMethodImpl.fromNetty(request.method());
}
return method;
}
@Override
public String rawMethod() {
if (rawMethod == null) {
rawMethod = request.method().toString();
}
return rawMethod;
}
@Override
public String uri() {
if (uri == null) {

View File

@@ -17,7 +17,6 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http2.DefaultHttp2Headers;
import io.netty.handler.codec.http2.Http2Connection;
import io.netty.handler.codec.http2.Http2Error;
import io.netty.handler.codec.http2.Http2Exception;
import io.netty.handler.codec.http2.Http2Headers;
@@ -166,7 +165,7 @@ class Http2ClientConnection extends Http2ConnectionBase implements HttpClientCon
Handler<HttpClientRequest> pushHandler = stream.pushHandler();
if (pushHandler != null) {
String rawMethod = headers.method().toString();
HttpMethod method = HttpUtils.toVertxMethod(rawMethod);
HttpMethod method = HttpMethod.valueOf(rawMethod);
String uri = headers.path().toString();
String authority = headers.authority() != null ? headers.authority().toString() : null;
MultiMap headersMap = new Http2HeadersAdaptor(headers);
@@ -181,7 +180,7 @@ class Http2ClientConnection extends Http2ConnectionBase implements HttpClientCon
host = authority.substring(0, pos);
port = Integer.parseInt(authority.substring(pos + 1));
}
HttpClientRequestPushPromise pushReq = new HttpClientRequestPushPromise(this, client, isSsl(), method, rawMethod, uri, host, port, headersMap);
HttpClientRequestPushPromise pushReq = new HttpClientRequestPushPromise(this, client, isSsl(), method, uri, host, port, headersMap);
pushReq.getStream().init(promisedStream);
if (metrics != null) {
((Stream)pushReq.getStream()).metric = metrics.responsePushed(queueMetric, metric(), localAddress(), remoteAddress(), pushReq);
@@ -455,9 +454,9 @@ class Http2ClientConnection extends Http2ConnectionBase implements HttpClientCon
}
@Override
public void writeHead(HttpMethod method, String rawMethod, String uri, MultiMap headers, String hostHeader, boolean chunked, ByteBuf content, boolean end, StreamPriority priority, Handler<AsyncResult<Void>> handler) {
public void writeHead(HttpMethod method, String uri, MultiMap headers, String hostHeader, boolean chunked, ByteBuf content, boolean end, StreamPriority priority, Handler<AsyncResult<Void>> handler) {
Http2Headers h = new DefaultHttp2Headers();
h.method(method != HttpMethod.OTHER ? method.name() : rawMethod);
h.method(method.name());
boolean e;
if (method == HttpMethod.CONNECT) {
if (hostHeader == null) {

View File

@@ -132,11 +132,7 @@ public class Http2ServerConnection extends Http2ConnectionBase implements HttpSe
private synchronized void doSendPush(int streamId, String host, HttpMethod method, MultiMap headers, String path, StreamPriority streamPriority, Promise<HttpServerResponse> promise) {
Http2Headers headers_ = new DefaultHttp2Headers();
if (method == HttpMethod.OTHER) {
throw new IllegalArgumentException("Cannot push HttpMethod.OTHER");
} else {
headers_.method(method.name());
}
headers_.method(method.name());
headers_.path(path);
headers_.scheme(isSsl() ? "https" : "http");
if (host != null) {

View File

@@ -419,7 +419,7 @@ public class Http2ServerRequestImpl extends Http2ServerStream implements HttpSer
if (postRequestDecoder == null) {
String contentType = headersMap.get(HttpHeaderNames.CONTENT_TYPE);
if (contentType != null) {
io.netty.handler.codec.http.HttpMethod method = io.netty.handler.codec.http.HttpMethod.valueOf(rawMethod);
io.netty.handler.codec.http.HttpMethod method = HttpMethodImpl.toNetty(this.method);
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) &&

View File

@@ -27,7 +27,6 @@ import static io.vertx.core.spi.metrics.Metrics.METRICS_ENABLED;
abstract class Http2ServerStream extends VertxHttp2Stream<Http2ServerConnection> {
protected final Http2Headers headers;
protected final String rawMethod;
protected final HttpMethod method;
protected final String uri;
protected final String host;
@@ -43,7 +42,6 @@ abstract class Http2ServerStream extends VertxHttp2Stream<Http2ServerConnection>
this.headers = null;
this.method = method;
this.rawMethod = method.name();
this.uri = uri;
this.host = null;
this.response = new Http2ServerResponseImpl(conn, this, true, contentEncoding, null);
@@ -61,8 +59,7 @@ abstract class Http2ServerStream extends VertxHttp2Stream<Http2ServerConnection>
this.headers = headers;
this.host = host;
this.uri = headers.get(":path") != null ? headers.get(":path").toString() : null;
this.rawMethod = headers.get(":method") != null ? headers.get(":method").toString() : null;
this.method = HttpUtils.toVertxMethod(rawMethod);
this.method = headers.get(":method") != null ? HttpMethod.valueOf(headers.get(":method").toString()) : null;
this.response = new Http2ServerResponseImpl(conn, this, false, contentEncoding, host);
}
@@ -115,10 +112,6 @@ abstract class Http2ServerStream extends VertxHttp2Stream<Http2ServerConnection>
return method;
}
public String rawMethod() {
return rawMethod;
}
@Override
void handleClose() {
super.handleClose();

View File

@@ -103,7 +103,6 @@ public class Http2UpgradedClientConnection implements HttpClientConnection {
*/
@Override
public void writeHead(HttpMethod method,
String rawMethod,
String uri,
MultiMap headers,
String hostHeader,
@@ -171,7 +170,7 @@ public class Http2UpgradedClientConnection implements HttpClientConnection {
HttpClientUpgradeHandler upgradeHandler = new HttpClientUpgradeHandler(httpCodec, upgradeCodec, 65536);
pipeline.addAfter("codec", null, new UpgradeRequestHandler());
pipeline.addAfter("codec", null, upgradeHandler);
stream.writeHead(method, rawMethod, uri, headers, hostHeader, chunked, buf, end, priority, listener);
stream.writeHead(method, uri, headers, hostHeader, chunked, buf, end, priority, listener);
}
@Override

View File

@@ -14,7 +14,6 @@ package io.vertx.core.http.impl;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.CompositeByteBuf;
import io.netty.buffer.Unpooled;
import io.vertx.codegen.annotations.Nullable;
import io.vertx.core.*;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClientRequest;
@@ -57,7 +56,6 @@ public class HttpClientRequestImpl extends HttpClientRequestBase implements Http
private final Future<Void> endFuture;
private boolean chunked;
private String hostHeader;
private String rawMethod;
private Handler<Void> continueHandler;
private Handler<Void> drainHandler;
private Handler<HttpClientRequest> pushHandler;
@@ -151,17 +149,6 @@ public class HttpClientRequestImpl extends HttpClientRequestBase implements Http
return chunked;
}
@Override
public synchronized String getRawMethod() {
return rawMethod;
}
@Override
public synchronized HttpClientRequest setRawMethod(String method) {
this.rawMethod = method;
return this;
}
@Override
public synchronized HttpClientRequest setHost(String host) {
this.hostHeader = host;
@@ -403,11 +390,6 @@ public class HttpClientRequestImpl extends HttpClientRequestBase implements Http
private synchronized void connect(Handler<AsyncResult<HttpVersion>> headersHandler) {
if (!connecting) {
if (method == HttpMethod.OTHER && rawMethod == null) {
throw new IllegalStateException("You must provide a rawMethod when using an HttpMethod.OTHER method");
}
SocketAddress peerAddress;
if (hostHeader != null) {
int idx = hostHeader.lastIndexOf(':');
@@ -478,7 +460,7 @@ public class HttpClientRequestImpl extends HttpClientRequestBase implements Http
}
};
}
stream.writeHead(method, rawMethod, uri, headers, hostHeader(), chunked, pending, ended, priority, handler);
stream.writeHead(method, uri, headers, hostHeader(), chunked, pending, ended, priority, handler);
if (ended) {
tryComplete();
}

View File

@@ -27,7 +27,6 @@ class HttpClientRequestPushPromise extends HttpClientRequestBase {
private final Http2ClientConnection conn;
private final Http2ClientConnection.StreamImpl stream;
private final String rawMethod;
private final MultiMap headers;
public HttpClientRequestPushPromise(
@@ -35,7 +34,6 @@ class HttpClientRequestPushPromise extends HttpClientRequestBase {
HttpClientImpl client,
boolean ssl,
HttpMethod method,
String rawMethod,
String uri,
String host,
int port,
@@ -43,7 +41,6 @@ class HttpClientRequestPushPromise extends HttpClientRequestBase {
super(client, conn.getContext(), ssl, method, SocketAddress.inetSocketAddress(port, host), host, port, uri);
this.conn = conn;
this.stream = new Http2ClientConnection.StreamImpl(conn, conn.getContext(), this, null);
this.rawMethod = rawMethod;
this.headers = headers;
}
@@ -82,16 +79,6 @@ class HttpClientRequestPushPromise extends HttpClientRequestBase {
return method;
}
@Override
public String getRawMethod() {
return rawMethod;
}
@Override
public HttpClientRequest setRawMethod(String method) {
throw new IllegalStateException();
}
@Override
public String uri() {
return uri;

View File

@@ -12,17 +12,14 @@
package io.vertx.core.http.impl;
import io.netty.buffer.ByteBuf;
import io.netty.util.concurrent.FutureListener;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpConnection;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpVersion;
import io.vertx.core.http.StreamPriority;
import io.vertx.core.impl.ContextInternal;
import io.vertx.core.net.NetSocket;
/**
* @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
@@ -45,7 +42,7 @@ public interface HttpClientStream {
HttpConnection connection();
ContextInternal getContext();
void writeHead(HttpMethod method, String rawMethod, String uri, MultiMap headers, String hostHeader, boolean chunked, ByteBuf buf, boolean end, StreamPriority priority, Handler<AsyncResult<Void>> listener);
void writeHead(HttpMethod method, String uri, MultiMap headers, String hostHeader, boolean chunked, ByteBuf buf, boolean end, StreamPriority priority, Handler<AsyncResult<Void>> listener);
void writeBuffer(ByteBuf buf, boolean end, Handler<AsyncResult<Void>> listener);
void writeFrame(int type, int flags, ByteBuf payload);

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package io.vertx.core.http.impl;
import io.vertx.core.http.HttpMethod;
import java.util.Objects;
public class HttpMethodImpl implements HttpMethod {
public static io.netty.handler.codec.http.HttpMethod toNetty(HttpMethod method) {
if (method instanceof HttpMethodImpl) {
return ((HttpMethodImpl) method).nettyMethod;
} else {
return io.netty.handler.codec.http.HttpMethod.valueOf(method.name());
}
}
/**
* Lookup the {@code HttpMethod} value for the specified {@code nettyMethod}.
* <br/>
* The predefined method constants {@link #GET}, {@link #POST}, {@link #PUT}, {@link #HEAD}, {@link #OPTIONS},
* {@link #DELETE}, {@link #TRACE}, {@link #CONNECT} and {@link #PATCH} are interned and will be returned
* when case sensitively matching their string value (i.e {@code "GET"}, etc...)
* <br/>
* Otherwise a new instance is returned.
*
* @param method the netty method
* @return the {@code HttpMethod} instance for the specified netty {@code method}
*/
public static HttpMethod fromNetty(io.netty.handler.codec.http.HttpMethod method) {
// Fast path
if (method == io.netty.handler.codec.http.HttpMethod.GET) {
return GET;
} else if (method == io.netty.handler.codec.http.HttpMethod.POST) {
return POST;
} else {
// Keep method small
return _fromNetty(method);
}
}
private static HttpMethod _fromNetty(io.netty.handler.codec.http.HttpMethod sMethod) {
switch (sMethod.name()) {
case "OPTIONS":
return OPTIONS;
case "HEAD":
return HEAD;
case "PUT":
return PUT;
case "DELETE":
return DELETE;
case "TRACE":
return TRACE;
case "CONNECT":
return CONNECT;
case "PATCH":
return PATCH;
default:
return new HttpMethodImpl(sMethod);
}
}
private final io.netty.handler.codec.http.HttpMethod nettyMethod;
public HttpMethodImpl(io.netty.handler.codec.http.HttpMethod nettyMethod) {
this.nettyMethod = nettyMethod;
}
@Override
public String name() {
return nettyMethod.name();
}
@Override
public int hashCode() {
return nettyMethod.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof HttpMethod) {
HttpMethod that = (HttpMethod) obj;
return Objects.equals(name(), that.name());
}
return false;
}
@Override
public String toString() {
return name();
}
}

View File

@@ -667,41 +667,6 @@ public final class HttpUtils {
return null;
}
static HttpMethod toNettyHttpMethod(io.vertx.core.http.HttpMethod method, String rawMethod) {
switch (method) {
case CONNECT: {
return HttpMethod.CONNECT;
}
case GET: {
return HttpMethod.GET;
}
case PUT: {
return HttpMethod.PUT;
}
case POST: {
return HttpMethod.POST;
}
case DELETE: {
return HttpMethod.DELETE;
}
case HEAD: {
return HttpMethod.HEAD;
}
case OPTIONS: {
return HttpMethod.OPTIONS;
}
case TRACE: {
return HttpMethod.TRACE;
}
case PATCH: {
return HttpMethod.PATCH;
}
default: {
return HttpMethod.valueOf(rawMethod);
}
}
}
static HttpVersion toNettyHttpVersion(io.vertx.core.http.HttpVersion version) {
switch (version) {
case HTTP_1_0: {
@@ -716,11 +681,7 @@ public final class HttpUtils {
}
static io.vertx.core.http.HttpMethod toVertxMethod(String method) {
try {
return io.vertx.core.http.HttpMethod.valueOf(method);
} catch (IllegalArgumentException e) {
return io.vertx.core.http.HttpMethod.OTHER;
}
return io.vertx.core.http.HttpMethod.valueOf(method);
}
private static final AsciiString TIMEOUT_EQ = AsciiString.of("timeout=");

View File

@@ -3826,7 +3826,7 @@ public class Http1xTest extends HttpTest {
@Test
public void testPartialH2CAmbiguousRequest() throws Exception {
server.requestHandler(req -> {
assertEquals("POST", req.rawMethod());
assertEquals(HttpMethod.POST, req.method());
testComplete();
});
Buffer fullRequest = Buffer.buffer("POST /whatever HTTP/1.1\r\n\r\n");

View File

@@ -0,0 +1,121 @@
/*
* Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package io.vertx.core.http;
import io.vertx.core.http.impl.HttpMethodImpl;
import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
public class HttpMethodTest {
@Test
public void testConstantNames() {
assertEquals("GET", HttpMethod.GET.name());
assertEquals("POST", HttpMethod.POST.name());
assertEquals("PUT", HttpMethod.PUT.name());
assertEquals("HEAD", HttpMethod.HEAD.name());
assertEquals("CONNECT", HttpMethod.CONNECT.name());
assertEquals("DELETE", HttpMethod.DELETE.name());
assertEquals("OPTIONS", HttpMethod.OPTIONS.name());
assertEquals("PATCH", HttpMethod.PATCH.name());
assertEquals("TRACE", HttpMethod.TRACE.name());
}
@Test
public void testConstants() {
for (HttpMethod method : Arrays.asList(
HttpMethod.GET,
HttpMethod.POST,
HttpMethod.HEAD,
HttpMethod.PUT,
HttpMethod.CONNECT,
HttpMethod.DELETE,
HttpMethod.OPTIONS,
HttpMethod.PATCH,
HttpMethod.TRACE
)) {
assertSame(HttpMethod.valueOf(method.name()), method);
assertSame(method.name(), method.toString());
}
}
@Test
public void testInvalidValueOf() {
for (String method : Arrays.asList("", " ")) {
try {
HttpMethod.valueOf(method);
fail();
} catch (IllegalArgumentException ignore) {
}
}
try {
HttpMethod.valueOf(null);
fail();
} catch (NullPointerException ignore) {
}
}
@Test
public void testValueOf() {
HttpMethod m1 = HttpMethod.valueOf("foo");
HttpMethod m2 = HttpMethod.valueOf("foo");
assertEquals("foo", m1.name());
assertEquals("foo", m1.toString());
assertNotSame(m1, m2);
assertEquals(m1.hashCode(), m2.hashCode());
assertEquals(m1, m2);
}
@Test
public void testCaseSensitive() {
HttpMethod m1 = HttpMethod.valueOf("Foo");
HttpMethod m2 = HttpMethod.valueOf("foo");
assertEquals("Foo", m1.name());
assertEquals("Foo", m1.toString());
assertNotSame(m1, m2);
assertNotEquals(m1.hashCode(), m2.hashCode());
assertNotEquals(m1, m2);
}
@Test
public void testNettyInterop() {
assertSame(HttpMethodImpl.toNetty(HttpMethod.GET), io.netty.handler.codec.http.HttpMethod.GET);
assertSame(HttpMethodImpl.toNetty(HttpMethod.POST), io.netty.handler.codec.http.HttpMethod.POST);
assertSame(HttpMethodImpl.toNetty(HttpMethod.PUT), io.netty.handler.codec.http.HttpMethod.PUT);
assertSame(HttpMethodImpl.toNetty(HttpMethod.HEAD), io.netty.handler.codec.http.HttpMethod.HEAD);
assertSame(HttpMethodImpl.toNetty(HttpMethod.CONNECT), io.netty.handler.codec.http.HttpMethod.CONNECT);
assertSame(HttpMethodImpl.toNetty(HttpMethod.DELETE), io.netty.handler.codec.http.HttpMethod.DELETE);
assertSame(HttpMethodImpl.toNetty(HttpMethod.OPTIONS), io.netty.handler.codec.http.HttpMethod.OPTIONS);
assertSame(HttpMethodImpl.toNetty(HttpMethod.PATCH), io.netty.handler.codec.http.HttpMethod.PATCH);
assertSame(HttpMethodImpl.toNetty(HttpMethod.TRACE), io.netty.handler.codec.http.HttpMethod.TRACE);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.GET), HttpMethod.GET);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.valueOf("GET")), HttpMethod.GET);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.POST), HttpMethod.POST);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.valueOf("POST")), HttpMethod.POST);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.PUT), HttpMethod.PUT);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.valueOf("PUT")), HttpMethod.PUT);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.HEAD), HttpMethod.HEAD);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.CONNECT), HttpMethod.CONNECT);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.DELETE), HttpMethod.DELETE);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.OPTIONS), HttpMethod.OPTIONS);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.PATCH), HttpMethod.PATCH);
assertSame(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.TRACE), HttpMethod.TRACE);
assertEquals(HttpMethodImpl.toNetty(HttpMethod.valueOf("foo")).name(), "foo");
assertEquals(HttpMethodImpl.fromNetty(io.netty.handler.codec.http.HttpMethod.valueOf("foo")).name(), "foo");
}
}

View File

@@ -3494,26 +3494,15 @@ public abstract class HttpTest extends HttpTestBase {
await();
}
@Test
public void testOtherMethodWithRawMethod() {
try {
client.request(HttpMethod.OTHER, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
}).end();
fail();
} catch (IllegalStateException expected) {
}
}
@Test
public void testOtherMethodRequest() {
server.requestHandler(r -> {
assertEquals(HttpMethod.OTHER, r.method());
assertEquals("COPY", r.rawMethod());
assertEquals("COPY", r.method().name());
r.response().end();
}).listen(testAddress, onSuccess(s -> {
client.request(HttpMethod.OTHER, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onSuccess(resp -> {
client.request(HttpMethod.valueOf("COPY"), testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onSuccess(resp -> {
testComplete();
})).setRawMethod("COPY").end();
})).end();
}));
await();
}

View File

@@ -12,7 +12,7 @@ package io.vertx.core.json;
import com.fasterxml.jackson.core.type.TypeReference;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.WebsocketVersion;
import io.vertx.core.impl.Utils;
import io.vertx.core.json.jackson.DatabindCodec;
import io.vertx.core.json.jackson.JacksonCodec;
@@ -401,9 +401,9 @@ public class JsonCodecTest {
@Test
public void testEnumValue() {
// just a random enum
Buffer json = mapper.toBuffer(HttpMethod.CONNECT);
Buffer json = mapper.toBuffer(WebsocketVersion.V13);
assertNotNull(json);
assertEquals("\"CONNECT\"", json.toString());
assertEquals("\"V13\"", json.toString());
}
@Test