Skip to content

Commit

Permalink
OPTIONS request support
Browse files Browse the repository at this point in the history
  • Loading branch information
oxsean committed Jul 25, 2024
1 parent b5bd138 commit 6dd81e6
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@

public enum HttpMethods {
GET,
HEAD,
POST,
PUT,
PATCH,
DELETE,
HEAD,
OPTIONS,
PATCH,
TRACE;

public static final byte[][] HTTP_METHODS_BYTES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@
String[] consumes() default {};

String[] produces() default {};

boolean disabled() default false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ public PathCondition getPathCondition() {
return pathCondition;
}

public MethodsCondition getMethodsCondition() {
return methodsCondition;
}

public ProducesCondition getProducesCondition() {
return producesCondition;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
import org.apache.dubbo.remoting.http12.HttpMethods;
import org.apache.dubbo.remoting.http12.HttpRequest;
import org.apache.dubbo.remoting.http12.HttpResponse;
import org.apache.dubbo.remoting.http12.HttpResult;
import org.apache.dubbo.remoting.http12.HttpStatus;
import org.apache.dubbo.remoting.http12.exception.HttpResultPayloadException;
import org.apache.dubbo.remoting.http12.message.MediaType;
import org.apache.dubbo.remoting.http12.message.codec.CodecUtils;
import org.apache.dubbo.rpc.model.FrameworkModel;
Expand All @@ -35,11 +38,14 @@
import org.apache.dubbo.rpc.protocol.tri.rest.argument.CompositeArgumentResolver;
import org.apache.dubbo.rpc.protocol.tri.rest.argument.GeneralTypeConverter;
import org.apache.dubbo.rpc.protocol.tri.rest.argument.TypeConverter;
import org.apache.dubbo.rpc.protocol.tri.rest.mapping.condition.MethodsCondition;
import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.HandlerMeta;
import org.apache.dubbo.rpc.protocol.tri.rest.util.RequestUtils;
import org.apache.dubbo.rpc.protocol.tri.route.RequestHandler;
import org.apache.dubbo.rpc.protocol.tri.route.RequestHandlerMapping;

import java.util.Set;

@Activate(order = -2000)
public final class RestRequestHandlerMapping implements RequestHandlerMapping {

Expand Down Expand Up @@ -71,6 +77,11 @@ public RequestHandler getRequestHandler(URL url, HttpRequest request, HttpRespon
return null;
}

String method = request.method();
if (HttpMethods.OPTIONS.name().equals(method)) {
handleOptionsRequest(request);
}

String requestMediaType = request.mediaType();
String responseMediaType = contentNegotiator.negotiate(request);
if (responseMediaType != null) {
Expand All @@ -90,7 +101,7 @@ public RequestHandler getRequestHandler(URL url, HttpRequest request, HttpRespon
typeConverter,
codecUtils.determineHttpMessageEncoder(url, frameworkModel, responseMediaType));

if (HttpMethods.supportBody(request.method()) && !RequestUtils.isFormOrMultiPart(request)) {
if (HttpMethods.supportBody(method) && !RequestUtils.isFormOrMultiPart(request)) {
if (StringUtils.isEmpty(requestMediaType)) {
requestMediaType = responseMediaType;
}
Expand All @@ -111,6 +122,25 @@ public RequestHandler getRequestHandler(URL url, HttpRequest request, HttpRespon
return handler;
}

private static void handleOptionsRequest(HttpRequest request) {
RequestMapping mapping = request.attribute(RestConstants.MAPPING_ATTRIBUTE);
MethodsCondition condition = mapping.getMethodsCondition();
if (condition == null) {
throw new HttpResultPayloadException(HttpResult.builder()
.status(HttpStatus.NO_CONTENT)
.header("allow", "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS")
.build());
}
Set<String> methods = condition.getMethods();
if (methods.size() == 1 && methods.contains(HttpMethods.OPTIONS.name())) {
return;
}
throw new HttpResultPayloadException(HttpResult.builder()
.status(HttpStatus.NO_CONTENT)
.header("allow", StringUtils.join(methods, ","))
.build());
}

@Override
public String getType() {
return TripleConstant.TRIPLE_HANDLER_TYPE_REST;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,22 @@ public MethodsCondition combine(MethodsCondition other) {
@Override
public MethodsCondition match(HttpRequest request) {
String method = request.method();

if (OPTIONS.name().equals(method)) {
if (request.hasHeader("origin") && request.hasHeader("access-control-request-method")) {
return new MethodsCondition(OPTIONS.name());
} else {
return this;
}
}

if (methods.contains(method)) {
return new MethodsCondition(method);
}

if (HEAD.name().equals(method) && methods.contains(GET.name())) {
return new MethodsCondition(GET.name());
}
if (OPTIONS.name().equals(method)
&& request.hasHeader("origin")
&& request.hasHeader("access-control-request-method")) {
return new MethodsCondition(OPTIONS.name());
}

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.remoting.http12.rest.Mapping;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.protocol.tri.rest.cors.CorsUtils;
import org.apache.dubbo.rpc.protocol.tri.rest.mapping.RequestMapping;
Expand Down Expand Up @@ -51,12 +52,13 @@ public RestToolKit getRestToolKit() {

@Override
public boolean accept(MethodMeta methodMeta) {
return methodMeta.getMethodDescriptor() != null || methodMeta.findAnnotation(Annotations.Mapping) != null;
AnnotationMeta<Mapping> mapping = methodMeta.findAnnotation(Mapping.class);
return mapping != null ? !mapping.getAnnotation().disabled() : methodMeta.getMethodDescriptor() != null;
}

@Override
public RequestMapping resolve(ServiceMeta serviceMeta) {
AnnotationMeta<?> mapping = serviceMeta.findAnnotation(Annotations.Mapping);
AnnotationMeta<Mapping> mapping = serviceMeta.findAnnotation(Mapping.class);
Builder builder = builder(mapping);

String[] paths = getPaths(mapping);
Expand All @@ -74,7 +76,11 @@ public RequestMapping resolve(ServiceMeta serviceMeta) {
@Override
public RequestMapping resolve(MethodMeta methodMeta) {
Method method = methodMeta.getMethod();
AnnotationMeta<?> mapping = methodMeta.findAnnotation(Annotations.Mapping);
AnnotationMeta<Mapping> mapping = methodMeta.findAnnotation(Mapping.class);
if (mapping != null && mapping.getAnnotation().disabled()) {
return null;
}

Builder builder = builder(mapping);

String[] paths = getPaths(mapping);
Expand Down

0 comments on commit 6dd81e6

Please sign in to comment.