This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.3
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.3 by this push:
new 70f6e03636 Returns a matching http status code based on the rest
mappings (#14714)
70f6e03636 is described below
commit 70f6e036363ac5f66e13dbf706c41287bc34ac73
Author: Sean Yang <[email protected]>
AuthorDate: Fri Sep 27 16:14:57 2024 +0800
Returns a matching http status code based on the rest mappings (#14714)
---
.../mapping/DefaultRequestMappingRegistry.java | 56 ++++++++++++++++++++--
.../protocol/tri/rest/mapping/RequestMapping.java | 16 +++++--
.../tri/rest/support/basic/RestProtocolTest.groovy | 22 ++++++++-
.../rpc/protocol/tri/rest/service/DemoService.java | 4 ++
.../protocol/tri/rest/service/DemoServiceImpl.java | 5 ++
5 files changed, 93 insertions(+), 10 deletions(-)
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java
index f219b85403..8ec6bf4716 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.config.nested.RestConfig;
import org.apache.dubbo.remoting.http12.HttpRequest;
+import org.apache.dubbo.remoting.http12.exception.HttpStatusException;
import org.apache.dubbo.remoting.http12.message.MethodMetadata;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.model.FrameworkModel;
@@ -45,6 +46,7 @@ import org.apache.dubbo.rpc.protocol.tri.rest.util.PathUtils;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -205,7 +207,8 @@ public final class DefaultRequestMappingRegistry implements
RequestMappingRegist
KeyString path = new KeyString(stringPath,
restConfig.getCaseSensitiveMatchOrDefault());
List<Candidate> candidates = new ArrayList<>();
- tryMatch(request, path, candidates);
+ List<RequestMapping> partialMatches = new LinkedList<>();
+ tryMatch(request, path, candidates, partialMatches);
if (candidates.isEmpty()) {
int end = path.length();
@@ -213,7 +216,7 @@ public final class DefaultRequestMappingRegistry implements
RequestMappingRegist
if (restConfig.getTrailingSlashMatchOrDefault()) {
if (path.charAt(end - 1) == '/') {
end--;
- tryMatch(request, path.subSequence(0, end), candidates);
+ tryMatch(request, path.subSequence(0, end), candidates,
partialMatches);
}
}
@@ -225,7 +228,7 @@ public final class DefaultRequestMappingRegistry implements
RequestMappingRegist
}
if (ch == '.' &&
restConfig.getSuffixPatternMatchOrDefault()) {
if (contentNegotiator.supportExtension(path.toString(i
+ 1, end))) {
- tryMatch(request, path.subSequence(0, i),
candidates);
+ tryMatch(request, path.subSequence(0, i),
candidates, partialMatches);
if (!candidates.isEmpty()) {
break;
}
@@ -234,7 +237,7 @@ public final class DefaultRequestMappingRegistry implements
RequestMappingRegist
}
if (ch == '~') {
request.setAttribute(RestConstants.SIG_ATTRIBUTE,
path.toString(i + 1, end));
- tryMatch(request, path.subSequence(0, i), candidates);
+ tryMatch(request, path.subSequence(0, i), candidates,
partialMatches);
if (!candidates.isEmpty()) {
break;
}
@@ -245,6 +248,7 @@ public final class DefaultRequestMappingRegistry implements
RequestMappingRegist
int size = candidates.size();
if (size == 0) {
+ handleNoMatch(request, partialMatches);
return null;
}
if (size > 1) {
@@ -289,7 +293,8 @@ public final class DefaultRequestMappingRegistry implements
RequestMappingRegist
return handler;
}
- private void tryMatch(HttpRequest request, KeyString path, List<Candidate>
candidates) {
+ private void tryMatch(
+ HttpRequest request, KeyString path, List<Candidate> candidates,
List<RequestMapping> partialMatches) {
List<Match<Registration>> matches = new ArrayList<>();
lock.readLock().lock();
@@ -315,6 +320,47 @@ public final class DefaultRequestMappingRegistry
implements RequestMappingRegist
candidates.add(candidate);
}
}
+ if (candidates.isEmpty()) {
+ for (int i = 0; i < size; i++) {
+ partialMatches.add(matches.get(i).getValue().mapping);
+ }
+ }
+ }
+
+ private void handleNoMatch(HttpRequest request, List<RequestMapping>
partialMatches) {
+ if (partialMatches.isEmpty()) {
+ return;
+ }
+ boolean methodsMismatch = true;
+ boolean consumesMismatch = true;
+ boolean producesMismatch = true;
+ boolean paramsMismatch = true;
+ for (RequestMapping mapping : partialMatches) {
+ if (methodsMismatch) {
+ methodsMismatch = !mapping.matchMethod(request.method());
+ }
+ if (consumesMismatch) {
+ consumesMismatch = !mapping.matchConsumes(request);
+ }
+ if (producesMismatch) {
+ producesMismatch = !mapping.matchProduces(request);
+ }
+ if (paramsMismatch) {
+ paramsMismatch = !mapping.matchParams(request);
+ }
+ }
+ if (methodsMismatch) {
+ throw new HttpStatusException(405, "Request method '" +
request.method() + "' not supported");
+ }
+ if (consumesMismatch) {
+ throw new HttpStatusException(415, "Content type '" +
request.contentType() + "' not supported");
+ }
+ if (producesMismatch) {
+ throw new HttpStatusException(406, "Could not find acceptable
representation");
+ }
+ if (paramsMismatch) {
+ throw new HttpStatusException(400, "Unsatisfied query parameter
conditions");
+ }
}
@Override
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java
index 1ea35e0e82..4264594e01 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java
@@ -119,6 +119,18 @@ public final class RequestMapping implements
Condition<RequestMapping, HttpReque
return methodsCondition == null ||
methodsCondition.getMethods().contains(method);
}
+ public boolean matchParams(HttpRequest request) {
+ return paramsCondition == null || paramsCondition.match(request) !=
null;
+ }
+
+ public boolean matchConsumes(HttpRequest request) {
+ return consumesCondition == null || consumesCondition.match(request)
!= null;
+ }
+
+ public boolean matchProduces(HttpRequest request) {
+ return producesCondition == null || producesCondition.match(request)
!= null;
+ }
+
@Override
public RequestMapping match(HttpRequest request) {
return doMatch(request, null);
@@ -196,10 +208,6 @@ public final class RequestMapping implements
Condition<RequestMapping, HttpReque
return name;
}
- public String getSig() {
- return sig;
- }
-
public PathCondition getPathCondition() {
return pathCondition;
}
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/test/groovy/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/RestProtocolTest.groovy
b/dubbo-rpc/dubbo-rpc-triple/src/test/groovy/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/RestProtocolTest.groovy
index 4b3547d238..4a2da172b9 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/test/groovy/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/RestProtocolTest.groovy
+++
b/dubbo-rpc/dubbo-rpc-triple/src/test/groovy/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/RestProtocolTest.groovy
@@ -241,7 +241,27 @@ class RestProtocolTest extends BaseServiceTest {
path | accept | output
'/produceTest?name=world' | '' | 'world'
'/produceTest?name=world' | 'text/plain' | 'world'
- '/produceTest?name=world' | 'application/json' |
'{"message":"Invoker not found","status":"404"}'
+ '/produceTest?name=world' | 'application/json' |
'{"message":"Could not find acceptable representation","status":"406"}'
+ }
+
+ def "mismatch test"() {
+ given:
+ def request = new TestRequest(
+ method: method,
+ path: path,
+ contentType: contentType,
+ accept: accept
+ )
+ expect:
+ runner.run(request, String.class) == output
+ where:
+ method | path | contentType | accept
| output
+ 'POST' | '/mismatchTest?name=world' | 'text/plain' |
'text/plain' | 'world'
+ 'POST' | '/mismatchTest1' | 'text/plain' |
'text/plain' | '{"message":"Invoker not found","status":"404"}'
+ 'GET' | '/mismatchTest' | '' | ''
| '{"message":"Request method \'GET\' not supported","status":"405"}'
+ 'POST' | '/mismatchTest' | 'application/json' |
'text/plain' | '{"message":"Content type \'application/json\' not
supported","status":"415"}'
+ 'POST' | '/mismatchTest' | 'text/plain' |
'application/json' | '{"message":"Could not find acceptable
representation","status":"406"}'
+ 'POST' | '/mismatchTest?name=earth' | 'text/plain' |
'text/plain' | '{"message":"Unsatisfied query parameter
conditions","status":"400"}'
}
}
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/service/DemoService.java
b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/service/DemoService.java
index 8469f14080..b9597f057a 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/service/DemoService.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/service/DemoService.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.rpc.protocol.tri.rest.service;
import org.apache.dubbo.common.stream.StreamObserver;
+import org.apache.dubbo.remoting.http12.HttpMethods;
import org.apache.dubbo.remoting.http12.rest.Mapping;
import org.apache.dubbo.remoting.http12.rest.Param;
import org.apache.dubbo.rpc.protocol.tri.rest.service.User.Group;
@@ -71,4 +72,7 @@ public interface DemoService {
@Mapping(produces = "text/plain")
String produceTest(String name);
+
+ @Mapping(method = HttpMethods.POST, consumes = "text/plain", produces =
"text/plain", params = "name=world")
+ String mismatchTest(String name);
}
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/service/DemoServiceImpl.java
b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/service/DemoServiceImpl.java
index 767cd7e684..b5575fdbae 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/service/DemoServiceImpl.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/service/DemoServiceImpl.java
@@ -148,4 +148,9 @@ public class DemoServiceImpl implements DemoService {
public String produceTest(String name) {
return name;
}
+
+ @Override
+ public String mismatchTest(String name) {
+ return name;
+ }
}