Skip to content

Commit 1d3c619

Browse files
committed
fix: refactor odata handler
1 parent 74f5679 commit 1d3c619

File tree

6 files changed

+207
-159
lines changed

6 files changed

+207
-159
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package io.neonbee.endpoint;
2+
3+
import static io.neonbee.data.DataAction.CREATE;
4+
import static io.neonbee.data.DataAction.DELETE;
5+
import static io.neonbee.data.DataAction.READ;
6+
import static io.neonbee.data.DataAction.UPDATE;
7+
import static io.vertx.core.http.HttpMethod.GET;
8+
import static io.vertx.core.http.HttpMethod.HEAD;
9+
import static io.vertx.core.http.HttpMethod.PATCH;
10+
import static io.vertx.core.http.HttpMethod.POST;
11+
import static io.vertx.core.http.HttpMethod.PUT;
12+
13+
import io.neonbee.data.DataAction;
14+
import io.vertx.core.http.HttpMethod;
15+
16+
/**
17+
* Utility class to map HTTP methods to DataActions.
18+
*/
19+
public class HttpMethodToDataActionMapper {
20+
21+
/**
22+
* Maps an HTTP method to a DataAction.
23+
*
24+
* @param method The HTTP method
25+
* @return The corresponding DataAction, or null if no mapping exists
26+
*/
27+
public static DataAction mapMethodToAction(HttpMethod method) {
28+
if (POST.equals(method)) {
29+
return CREATE;
30+
} else if (HEAD.equals(method) || GET.equals(method)) {
31+
return READ;
32+
} else if (PUT.equals(method) || PATCH.equals(method)) {
33+
return UPDATE;
34+
} else if (HttpMethod.DELETE.equals(method)) {
35+
return DELETE;
36+
} else {
37+
return null;
38+
}
39+
}
40+
}
Lines changed: 9 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,30 @@
11
package io.neonbee.endpoint.odatav4;
22

3-
import static io.neonbee.data.DataAction.CREATE;
4-
import static io.neonbee.data.DataAction.DELETE;
5-
import static io.neonbee.data.DataAction.READ;
6-
import static io.neonbee.data.DataAction.UPDATE;
7-
import static io.neonbee.endpoint.odatav4.ODataV4Endpoint.normalizeUri;
8-
import static io.vertx.core.http.HttpMethod.GET;
9-
import static io.vertx.core.http.HttpMethod.HEAD;
10-
import static io.vertx.core.http.HttpMethod.PATCH;
11-
import static io.vertx.core.http.HttpMethod.POST;
12-
import static io.vertx.core.http.HttpMethod.PUT;
13-
import static org.apache.olingo.server.core.ODataHandlerException.MessageKeys.AMBIGUOUS_XHTTP_METHOD;
14-
import static org.apache.olingo.server.core.ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED;
15-
import static org.apache.olingo.server.core.ODataHandlerException.MessageKeys.INVALID_HTTP_METHOD;
3+
import static io.neonbee.endpoint.HttpMethodToDataActionMapper.mapMethodToAction;
4+
import static io.neonbee.endpoint.odatav4.internal.olingo.OlingoEndpointHandler.getStatusCode;
5+
import static io.neonbee.endpoint.odatav4.internal.olingo.OlingoEndpointHandler.mapToODataRequest;
166

177
import java.util.List;
188
import java.util.Map;
9+
import java.util.Optional;
1910
import java.util.regex.Matcher;
2011
import java.util.regex.Pattern;
2112

2213
import org.apache.olingo.commons.api.edm.FullQualifiedName;
23-
import org.apache.olingo.commons.api.http.HttpHeader;
24-
import org.apache.olingo.commons.api.http.HttpMethod;
25-
import org.apache.olingo.server.api.ODataApplicationException;
26-
import org.apache.olingo.server.api.ODataLibraryException;
2714
import org.apache.olingo.server.api.ODataRequest;
2815
import org.apache.olingo.server.api.ServiceMetadata;
29-
import org.apache.olingo.server.core.ODataHandlerException;
30-
31-
import com.google.common.annotations.VisibleForTesting;
3216

3317
import io.neonbee.data.DataAction;
3418
import io.neonbee.data.DataContext;
3519
import io.neonbee.data.DataQuery;
3620
import io.neonbee.data.DataRequest;
3721
import io.neonbee.data.internal.DataContextImpl;
3822
import io.neonbee.entity.AbstractEntityVerticle;
39-
import io.neonbee.internal.helper.BufferHelper;
4023
import io.vertx.core.Future;
4124
import io.vertx.core.Handler;
4225
import io.vertx.core.buffer.Buffer;
43-
import io.vertx.core.http.HttpServerRequest;
4426
import io.vertx.core.http.HttpServerResponse;
27+
import io.vertx.ext.web.RequestBody;
4528
import io.vertx.ext.web.RoutingContext;
4629

4730
public final class ODataProxyEndpointHandler implements Handler<RoutingContext> {
@@ -61,20 +44,6 @@ public ODataProxyEndpointHandler(ServiceMetadata serviceMetadata) {
6144
this.serviceMetadata = serviceMetadata;
6245
}
6346

64-
private DataAction mapMethodToAction(io.vertx.core.http.HttpMethod method) {
65-
if (POST.equals(method)) {
66-
return CREATE;
67-
} else if (HEAD.equals(method) || GET.equals(method)) {
68-
return READ;
69-
} else if (PUT.equals(method) || PATCH.equals(method)) {
70-
return UPDATE;
71-
} else if (io.vertx.core.http.HttpMethod.DELETE.equals(method)) {
72-
return DELETE;
73-
} else {
74-
return null;
75-
}
76-
}
77-
7847
@SuppressWarnings("unused") // normale Java-Warnung
7948
@Override
8049
public void handle(RoutingContext routingContext) {
@@ -88,7 +57,10 @@ public void handle(RoutingContext routingContext) {
8857
serviceMetadata.getEdm().getEntityContainer().getNamespace());
8958

9059
DataAction action = mapMethodToAction(routingContext.request().method());
91-
dataQuery = odataRequestToQuery(odataRequest, action, routingContext.body().buffer());
60+
Buffer body = Optional.ofNullable(routingContext.body())
61+
.map(RequestBody::buffer)
62+
.orElse(Buffer.buffer());
63+
dataQuery = odataRequestToQuery(odataRequest, action, body);
9264
fullQualifiedName = getFullQualifiedName(odataRequest);
9365
} catch (Exception cause) {
9466
routingContext.fail(getStatusCode(cause), cause);
@@ -163,98 +135,4 @@ private static DataQuery odataRequestToQuery(ODataRequest request, DataAction ac
163135
return new DataQuery(action, uriPath, stringListMap, request.getAllHeaders(), body).addHeader("X-HTTP-Method",
164136
request.getMethod().name());
165137
}
166-
167-
private static int getStatusCode(Throwable throwable) {
168-
return throwable instanceof ODataApplicationException odae ? odae.getStatusCode() : -1;
169-
}
170-
171-
/**
172-
* Maps a Vert.x RoutingContext into a new ODataRequest.
173-
*
174-
* @param routingContext the context for the handling of the HTTP request
175-
* @param schemaNamespace the name of the service namespace
176-
* @return A new ODataRequest
177-
* @throws ODataLibraryException ODataLibraryException
178-
*/
179-
@VisibleForTesting
180-
static ODataRequest mapToODataRequest(RoutingContext routingContext, String schemaNamespace)
181-
throws ODataLibraryException {
182-
HttpServerRequest request = routingContext.request();
183-
184-
ODataRequest odataRequest = new ODataRequest();
185-
odataRequest.setProtocol(request.scheme());
186-
odataRequest.setMethod(mapODataRequestMethod(request));
187-
odataRequest.setBody(new BufferHelper.BufferInputStream(routingContext.body().buffer()));
188-
for (String header : request.headers().names()) {
189-
odataRequest.addHeader(header, request.headers().getAll(header));
190-
}
191-
192-
/* @formatter:off *//*
193-
* The OData request is awaiting the following fields:
194-
*
195-
* rawRequestUri = http://localhost/odata/sys1/Employees?$format=json,$top=10
196-
* rawBaseUri = http://localhost/odata/
197-
* rawServiceResolutionUri = sys1
198-
* rawODataPath = /Employees
199-
* rawQueryPath = $format=json,$top=10
200-
*
201-
* We can map these from the normalizedUri
202-
*//* @formatter:on */
203-
204-
ODataV4Endpoint.NormalizedUri normalizedUri = normalizeUri(routingContext, schemaNamespace);
205-
odataRequest.setRawRequestUri(normalizedUri.requestUri);
206-
odataRequest.setRawBaseUri(normalizedUri.baseUri);
207-
odataRequest.setRawServiceResolutionUri(normalizedUri.schemaNamespace);
208-
odataRequest.setRawODataPath(normalizedUri.resourcePath);
209-
odataRequest.setRawQueryPath(normalizedUri.requestQuery);
210-
211-
return odataRequest;
212-
}
213-
214-
/**
215-
* Maps the Vert.x HttpServerRequest method to a valid OData HttpMethod, considering the request method, the
216-
* X-HTTP-Method and X-HTTP-Method-Override headers.
217-
*
218-
* @param request The incoming HttpRequest to map
219-
* @return A valid OData HttpMethod
220-
* @throws ODataLibraryException ODataLibraryException
221-
*/
222-
@VisibleForTesting
223-
@SuppressWarnings("checkstyle:LocalVariableName")
224-
static org.apache.olingo.commons.api.http.HttpMethod mapODataRequestMethod(HttpServerRequest request)
225-
throws ODataLibraryException {
226-
org.apache.olingo.commons.api.http.HttpMethod odataRequestMethod;
227-
String rawMethod = request.method().name();
228-
try {
229-
odataRequestMethod = org.apache.olingo.commons.api.http.HttpMethod.valueOf(rawMethod);
230-
} catch (IllegalArgumentException e) {
231-
throw new ODataHandlerException("HTTP method not allowed" + rawMethod, e, HTTP_METHOD_NOT_ALLOWED,
232-
rawMethod);
233-
}
234-
235-
try { // in case it is a POST request, also consider the X-Http-Method and X-Http-Method-Override headers
236-
if (odataRequestMethod == org.apache.olingo.commons.api.http.HttpMethod.POST) {
237-
String xHttpMethod = request.getHeader(HttpHeader.X_HTTP_METHOD);
238-
String xHttpMethodOverride = request.getHeader(HttpHeader.X_HTTP_METHOD_OVERRIDE);
239-
240-
if ((xHttpMethod == null) && (xHttpMethodOverride == null)) {
241-
return odataRequestMethod;
242-
} else if (xHttpMethod == null) {
243-
return org.apache.olingo.commons.api.http.HttpMethod.valueOf(xHttpMethodOverride);
244-
} else if (xHttpMethodOverride == null) {
245-
return org.apache.olingo.commons.api.http.HttpMethod.valueOf(xHttpMethod);
246-
} else {
247-
if (!xHttpMethod.equalsIgnoreCase(xHttpMethodOverride)) {
248-
throw new ODataHandlerException("Ambiguous X-HTTP-Methods", AMBIGUOUS_XHTTP_METHOD, xHttpMethod,
249-
xHttpMethodOverride);
250-
}
251-
return HttpMethod.valueOf(xHttpMethod);
252-
}
253-
} else {
254-
return odataRequestMethod;
255-
}
256-
} catch (IllegalArgumentException e) {
257-
throw new ODataHandlerException("Invalid HTTP method" + rawMethod, e, INVALID_HTTP_METHOD, rawMethod);
258-
}
259-
}
260138
}

src/main/java/io/neonbee/endpoint/odatav4/internal/olingo/OlingoEndpointHandler.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,14 @@ public void handle(RoutingContext routingContext) {
105105
});
106106
}
107107

108-
private static int getStatusCode(Throwable throwable) {
109-
return throwable instanceof ODataApplicationException ? ((ODataApplicationException) throwable).getStatusCode()
110-
: -1;
108+
/**
109+
* Returns the status code of the ODataApplicationException or -1 if the throwable is of another type.
110+
*
111+
* @param throwable The throwable to get the status code from
112+
* @return The status code or -1
113+
*/
114+
public static int getStatusCode(Throwable throwable) {
115+
return throwable instanceof ODataApplicationException odae ? odae.getStatusCode() : -1;
111116
}
112117

113118
/**
@@ -118,8 +123,7 @@ private static int getStatusCode(Throwable throwable) {
118123
* @return A new ODataRequest
119124
* @throws ODataLibraryException ODataLibraryException
120125
*/
121-
@VisibleForTesting
122-
static ODataRequest mapToODataRequest(RoutingContext routingContext, String schemaNamespace)
126+
public static ODataRequest mapToODataRequest(RoutingContext routingContext, String schemaNamespace)
123127
throws ODataLibraryException {
124128
HttpServerRequest request = routingContext.request();
125129

src/main/java/io/neonbee/endpoint/raw/RawEndpoint.java

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package io.neonbee.endpoint.raw;
22

33
import static io.neonbee.data.DataAction.CREATE;
4-
import static io.neonbee.data.DataAction.DELETE;
5-
import static io.neonbee.data.DataAction.READ;
6-
import static io.neonbee.data.DataAction.UPDATE;
74
import static io.neonbee.data.DataException.FAILURE_CODE_NO_HANDLERS;
85
import static io.neonbee.data.DataException.FAILURE_CODE_TIMEOUT;
96
import static io.neonbee.data.DataVerticle.requestData;
107
import static io.neonbee.endpoint.Endpoint.createRouter;
8+
import static io.neonbee.endpoint.HttpMethodToDataActionMapper.mapMethodToAction;
119
import static io.neonbee.internal.helper.CollectionHelper.multiMapToMap;
1210
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
1311
import static io.netty.handler.codec.http.HttpResponseStatus.CREATED;
@@ -16,11 +14,6 @@
1614
import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
1715
import static io.netty.handler.codec.http.HttpResponseStatus.NO_CONTENT;
1816
import static io.vertx.core.Future.succeededFuture;
19-
import static io.vertx.core.http.HttpMethod.GET;
20-
import static io.vertx.core.http.HttpMethod.HEAD;
21-
import static io.vertx.core.http.HttpMethod.PATCH;
22-
import static io.vertx.core.http.HttpMethod.POST;
23-
import static io.vertx.core.http.HttpMethod.PUT;
2417
import static io.vertx.ext.web.impl.Utils.pathOffset;
2518
import static java.lang.Character.isUpperCase;
2619

@@ -45,7 +38,6 @@
4538
import io.vertx.core.Handler;
4639
import io.vertx.core.Vertx;
4740
import io.vertx.core.buffer.Buffer;
48-
import io.vertx.core.http.HttpMethod;
4941
import io.vertx.core.http.HttpServerRequest;
5042
import io.vertx.core.http.HttpServerResponse;
5143
import io.vertx.core.json.Json;
@@ -232,19 +224,5 @@ static String determineQualifiedName(RoutingContext routingContext) {
232224

233225
return null;
234226
}
235-
236-
private DataAction mapMethodToAction(HttpMethod method) {
237-
if (POST.equals(method)) {
238-
return CREATE;
239-
} else if (HEAD.equals(method) || GET.equals(method)) {
240-
return READ;
241-
} else if (PUT.equals(method) || PATCH.equals(method)) {
242-
return UPDATE;
243-
} else if (HttpMethod.DELETE.equals(method)) {
244-
return DELETE;
245-
} else {
246-
return null;
247-
}
248-
}
249227
}
250228
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.neonbee.endpoint;
2+
3+
import static io.neonbee.endpoint.HttpMethodToDataActionMapper.mapMethodToAction;
4+
import static org.junit.jupiter.api.Assertions.*;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
class HttpMethodToDataActionMapperTest {
9+
10+
@Test
11+
void testMapMethodToAction() {
12+
assertEquals(io.neonbee.data.DataAction.CREATE, mapMethodToAction(io.vertx.core.http.HttpMethod.POST));
13+
assertEquals(io.neonbee.data.DataAction.READ, mapMethodToAction(io.vertx.core.http.HttpMethod.GET));
14+
assertEquals(io.neonbee.data.DataAction.READ, mapMethodToAction(io.vertx.core.http.HttpMethod.HEAD));
15+
assertEquals(io.neonbee.data.DataAction.UPDATE, mapMethodToAction(io.vertx.core.http.HttpMethod.PUT));
16+
assertEquals(io.neonbee.data.DataAction.UPDATE, mapMethodToAction(io.vertx.core.http.HttpMethod.PATCH));
17+
assertEquals(io.neonbee.data.DataAction.DELETE, mapMethodToAction(io.vertx.core.http.HttpMethod.DELETE));
18+
assertNull(mapMethodToAction(io.vertx.core.http.HttpMethod.OPTIONS));
19+
}
20+
}

0 commit comments

Comments
 (0)